# Bacula(R) is a registered trademark of Kern Sibbald.
import logging
+import time
from baculak8s.entities.file_info import DIRECTORY
from baculak8s.entities.plugin_object import PluginObject
self._handle_error(response['error'])
return False
return True
-
+
def process_pvcdata(self, namespace, pvcdata, backup_with_pod = False):
status = None
vsnapshot = None
+ is_cloned = False
+ cloned_pvc_name = None
# Detect if pvcdata is compatible with snapshots
if not backup_with_pod:
+ logging.debug('Backup without pod')
vsnapshot, pvcdata = self.handle_create_vsnapshot_backup(namespace, pvcdata.get('name'))
-
- logging.debug('Process_pvcdata (Backup_job): {} {}'.format(vsnapshot, pvcdata))
+ logging.debug('Process_pvcdata (Backup_job): {} --- {}'.format(vsnapshot, pvcdata))
+ # if vsnapshot is None:
+ # self._io.send_info(CHANGE_BACKUP_MODE_FOR_INCOMPATIBLITY_PVC.format(pvcdata.get('name')))
+ # cloned_pvc_name = self.create_pvcclone(namespace, pvcdata.get('name'))
+ # cloned_pvc = self._plugin.get_pvcdata_namespaced(namespace, cloned_pvc_name)
+ # logging.debug('Cloned pvc fi:{}'.format(cloned_pvc.get('fi')))
+ # cloned_pvc.get('fi').set_name(pvcdata.get('fi').name)
+ # pvcdata = cloned_pvc
+ # is_cloned = True
if self.prepare_bacula_pod(pvcdata, namespace=namespace, mode='backup'):
super()._estimate_file(pvcdata) # here to send info about pvcdata to plugin
status = self.__backup_pvcdata(namespace=namespace)
# Both prepare_bacula_pod fails or not, we must remove snapshot and pvc
if not backup_with_pod:
self.handle_delete_vsnapshot_backup(namespace, vsnapshot, pvcdata)
+ if is_cloned:
+ self.delete_pvcclone(namespace, cloned_pvc_name)
return status
def handle_pod_container_exec_command(self, corev1api, namespace, pod, runjobparam, failonerror=False):
return False
if backupmode == BaculaBackupMode.Snapshot:
+ logging.debug('Snapshot mode chosen')
vsnapshot, pvc_from_vsnap = self.handle_create_vsnapshot_backup(namespace, pvcname)
logging.debug("The vsnapshot created from pvc {} is: {}".format(pvcname, vsnapshot))
logging.debug("The pvc create from vsnapshot {} is: {}. FI: {}".format(vsnapshot, pvc_from_vsnap, pvc_from_vsnap.get('fi')))
Manage operations to create snapshot and new pvc from this snapshot to do backup.
"""
pvc = self._plugin.get_pvcdata_namespaced(namespace, pvcname)
+
# Check if pvc is compatible with vsnapshot
if not self._plugin.check_pvc_compatiblity_with_vsnapshot(namespace, pvc.get('name')):
+ logging.debug('The pvc is not compatible with vsnapshots. Name:{}'.format(pvc.get('name')))
return None, pvc
logging.debug('Origin pvcdata FileInfo:\n{}'.format(pvc.get('fi')))
self._io.send_info(VSNAPSHOT_BACKUP_COMPATIBLE_INFO.format(pvc.get('name')))
dict: updated pvc data list as dictionary
"""
# here we collect node_names for proper backup pod deployment
- logging.debug('Init PVCDATALIST: {}'.format(pvcdatalist))
+ logging.debug('Init PVCDATALIST')
pods = pods_namespaced_specs(corev1api, namespace=namespace)
- logging.debug('Get pods:{}'.format(pods))
+ # logging.debug('Get pods:{}'.format(pods))
for pod in pods:
if pod.spec is not None and pod.spec.volumes is not None:
for vol in pod.spec.volumes:
logging.debug('[CUSTOM] Enter in pvcdatalist')
logging.debug('Pvcf: {} -- Node_name: {}'.format(pvcf, pod.spec.node_name))
pvcdatalist[pvcf]['node_name'] = pod.spec.node_name
- logging.debug('END PVCDATALIST: {}'.format(pvcdatalist))
+ logging.debug('END PVCDATALIST')
return pvcdatalist
import logging
import pathlib
+from kubernetes import client
K8SOBJ_SNAPSHOT_GROUP = 'snapshot.storage.k8s.io'
K8SOBJ_SNAPSHOT_VERSION = 'v1'
def volumesnapshotclass_list_all(custom_api, filter_names=None):
vol_snap_list = {}
+ # volume_snapshot_classes = []
volume_snapshot_classes = custom_api.list_cluster_custom_object(K8SOBJ_SNAPSHOT_GROUP, K8SOBJ_SNAPSHOT_VERSION, K8SOBJ_SNAPSHOT_PLURAL, watch=False)
logging.debug("Volume snapshot classes:{}".format(volume_snapshot_classes))
- for vol_snap in volume_snapshot_classes.get('items'):
- if filter_names is not None and len(filter_names) > 0:
- logging.debug("filter_names-glob-for: {}".format(vol_snap.get('metadata').get('name')))
- found = False
- for vol_glob in filter_names:
- logging.debug("checking vol_glob: {}".format(vol_glob))
- if pathlib.Path(vol_snap.get('metadata').get('name')).match(vol_glob):
- found = True
- logging.debug('Found volSnap.')
- break
- if not found:
- continue
- vol_snap_list[vol_snap.get('metadata').get('name')] = vol_snap
+ if volume_snapshot_classes:
+ for vol_snap in volume_snapshot_classes.get('items'):
+ if filter_names is not None and len(filter_names) > 0:
+ logging.debug("filter_names-glob-for: {}".format(vol_snap.get('metadata').get('name')))
+ found = False
+ for vol_glob in filter_names:
+ logging.debug("checking vol_glob: {}".format(vol_glob))
+ if pathlib.Path(vol_snap.get('metadata').get('name')).match(vol_glob):
+ found = True
+ logging.debug('Found volSnap.')
+ break
+ if not found:
+ continue
+ vol_snap_list[vol_snap.get('metadata').get('name')] = vol_snap
return vol_snap_list
+def snapshot_api_is_supported():
+ for api in client.ApisApi().get_api_versions().groups:
+ if api.name == K8SOBJ_SNAPSHOT_GROUP:
+ for v in api.versions:
+ if v.version == K8SOBJ_SNAPSHOT_VERSION:
+ logging.debug('Cluster support snapshots API')
+ return True
+ logging.debug('Cluster does not support snapshots API')
+ return False
+
def get_snapshot_drivers_compatible(custom_api):
compatible_drivers = []
+ if not snapshot_api_is_supported():
+ return compatible_drivers
+ volume_snapshot_classes = []
try:
+ # raise Exception("This is a probe")
volume_snapshot_classes = volumesnapshotclass_list_all(custom_api)
except Exception as e:
logging.error('Controlled exception. This exception is because the volumesnapshotclasses is nos available. We can confirm this fact with `kubectl api-resources`')
# TODO: export/move all checks into k8sbackend
def check_storage_compatibility_with_vsnapshot(self, storage_class_name):
- logging.debug("Check Storage compatibility. {}".format(storage_class_name))
+ logging.debug("Check Storage class compatibility.{}".format(storage_class_name))
storage_provisioner = get_provisioner(self.storagev1api, storage_class_name)
logging.debug("Provisioner {}".format(storage_provisioner))
logging.debug('Compatible Drivers: {} '.format(get_snapshot_drivers_compatible(self.crd_api)))
def check_pvc_compatiblity_with_vsnapshot(self, namespace, pvc_name):
pvc = self.get_pvcdata_namespaced(namespace, pvc_name)
- logging.debug('[CUSTOM] Check Compatibilidy with Snapshots. Name: {}'.format(pvc_name))
- logging.debug('[CUSTOM] PVC: {}'.format(pvc))
+ logging.debug('Check Compatibility with Snapshots. Name: {}'.format(pvc_name))
+ logging.debug('PVC: {}'.format(pvc))
return self.check_storage_compatibility_with_vsnapshot(pvc.get('storage_class_name'))
def _check_config_map(self, file_info):