okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 1 | import parse |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 2 | import staffeln.conf |
| 3 | import collections |
| 4 | from staffeln.common import constants |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 5 | from staffeln.conductor import result |
okozachenko | d280136 | 2021-05-05 21:23:46 +0300 | [diff] [blame] | 6 | from openstack.exceptions import ResourceNotFound as OpenstackResourceNotFound |
| 7 | from openstack.exceptions import SDKException as OpenstackSDKException |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 8 | from oslo_log import log |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 9 | from staffeln.common import context |
| 10 | from staffeln import objects |
| 11 | from staffeln.i18n import _ |
okozachenko | b7d5537 | 2021-05-10 18:21:02 +0300 | [diff] [blame] | 12 | from staffeln.common import openstack |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 13 | |
| 14 | CONF = staffeln.conf.CONF |
| 15 | LOG = log.getLogger(__name__) |
| 16 | |
| 17 | BackupMapping = collections.namedtuple( |
okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 18 | "BackupMapping", ["volume_id", "backup_id", "project_id", "instance_id", "backup_completed"] |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 19 | ) |
| 20 | |
| 21 | QueueMapping = collections.namedtuple( |
okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 22 | "QueueMapping", ["volume_id", "backup_id", "project_id", "instance_id", "backup_status"] |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 23 | ) |
| 24 | |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 25 | |
| 26 | def check_vm_backup_metadata(metadata): |
| 27 | if not CONF.conductor.backup_metadata_key in metadata: |
| 28 | return False |
| 29 | return metadata[CONF.conductor.backup_metadata_key].lower() in ["true"] |
| 30 | |
| 31 | |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 32 | class Backup(object): |
| 33 | """Implmentations of the queue with the sql.""" |
| 34 | |
| 35 | def __init__(self): |
| 36 | self.ctx = context.make_context() |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 37 | self.result = result.BackupResult() |
okozachenko | b7d5537 | 2021-05-10 18:21:02 +0300 | [diff] [blame] | 38 | self.openstacksdk = openstack.OpenstackSDK() |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 39 | self.project_list = {} |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 40 | |
| 41 | def publish_backup_result(self): |
| 42 | self.result.publish() |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 43 | |
okozachenko | 9eae01d | 2021-05-11 16:47:27 +0300 | [diff] [blame] | 44 | def refresh_backup_result(self): |
| 45 | self.result.initialize() |
| 46 | |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 47 | def get_backups(self, filters=None): |
| 48 | return objects.Volume.list(self.ctx, filters=filters) |
| 49 | |
okozachenko | fb38560 | 2021-05-07 19:00:47 +0300 | [diff] [blame] | 50 | def get_backup_quota(self, project_id): |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 51 | return self.openstacksdk.get_backup_quota(project_id) |
okozachenko | fb38560 | 2021-05-07 19:00:47 +0300 | [diff] [blame] | 52 | |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 53 | def get_queues(self, filters=None): |
| 54 | """Get the list of volume queue columns from the queue_data table""" |
| 55 | queues = objects.Queue.list(self.ctx, filters=filters) |
| 56 | return queues |
| 57 | |
okozachenko | d280136 | 2021-05-05 21:23:46 +0300 | [diff] [blame] | 58 | def create_queue(self, old_tasks): |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 59 | """Create the queue of all the volumes for backup""" |
okozachenko | d280136 | 2021-05-05 21:23:46 +0300 | [diff] [blame] | 60 | # 1. get the old task list, not finished in the last cycle |
| 61 | # and keep till now |
| 62 | old_task_volume_list = [] |
| 63 | for old_task in old_tasks: |
| 64 | old_task_volume_list.append(old_task.volume_id) |
| 65 | |
| 66 | # 2. add new tasks in the queue which are not existing in the old task list |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 67 | queue_list = self.check_instance_volumes() |
| 68 | for queue in queue_list: |
okozachenko | d280136 | 2021-05-05 21:23:46 +0300 | [diff] [blame] | 69 | if not queue.volume_id in old_task_volume_list: |
| 70 | self._volume_queue(queue) |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 71 | |
| 72 | # Backup the volumes attached to which has a specific metadata |
okozachenko | fb38560 | 2021-05-07 19:00:47 +0300 | [diff] [blame] | 73 | def filter_by_server_metadata(self, metadata): |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 74 | |
| 75 | if not CONF.conductor.backup_metadata_key in metadata: |
| 76 | return False |
| 77 | |
| 78 | return metadata[CONF.conductor.backup_metadata_key].lower() == constants.BACKUP_ENABLED_KEY |
| 79 | |
| 80 | # Backup the volumes in in-use and available status |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 81 | def filter_by_volume_status(self, volume_id, project_id): |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 82 | try: |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 83 | volume = self.openstacksdk.get_volume(volume_id, project_id) |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 84 | if volume == None: return False |
| 85 | res = volume['status'] in ("available", "in-use") |
| 86 | if not res: |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 87 | reason = _("Volume %s is not backed because it is in %s status" % (volume_id, volume['status'])) |
| 88 | LOG.info(reason) |
| 89 | self.result.add_failed_backup(project_id, volume_id, reason) |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 90 | return res |
| 91 | |
okozachenko | d280136 | 2021-05-05 21:23:46 +0300 | [diff] [blame] | 92 | except OpenstackResourceNotFound: |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 93 | return False |
| 94 | |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 95 | # delete all backups forcily regardless of the status |
okozachenko | 2ab48e8 | 2021-05-07 16:55:11 +0300 | [diff] [blame] | 96 | def hard_cancel_backup_task(self, task): |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 97 | try: |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 98 | project_id = task.project_id |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 99 | reason = _("Cancel backup %s because of timeout." % task.backup_id) |
| 100 | LOG.info(reason) |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 101 | |
| 102 | if project_id not in self.project_list: self.process_non_existing_backup(task) |
| 103 | self.openstacksdk.set_project(self.project_list[project_id]) |
| 104 | backup = self.openstacksdk.get_backup(task.backup_id) |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 105 | if backup == None: return task.delete_queue() |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 106 | self.openstacksdk.delete_backup(task.backup_id) |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 107 | task.delete_queue() |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 108 | self.result.add_failed_backup(task.project_id, task.volume_id, reason) |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 109 | except OpenstackResourceNotFound: |
| 110 | task.delete_queue() |
| 111 | |
| 112 | except OpenstackSDKException as e: |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 113 | reason = _("Backup %s deletion failed." |
| 114 | "%s" % (task.backup_id, str(e))) |
| 115 | LOG.info(reason) |
| 116 | # TODO(Alex): If backup timeout and also back cancel failed, |
| 117 | # then what to do? |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 118 | # 1. notify |
| 119 | # 2. set the volume status as in-use |
| 120 | # remove from the queue table |
| 121 | task.delete_queue() |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 122 | self.result.add_failed_backup(task.project_id, task.volume_id, reason) |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 123 | |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 124 | # delete only available backups: reserved |
okozachenko | 2ab48e8 | 2021-05-07 16:55:11 +0300 | [diff] [blame] | 125 | def soft_remove_backup_task(self, backup_object): |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 126 | try: |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 127 | backup = self.openstacksdk.get_backup(backup_object.backup_id) |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 128 | if backup == None: return backup_object.delete_backup() |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 129 | if backup["status"] in ("available"): |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 130 | self.openstacksdk.delete_backup(backup_object.backup_id) |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 131 | backup_object.delete_backup() |
| 132 | elif backup["status"] in ("error", "error_restoring"): |
| 133 | # TODO(Alex): need to discuss |
| 134 | # now if backup is in error status, then retention service |
| 135 | # does not remove it from openstack but removes it from the |
| 136 | # backup table so user can delete it on Horizon. |
| 137 | backup_object.delete_backup() |
| 138 | else: # "deleting", "restoring" |
| 139 | LOG.info(_("Rotation for the backup %s is skipped in this cycle " |
| 140 | "because it is in %s status") % (backup_object.backup_id, backup["status"])) |
| 141 | |
okozachenko | d280136 | 2021-05-05 21:23:46 +0300 | [diff] [blame] | 142 | except OpenstackResourceNotFound: |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 143 | LOG.info(_("Backup %s is not existing in Openstack." |
| 144 | "Or cinder-backup is not existing in the cloud." % backup_object.backup_id)) |
| 145 | # remove from the backup table |
| 146 | backup_object.delete_backup() |
| 147 | return False |
| 148 | |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 149 | except OpenstackSDKException as e: |
okozachenko | a6dcdc0 | 2021-05-10 14:13:26 +0300 | [diff] [blame] | 150 | LOG.info( |
| 151 | _("Backup %s deletion failed." "%s" % (backup_object.backup_id, |
| 152 | str(e))) |
| 153 | ) |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 154 | # TODO(Alex): Add it into the notification queue |
| 155 | # remove from the backup table |
| 156 | backup_object.delete_backup() |
| 157 | return False |
| 158 | |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 159 | # delete all backups forcily regardless of the status |
| 160 | def hard_remove_volume_backup(self, backup_object): |
| 161 | try: |
okozachenko | b875cbe | 2021-05-11 19:29:51 +0300 | [diff] [blame] | 162 | project_id = backup_object.project_id |
| 163 | if project_id not in self.project_list: |
| 164 | backup_object.delete_backup() |
| 165 | |
| 166 | self.openstacksdk.set_project(project_id) |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 167 | backup = self.openstacksdk.get_backup(uuid=backup_object.backup_id, |
okozachenko | b875cbe | 2021-05-11 19:29:51 +0300 | [diff] [blame] | 168 | project_id=project_id) |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 169 | if backup == None: return backup_object.delete_backup() |
| 170 | |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 171 | self.openstacksdk.delete_backup(uuid=backup_object.backup_id) |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 172 | backup_object.delete_backup() |
| 173 | |
| 174 | except OpenstackResourceNotFound: |
| 175 | LOG.info(_("Backup %s is not existing in Openstack." |
| 176 | "Or cinder-backup is not existing in the cloud." % backup_object.backup_id)) |
| 177 | # remove from the backup table |
| 178 | backup_object.delete_backup() |
| 179 | |
| 180 | except OpenstackSDKException as e: |
okozachenko | a6dcdc0 | 2021-05-10 14:13:26 +0300 | [diff] [blame] | 181 | LOG.info( |
| 182 | _("Backup %s deletion failed." "%s" % (backup_object.backup_id, |
| 183 | str(e))) |
| 184 | ) |
| 185 | |
okozachenko | ca2b37a | 2021-05-06 20:38:02 +0300 | [diff] [blame] | 186 | # TODO(Alex): Add it into the notification queue |
| 187 | # remove from the backup table |
| 188 | backup_object.delete_backup() |
| 189 | |
okozachenko | b875cbe | 2021-05-11 19:29:51 +0300 | [diff] [blame] | 190 | def update_project_list(self): |
| 191 | projects = self.openstacksdk.get_projects() |
| 192 | for project in projects: |
| 193 | self.project_list[project.id] = project |
| 194 | |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 195 | def check_instance_volumes(self): |
| 196 | """Get the list of all the volumes from the project using openstacksdk |
| 197 | Function first list all the servers in the project and get the volumes |
| 198 | that are attached to the instance. |
| 199 | """ |
| 200 | queues_map = [] |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 201 | projects = self.openstacksdk.get_projects() |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 202 | for project in projects: |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 203 | empty_project = True |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 204 | self.project_list[project.id] = project |
| 205 | servers = self.openstacksdk.get_servers(project_id=project.id) |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 206 | for server in servers: |
okozachenko | fb38560 | 2021-05-07 19:00:47 +0300 | [diff] [blame] | 207 | if not self.filter_by_server_metadata(server.metadata): continue |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 208 | if empty_project: |
| 209 | empty_project = False |
| 210 | self.result.add_project(project.id, project.name) |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 211 | for volume in server.attached_volumes: |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 212 | if not self.filter_by_volume_status(volume["id"], project.id): continue |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 213 | queues_map.append( |
| 214 | QueueMapping( |
okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 215 | project_id=project.id, |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 216 | volume_id=volume["id"], |
| 217 | backup_id="NULL", |
| 218 | instance_id=server.id, |
| 219 | backup_status=constants.BACKUP_PLANNED, |
| 220 | ) |
| 221 | ) |
| 222 | return queues_map |
| 223 | |
| 224 | def _volume_queue(self, task): |
| 225 | """Saves the queue data to the database.""" |
| 226 | |
| 227 | # TODO(Alex): Need to escalate discussion |
| 228 | # When create the task list, need to check the WIP backup generators |
| 229 | # which are created in the past backup cycle. |
| 230 | # Then skip to create new tasks for the volumes whose backup is WIP |
| 231 | volume_queue = objects.Queue(self.ctx) |
| 232 | volume_queue.backup_id = task.backup_id |
| 233 | volume_queue.volume_id = task.volume_id |
| 234 | volume_queue.instance_id = task.instance_id |
Susanta Gautam | c406111 | 2021-05-10 02:39:23 +0000 | [diff] [blame] | 235 | volume_queue.project_id = task.project_id |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 236 | volume_queue.backup_status = task.backup_status |
| 237 | volume_queue.create() |
| 238 | |
| 239 | def create_volume_backup(self, queue): |
| 240 | """Initiate the backup of the volume |
| 241 | :params: queue: Provide the map of the volume that needs |
| 242 | backup. |
| 243 | This function will call the backupup api and change the |
| 244 | backup_status and backup_id in the queue table. |
| 245 | """ |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 246 | project_id = queue.project_id |
| 247 | if queue.backup_id == "NULL": |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 248 | try: |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 249 | LOG.info(_("Backup for volume %s creating in project %s" |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 250 | % (queue.volume_id, project_id))) |
okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 251 | # NOTE(Alex): no need to wait because we have a cycle time out |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 252 | if project_id not in self.project_list: self.process_non_existing_backup(queue) |
| 253 | self.openstacksdk.set_project(self.project_list[project_id]) |
| 254 | volume_backup = self.openstacksdk.create_backup(volume_id=queue.volume_id, |
okozachenko | b875cbe | 2021-05-11 19:29:51 +0300 | [diff] [blame] | 255 | project_id=project_id) |
okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 256 | queue.backup_id = volume_backup.id |
| 257 | queue.backup_status = constants.BACKUP_WIP |
| 258 | queue.save() |
okozachenko | d280136 | 2021-05-05 21:23:46 +0300 | [diff] [blame] | 259 | except OpenstackSDKException as error: |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 260 | reason = _("Backup creation for the volume %s failled. %s" |
| 261 | % (queue.volume_id, str(error))) |
| 262 | LOG.info(reason) |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 263 | self.result.add_failed_backup(project_id, queue.volume_id, reason) |
okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 264 | parsed = parse.parse("Error in creating volume backup {id}", str(error)) |
okozachenko | a6dcdc0 | 2021-05-10 14:13:26 +0300 | [diff] [blame] | 265 | if parsed is not None: |
| 266 | queue.backup_id = parsed["id"] |
okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 267 | queue.backup_status = constants.BACKUP_WIP |
| 268 | queue.save() |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 269 | else: |
| 270 | pass |
| 271 | # TODO(Alex): remove this task from the task list |
| 272 | # Backup planned task cannot have backup_id in the same cycle |
| 273 | # Reserve for now because it is related to the WIP backup genenrators which |
| 274 | # are not finished in the current cycle |
| 275 | |
okozachenko | a6dcdc0 | 2021-05-10 14:13:26 +0300 | [diff] [blame] | 276 | # backup gen was not created |
| 277 | def process_pre_failed_backup(self, task): |
| 278 | # 1.notify via email |
| 279 | reason = _("The backup creation for the volume %s was prefailed." |
| 280 | % task.volume_id) |
| 281 | self.result.add_failed_backup(task.project_id, task.volume_id, reason) |
| 282 | # LOG.error(reason) |
| 283 | # 2. remove failed task from the task queue |
| 284 | task.delete_queue() |
| 285 | |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 286 | def process_failed_backup(self, task): |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 287 | # 1. notify via email |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 288 | reason = _("The status of backup for the volume %s is error." % task.volume_id) |
| 289 | self.result.add_failed_backup(task.project_id, task.volume_id, reason) |
| 290 | LOG.error(reason) |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 291 | # 2. delete backup generator |
| 292 | self.openstacksdk.delete_backup(uuid=task.backup_id) |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 293 | # 3. remove failed task from the task queue |
| 294 | task.delete_queue() |
| 295 | |
okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 296 | def process_non_existing_backup(self, task): |
| 297 | task.delete_queue() |
| 298 | |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 299 | def process_available_backup(self, task): |
| 300 | LOG.info("Backup of the volume %s is successful." % task.volume_id) |
| 301 | # 1. save success backup in the backup table |
| 302 | self._volume_backup( |
| 303 | BackupMapping( |
| 304 | volume_id=task.volume_id, |
okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 305 | project_id=task.project_id, |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 306 | backup_id=task.backup_id, |
| 307 | instance_id=task.instance_id, |
| 308 | backup_completed=1, |
| 309 | ) |
| 310 | ) |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 311 | self.result.add_success_backup(task.project_id, task.volume_id, task.backup_id) |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 312 | # 2. remove from the task list |
| 313 | task.delete_queue() |
| 314 | # 3. TODO(Alex): notify via email |
| 315 | |
| 316 | def process_using_backup(self, task): |
okozachenko | cb31608 | 2021-05-07 21:30:39 +0300 | [diff] [blame] | 317 | # treat same as the available backup for now |
| 318 | self.process_available_backup(task) |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 319 | |
| 320 | def check_volume_backup_status(self, queue): |
| 321 | """Checks the backup status of the volume |
| 322 | :params: queue: Provide the map of the volume that needs backup |
| 323 | status checked. |
| 324 | Call the backups api to see if the backup is successful. |
| 325 | """ |
okozachenko | d4284d2 | 2021-05-05 20:48:23 +0300 | [diff] [blame] | 326 | try: |
okozachenko | ed4c487 | 2021-05-10 17:58:37 +0300 | [diff] [blame] | 327 | |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 328 | project_id = queue.project_id |
okozachenko | ed4c487 | 2021-05-10 17:58:37 +0300 | [diff] [blame] | 329 | |
okozachenko | a6dcdc0 | 2021-05-10 14:13:26 +0300 | [diff] [blame] | 330 | # The case in which the error produced before backup gen created. |
| 331 | if queue.backup_id == "NULL": |
| 332 | self.process_pre_failed_backup(queue) |
| 333 | return |
okozachenko | f731e62 | 2021-05-10 17:38:30 +0300 | [diff] [blame] | 334 | if project_id not in self.project_list: self.process_non_existing_backup(queue) |
| 335 | self.openstacksdk.set_project(self.project_list[project_id]) |
| 336 | backup_gen = self.openstacksdk.get_backup(queue.backup_id) |
okozachenko | ed4c487 | 2021-05-10 17:58:37 +0300 | [diff] [blame] | 337 | |
okozachenko | d4284d2 | 2021-05-05 20:48:23 +0300 | [diff] [blame] | 338 | if backup_gen == None: |
| 339 | # TODO(Alex): need to check when it is none |
okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 340 | LOG.info(_("[Beta] Backup status of %s is returning none." % (queue.backup_id))) |
okozachenko | 2ab48e8 | 2021-05-07 16:55:11 +0300 | [diff] [blame] | 341 | self.process_non_existing_backup(queue) |
okozachenko | d4284d2 | 2021-05-05 20:48:23 +0300 | [diff] [blame] | 342 | return |
| 343 | if backup_gen.status == "error": |
| 344 | self.process_failed_backup(queue) |
| 345 | elif backup_gen.status == "available": |
| 346 | self.process_available_backup(queue) |
| 347 | elif backup_gen.status == "creating": |
okozachenko | d4284d2 | 2021-05-05 20:48:23 +0300 | [diff] [blame] | 348 | LOG.info("Waiting for backup of %s to be completed" % queue.volume_id) |
| 349 | else: # "deleting", "restoring", "error_restoring" status |
| 350 | self.process_using_backup(queue) |
okozachenko | d280136 | 2021-05-05 21:23:46 +0300 | [diff] [blame] | 351 | except OpenstackResourceNotFound as e: |
okozachenko | 179cd57 | 2021-05-06 22:23:53 +0300 | [diff] [blame] | 352 | self.process_non_existing_backup(queue) |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 353 | |
| 354 | def _volume_backup(self, task): |
| 355 | # matching_backups = [ |
| 356 | # g for g in self.available_backups if g.backup_id == task.backup_id |
| 357 | # ] |
| 358 | # if not matching_backups: |
| 359 | volume_backup = objects.Volume(self.ctx) |
| 360 | volume_backup.backup_id = task.backup_id |
| 361 | volume_backup.volume_id = task.volume_id |
| 362 | volume_backup.instance_id = task.instance_id |
Susanta Gautam | c406111 | 2021-05-10 02:39:23 +0000 | [diff] [blame] | 363 | volume_backup.project_id = task.project_id |
okozachenko | 6d277e3 | 2021-05-05 20:23:32 +0300 | [diff] [blame] | 364 | volume_backup.backup_completed = task.backup_completed |
| 365 | volume_backup.create() |