def reboot(self): self.validate_can_perform_action() LOG.info(_LI("Rebooting instance %s."), self.id) if self.db_info.cluster_id is not None and not self.context.is_admin: raise exception.ClusterInstanceOperationNotSupported() self.update_db(task_status=InstanceTasks.REBOOTING) task_api.API(self.context).reboot(self.id)
def _create_resources(): # parse the ID from the Ref instance_id = utils.get_id_from_href(instance) # verify that the instance exists and can perform actions from trove.instance.models import Instance instance_model = Instance.load(context, instance_id) instance_model.validate_can_perform_action() cls.validate_can_perform_action(instance_model, 'backup_create') cls.verify_swift_auth_token(context) if instance_model.cluster_id is not None: raise exception.ClusterInstanceOperationNotSupported() ds = instance_model.datastore ds_version = instance_model.datastore_version parent = None if parent_id: # Look up the parent info or fail early if not found or if # the user does not have access to the parent. _parent = cls.get_by_id(context, parent_id) parent = { 'location': _parent.location, 'checksum': _parent.checksum, } try: db_info = DBBackup.create(name=name, description=description, tenant_id=context.tenant, state=BackupState.NEW, instance_id=instance_id, parent_id=parent_id, datastore_version_id=ds_version.id, deleted=False) except exception.InvalidModelError as ex: LOG.exception( _("Unable to create backup record for " "instance: %s"), instance_id) raise exception.BackupCreationError(str(ex)) backup_info = { 'id': db_info.id, 'name': name, 'description': description, 'instance_id': instance_id, 'backup_type': db_info.backup_type, 'checksum': db_info.checksum, 'parent': parent, 'datastore': ds.name, 'datastore_version': ds_version.name, } api.API(context).create_backup(backup_info, instance_id) return db_info
def restart(self): self.validate_can_perform_action() LOG.info(_LI("Restarting datastore on instance %s."), self.id) if self.db_info.cluster_id is not None and not self.context.is_admin: raise exception.ClusterInstanceOperationNotSupported() # Set our local status since Nova might not change it quick enough. #TODO(tim.simpson): Possible bad stuff can happen if this service # shuts down before it can set status to NONE. # We need a last updated time to mitigate this; # after some period of tolerance, we'll assume the # status is no longer in effect. self.update_db(task_status=InstanceTasks.REBOOTING) task_api.API(self.context).restart(self.id)
def _resize_resources(): self.validate_can_perform_action() LOG.info(_("Resizing volume of instance %s.") % self.id) if self.db_info.cluster_id is not None: raise exception.ClusterInstanceOperationNotSupported() old_size = self.volume_size if int(new_size) <= old_size: raise exception.BadRequest(_("The new volume 'size' must be " "larger than the current volume " "size of '%s'.") % old_size) # Set the task to Resizing before sending off to the taskmanager self.update_db(task_status=InstanceTasks.RESIZING) task_api.API(self.context).resize_volume(new_size, self.id)
def _delete_resources(): if self.is_building: raise exception.UnprocessableEntity("Instance %s is not ready." % self.id) LOG.debug("Deleting instance with compute id = %s." % self.db_info.compute_instance_id) from trove.cluster.models import is_cluster_deleting if (self.db_info.cluster_id is not None and not is_cluster_deleting(self.context, self.db_info.cluster_id)): raise exception.ClusterInstanceOperationNotSupported() self.update_db(task_status=InstanceTasks.DELETING, configuration_id=None) task_api.API(self.context).delete_instance(self.id)
def resize_flavor(self, new_flavor_id): self.validate_can_perform_action() LOG.info( _LI("Resizing instance %(instance_id)s flavor to " "%(flavor_id)s."), { 'instance_id': self.id, 'flavor_id': new_flavor_id }) if self.db_info.cluster_id is not None: raise exception.ClusterInstanceOperationNotSupported() # Validate that the flavor can be found and that it isn't the same size # as the current one. client = create_nova_client(self.context) try: new_flavor = client.flavors.get(new_flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=new_flavor_id) old_flavor = client.flavors.get(self.flavor_id) new_flavor_size = new_flavor.ram old_flavor_size = old_flavor.ram if self.volume_support: if new_flavor.ephemeral != 0: raise exception.LocalStorageNotSupported() if new_flavor_size == old_flavor_size: raise exception.CannotResizeToSameSize() elif self.device_path is not None: # ephemeral support enabled if new_flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=new_flavor_id) if (new_flavor_size == old_flavor_size and new_flavor.ephemeral == new_flavor.ephemeral): raise exception.CannotResizeToSameSize() elif new_flavor_size == old_flavor_size: # uses local storage raise exception.CannotResizeToSameSize() # Set the task to RESIZING and begin the async call before returning. self.update_db(task_status=InstanceTasks.RESIZING) LOG.debug("Instance %s set to RESIZING.", self.id) task_api.API(self.context).resize_flavor(self.id, old_flavor, new_flavor)
def check_cluster_instance_actions(self, instance_id): # Check if instance is in a cluster and if actions are allowed instance = DBInstance.find_by(id=instance_id) if instance.cluster_id and self._block_cluster_instance_actions(): raise exception.ClusterInstanceOperationNotSupported()
def create(cls, context, instance, name, description=None, parent_id=None, incremental=False, swift_container=None, restore_from=None): """ create db record for Backup :param cls: :param context: tenant_id included :param instance: :param name: :param description: :param parent_id: :param incremental: flag to indicate incremental backup based on previous backup :param swift_container: Swift container name. :param restore_from: A dict that contains backup information of another region. :return: """ backup_state = BackupState.NEW checksum = None instance_id = None parent = None last_backup_id = None location = None backup_type = constants.BACKUP_TYPE_FULL size = None if restore_from: # Check location and datastore version. LOG.info(f"Restoring backup, restore_from: {restore_from}") backup_state = BackupState.RESTORED ds_version_id = restore_from.get('local_datastore_version_id') ds_version = datastore_models.DatastoreVersion.load_by_uuid( ds_version_id) location = restore_from.get('remote_location') swift_client = clients.create_swift_client(context) try: obj_meta = swift.get_metadata(swift_client, location, extra_attrs=['etag']) except Exception: msg = f'Failed to restore backup from {location}' LOG.exception(msg) raise exception.BackupCreationError(msg) checksum = obj_meta['etag'] if 'parent_location' in obj_meta: backup_type = constants.BACKUP_TYPE_INC size = restore_from['size'] else: instance_id = utils.get_id_from_href(instance) # Import here to avoid circular imports. from trove.instance import models as inst_model instance_model = inst_model.Instance.load(context, instance_id) instance_model.validate_can_perform_action() if instance_model.cluster_id is not None: raise exception.ClusterInstanceOperationNotSupported() cls.validate_can_perform_action(instance_model, 'backup_create') cls.verify_swift_auth_token(context) ds = instance_model.datastore ds_version = instance_model.datastore_version if parent_id: # Look up the parent info or fail early if not found or if # the user does not have access to the parent. _parent = cls.get_by_id(context, parent_id) parent = { 'location': _parent.location, 'checksum': _parent.checksum, } elif incremental: _parent = Backup.get_last_completed(context, instance_id) if _parent: parent = { 'location': _parent.location, 'checksum': _parent.checksum } last_backup_id = _parent.id if parent: backup_type = constants.BACKUP_TYPE_INC def _create_resources(): try: db_info = DBBackup.create(name=name, description=description, tenant_id=context.project_id, state=backup_state, instance_id=instance_id, parent_id=parent_id or last_backup_id, datastore_version_id=ds_version.id, deleted=False, location=location, checksum=checksum, backup_type=backup_type, size=size) except exception.InvalidModelError as ex: LOG.exception( "Unable to create backup record for " "instance: %s", instance_id) raise exception.BackupCreationError(str(ex)) if not restore_from: backup_info = { 'id': db_info.id, 'name': name, 'description': description, 'instance_id': instance_id, 'backup_type': db_info.backup_type, 'checksum': db_info.checksum, 'parent': parent, 'datastore': ds.name, 'datastore_version': ds_version.name, 'swift_container': swift_container } api.API(context).create_backup(backup_info, instance_id) else: context.notification.payload.update({'backup_id': db_info.id}) return db_info return run_with_quotas(context.project_id, {'backups': 1}, _create_resources)