str(self.objtype),
self.objcache is not None)
+
+ def set_name(self, name: str):
+ self.name = name
+
+
def is_bucket(self):
return self.type == DIRECTORY and not self.name
if backupmode == BaculaBackupMode.Snapshot:
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: {}".format(vsnapshot, pvc_from_vsnap))
+ logging.debug("The pvc create from vsnapshot {} is: {}. FI: {}".format(vsnapshot, pvc_from_vsnap, pvc_from_vsnap.get('fi')))
if vsnapshot == None:
logging.debug(CHANGE_BACKUP_MODE_FOR_INCOMPATIBLITY_PVC.format(pvcname))
# backupmode = BaculaBackupMode.Clone
self._io.send_info(CHANGE_BACKUP_MODE_FOR_INCOMPATIBLITY_PVC.format(pvcname))
else:
- pvc = pvc_from_vsnap.get("name")
+ pvc = pvc_from_vsnap
pvcname = pvc_from_vsnap.get("name")
logging.debug("handling vol after snapshot/clone: {}".format(pvcname))
# iterate on requested volumes for backup
logging.debug("iterate over requested vols for backup: {}".format(handledvolumes))
for volumes in handledvolumes:
+ logging.debug('Volume in handlevolumes:\n{}'.format(volumes))
pvc = volumes['pvc']
pvcname = volumes['pvcname']
# get pvcdata for this volume
"""
PVCDATA:plugintest-pvc-alone:{'name': 'plugintest-pvc-alone-baculaclone-lfxrra', 'node_name': None, 'storage_class_name': 'ocs-storagecluster-cephfs', 'capacity': '1Gi', 'fi': <baculak8s.entities.file_info.FileInfo object at 0x7fc3c08bc668>}
"""
- pvcdata = self._plugin.get_pvcdata_namespaced(namespace, pvcname, pvc)
+ pvcdata = self._plugin.get_pvcdata_namespaced(namespace, pvcname, pvcname)
if isinstance(pvcdata, dict) and 'error' in pvcdata:
self._handle_error(PVCDATA_GET_ERROR.format(parse_json_descr(pvcdata)))
else:
- logging.debug('PVCDATA:{}:{}'.format(pvc, pvcdata))
- logging.debug('PVCDATA FI.name:{}'.format(pvcdata.get('fi').name))
+ # Modify the name in FileInfo because we need save the file like original name
+ # and not the new pvc (from vsnapshot) name.
+ if volumes.get('vsnapshot') is not None:
+ logging.debug('We change the name of FileInfo to adapt the original pvc name with the new pvc name')
+ pvcdata.get('fi').set_name(pvc.get('fi').name)
+
if len(pvcdata) > 0:
status = self.process_pvcdata(namespace, pvcdata, True)
# Check if pvc is compatible with vsnapshot
if not self._plugin.check_pvc_compatiblity_with_vsnapshot(namespace, 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')))
- vsnapshot = self._plugin.create_vsnapshot(namespace, pvc.get('name'))
+ vsnapshot = self._plugin.create_vsnapshot(namespace, pvc)
if isinstance(vsnapshot, dict) and 'error' in vsnapshot:
self._handle_error(CANNOT_CREATE_VSNAPSHOT_ERR.format(parse_json_descr(vsnapshot)))
return None, None
#
# Bacula(R) is a registered trademark of Kern Sibbald.
#
+import logging
SNAPSHOT_DRIVER_COMPATIBLE='csi'
K8SOBJ_SNAPSHOT_GROUP = 'snapshot.storage.k8s.io'
-K8SOBJ_SNAPSHOT_VERSION = 'v1beta1'
+K8SOBJ_SNAPSHOT_VERSION = 'v1'
+K8SOBJ_SNAPSHOTCLASS_PLURAL = 'volumesnapshotclasses'
K8SOBJ_SNAPSHOT_PLURAL = 'volumesnapshots'
K8SOBJ_SNAPSHOT_KIND = 'VolumeSnapshot'
K8SOBJ_SNAPSHOT_NAME_TEMPLATE = 'bacula-vsnap-{pvc}-{jobid}'
BACKUP_PVC_FROM_SNAPSHOT_TEMPLATE = 'bacula-pvcfs-{pvc}-{jobid}'
-K8SOBJ_SNAPSHOT_CLASS = 'csi-hostpath-snapclass'
def csi_snapshots_read_namespaced(crd_api, namespace, name):
return crd_api.get_namespaced_custom_object(K8SOBJ_SNAPSHOT_GROUP, K8SOBJ_SNAPSHOT_VERSION, namespace, K8SOBJ_SNAPSHOT_PLURAL, name)
}
return snapdict
+def get_volume_snapshot_class_name(crd_api, pvc_storageclass_provisioner):
+ volume_snapshot_classes = crd_api.list_cluster_custom_object(K8SOBJ_SNAPSHOT_GROUP, K8SOBJ_SNAPSHOT_VERSION, K8SOBJ_SNAPSHOTCLASS_PLURAL, watch=False)
+ logging.debug("Provisioner of PVC Storage class:\n{}".format(pvc_storageclass_provisioner))
+ logging.debug("VolumeSnapshotClasses available:\n {}".format(volume_snapshot_classes))
+ for snap in volume_snapshot_classes.get('items'):
+ if pvc_storageclass_provisioner == snap.get('driver'):
+ logging.debug("VolumesnapshotClass selected:\n{}".format(snap.get('metadata').get('name')))
+ return snap.get('metadata').get('name')
+ raise ValueError("VolumeSnapshotClass not found for this provisioner: {}. Please contact with Bacula support".format(pvc_storageclass_provisioner))
-def prepare_create_snapshot_body(namespace, pvc_name, jobid):
+
+
+def prepare_create_snapshot_body(crd_api, namespace, pvc_name, jobid, pvc_storageclass_provisioner):
+ volumeSnapshotClassName = get_volume_snapshot_class_name(crd_api, pvc_storageclass_provisioner)
return {
"group": K8SOBJ_SNAPSHOT_GROUP,
"version": K8SOBJ_SNAPSHOT_VERSION,
"namespace": namespace
},
"spec": {
- "volumeSnapshotClassName": K8SOBJ_SNAPSHOT_CLASS,
+ "volumeSnapshotClassName": volumeSnapshotClassName,
"source": {
"persistentVolumeClaimName": pvc_name
}
'kind': K8SOBJ_SNAPSHOT_KIND,
'apiGroup': K8SOBJ_SNAPSHOT_GROUP
},
- 'accessModes': ['ReadOnlyMany'],
+ 'accessModes': ['ReadWriteOnce'],
'resources': { 'requests': {'storage': pvcdata.get('capacity')}}
}
}
return False
return status.get('readyToUse')
- def create_vsnapshot(self, namespace, pvcname):
- logging.info("Creating vsnapshot of pvc `{}`".format(pvcname))
- snapshot = prepare_create_snapshot_body(namespace, pvcname, self._params.get('jobid'))
+ def create_vsnapshot(self, namespace, pvc):
+ pvcname = pvc.get('name')
+ logging.info("Creating vsnapshot of pvc `{}`".format(pvc))
+ storage_provisioner = get_provisioner(self.storagev1api, pvc.get('storage_class_name'))
+ snapshot = prepare_create_snapshot_body(self.crd_api, namespace, pvcname, self._params.get('jobid'), storage_provisioner)
+ logging.debug("Body to create vsnapshot:\n`{}`\n".format(snapshot))
response = self.__execute(lambda: self.crd_api.create_namespaced_custom_object(**snapshot, pretty=True))
if isinstance(response, dict) and "error" in response:
return response
def create_pvc_from_vsnapshot(self, namespace, pvcdata):
new_pvc = prepare_pvc_from_vsnapshot_body(namespace, pvcdata, self._params.get('jobid'))
+ logging.debug("Body to create pvc from vsnapshot: `{}`".format(new_pvc))
response = self.create_pvc_clone(namespace, new_pvc)
if isinstance(response, dict) and 'error' in response:
return response