Exemplo n.º 1
0
 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)
Exemplo n.º 2
0
        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
Exemplo n.º 3
0
 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)
Exemplo n.º 4
0
 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)
Exemplo n.º 5
0
        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)
Exemplo n.º 6
0
    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)
Exemplo n.º 7
0
 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()
Exemplo n.º 8
0
    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)