def test_run_with_quotas(self): f = Mock() run_with_quotas(FAKE_TENANT1, {'instances': 1, 'volumes': 5}, f) self.assertTrue(QUOTAS.reserve.called) self.assertTrue(QUOTAS.commit.called) self.assertFalse(QUOTAS.rollback.called) self.assertTrue(f.called)
def delete(self): 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() if self.slaves: msg = _("Detach replicas before deleting replica source.") LOG.warn(msg) raise exception.ReplicaSourceDeleteForbidden(msg) self.update_db(task_status=InstanceTasks.DELETING, configuration_id=None) task_api.API(self.context).delete_instance(self.id) deltas = {'instances': -1} if self.volume_support: deltas['volumes'] = -self.volume_size return run_with_quotas(self.tenant_id, deltas, _delete_resources)
def delete(cls, context, backup_id): """ update Backup table on deleted flag for given Backup :param cls: :param context: context containing the tenant id and token :param backup_id: Backup uuid :return: """ # Recursively delete all children and grandchildren of this backup. query = DBBackup.query() query = query.filter_by(parent_id=backup_id, deleted=False) for child in query.all(): cls.delete(context, child.id) def _delete_resources(): backup = cls.get_by_id(context, backup_id) if backup.is_running: msg = _("Backup %s cannot be deleted because it is running.") raise exception.UnprocessableEntity(msg % backup_id) cls.verify_swift_auth_token(context) api.API(context).delete_backup(backup_id) return run_with_quotas(context.tenant, {'backups': -1}, _delete_resources)
def create(cls, context, instance, name, description=None, parent_id=None): """ create db record for Backup :param cls: :param context: tenant_id included :param instance: :param name: :param description: :return: """ 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) 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, deleted=False) except exception.InvalidModelError as ex: LOG.exception("Unable to create Backup record:") 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, } api.API(context).create_backup(backup_info, instance_id) return db_info return run_with_quotas(context.tenant, {'backups': 1}, _create_resources)
def delete(self): def _delete_resources(): if self.is_building: raise exception.UnprocessableEntity("Instance %s is not ready." % self.id) LOG.debug(_(" ... deleting compute id = %s") % self.db_info.compute_instance_id) LOG.debug(_(" ... setting status to DELETING.")) self.update_db(task_status=InstanceTasks.DELETING) task_api.API(self.context).delete_instance(self.id) deltas = {"instances": -1} if CONF.trove_volume_support: deltas["volumes"] = -self.volume_size return run_with_quotas(self.tenant_id, deltas, _delete_resources)
def delete(self): 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) self.update_db(task_status=InstanceTasks.DELETING, configuration_id=None) task_api.API(self.context).delete_instance(self.id) deltas = {'instances': -1} if self.volume_support: deltas['volumes'] = -self.volume_size return run_with_quotas(self.tenant_id, deltas, _delete_resources)
def resize_volume(self, new_size): def _resize_resources(): self.validate_can_perform_action() LOG.info("Resizing volume of instance %s..." % self.id) if not self.volume_size: raise exception.BadRequest("Instance %s has no volume." % self.id) old_size = self.volume_size if int(new_size) <= old_size: msg = "The new volume 'size' must be larger than the current " "volume size of '%s'" raise exception.BadRequest(msg % 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) new_size_l = long(new_size) validate_volume_size(new_size_l) return run_with_quotas(self.tenant_id, {"volumes": new_size_l - self.volume_size}, _resize_resources)
def delete(cls, context, backup_id): """ update Backup table on deleted flag for given Backup :param cls: :param context: context containing the tenant id and token :param backup_id: Backup uuid :return: """ def _delete_resources(): backup = cls.get_by_id(context, backup_id) if backup.is_running: msg = "Backup %s cannot be delete because it is running." % backup_id raise exception.UnprocessableEntity(msg) cls.verify_swift_auth_token(context) api.API(context).delete_backup(backup_id) return run_with_quotas(context.tenant, {"backups": -1}, _delete_resources)
def delete(self): 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) deltas = {"instances": -1} if self.volume_support: deltas["volumes"] = -self.volume_size return run_with_quotas(self.tenant_id, deltas, _delete_resources)
def resize_volume(self, new_size): def _resize_resources(): self.validate_can_perform_action() LOG.info(_LI("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) if not self.volume_size: raise exception.BadRequest(_("Instance %s has no volume.") % self.id) new_size_l = long(new_size) validate_volume_size(new_size_l) return run_with_quotas(self.tenant_id, {"volumes": new_size_l - self.volume_size}, _resize_resources)
def create(cls, context, instance, name, description=None): """ create db record for Backup :param cls: :param context: tenant_id included :param instance: :param name: :param description: :return: """ def _create_resources(): # parse the ID from the Ref instance_id = utils.get_id_from_href(instance) # verify that the instance exist and can perform actions from trove.instance.models import Instance instance_model = Instance.load(context, instance_id) instance_model.validate_can_perform_action() cls.verify_swift_auth_token(context) try: db_info = DBBackup.create( name=name, description=description, tenant_id=context.tenant, state=BackupState.NEW, instance_id=instance_id, deleted=False, ) except exception.InvalidModelError as ex: LOG.exception("Unable to create Backup record:") raise exception.BackupCreationError(str(ex)) api.API(context).create_backup(db_info.id, instance_id) return db_info return run_with_quotas(context.tenant, {"backups": 1}, _create_resources)
def create(cls, context, instance, name, description=None): """ create db record for Backup :param cls: :param context: tenant_id included :param instance: :param name: :param description: :return: """ def _create_resources(): # parse the ID from the Ref instance_id = utils.get_id_from_href(instance) # verify that the instance exist and can perform actions from trove.instance.models import Instance instance_model = Instance.load(context, instance_id) instance_model.validate_can_perform_action() cls.verify_swift_auth_token(context) try: db_info = DBBackup.create(name=name, description=description, tenant_id=context.tenant, state=BackupState.NEW, instance_id=instance_id, deleted=False) except exception.InvalidModelError as ex: LOG.exception("Unable to create Backup record:") raise exception.BackupCreationError(str(ex)) api.API(context).create_backup(db_info.id, instance_id) return db_info return run_with_quotas(context.tenant, {'backups': 1}, _create_resources)
def resize_volume(self, new_size): def _resize_resources(): self.validate_can_perform_action() LOG.info("Resizing volume of instance %s..." % self.id) if not self.volume_size: raise exception.BadRequest( _("Instance %s has no volume.") % self.id) 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) new_size_l = long(new_size) validate_volume_size(new_size_l) return run_with_quotas(self.tenant_id, {'volumes': new_size_l - self.volume_size}, _resize_resources)
def delete(self): 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) deltas = {'instances': -1} if self.volume_support: deltas['volumes'] = -self.volume_size return run_with_quotas(self.tenant_id, deltas, _delete_resources)
def create(cls, context, name, flavor_id, image_id, databases, users, datastore, datastore_version, volume_size, backup_id, availability_zone=None, nics=None, configuration_id=None): client = create_nova_client(context) try: flavor = client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {'instances': 1} if CONF.trove_volume_support: validate_volume_size(volume_size) deltas['volumes'] = volume_size else: if volume_size is not None: raise exception.VolumeNotSupported() ephemeral_support = CONF.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) if backup_id is not None: backup_info = Backup.get_by_id(context, backup_id) if backup_info.is_running: raise exception.BackupNotCompleteError(backup_id=backup_id) if not backup_info.check_swift_object_exist( context, verify_checksum=CONF.verify_swift_checksum_on_restore): raise exception.BackupFileNotFound( location=backup_info.location) backup_db_info = DBInstance.find_by( context=context, id=backup_info.instance_id) if (backup_db_info.datastore_version_id != datastore_version.id): ds_version = (datastore_models.DatastoreVersion. load_by_uuid(backup_db_info.datastore_version_id) ) raise exception.BackupDatastoreVersionMismatchError( version1=ds_version.name, version2=datastore_version.name) if not nics and CONF.default_neutron_networks: nics = [] for net_id in CONF.default_neutron_networks: nics.append({"net-id": net_id}) def _create_resources(): db_info = DBInstance.create(name=name, flavor_id=flavor_id, tenant_id=context.tenant, volume_size=volume_size, datastore_version_id= datastore_version.id, task_status=InstanceTasks.BUILDING, configuration_id=configuration_id) LOG.debug(_("Tenant %(tenant)s created new " "Trove instance %(db)s...") % {'tenant': context.tenant, 'db': db_info.id}) # if a configuration group is associated with an instance, # generate an overrides dict to pass into the instance creation # method overrides = Configuration.get_configuration_overrides( context, configuration_id) datastore_status = InstanceServiceStatus.create( instance_id=db_info.id, status=tr_instance.ServiceStatuses.NEW) if CONF.trove_dns_support: dns_client = create_dns_client(context) hostname = dns_client.determine_hostname(db_info.id) db_info.hostname = hostname db_info.save() root_password = None if cls.get_root_on_create( datastore_version.manager) and not backup_id: root_password = utils.generate_random_password() task_api.API(context).create_instance(db_info.id, name, flavor, image_id, databases, users, datastore_version.manager, datastore_version.packages, volume_size, backup_id, availability_zone, root_password, nics, overrides) return SimpleInstance(context, db_info, datastore_status, root_password) return run_with_quotas(context.tenant, deltas, _create_resources)
def create(cls, context, instance, name, description=None, parent_id=None, incremental=False): """ 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 :return: """ 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 last_backup_id = 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, } elif incremental: _parent = Backup.get_last_completed(context, instance_id) if _parent: parent = { 'location': _parent.location, 'checksum': _parent.checksum } last_backup_id = _parent.id try: db_info = DBBackup.create(name=name, description=description, tenant_id=context.tenant, state=BackupState.NEW, instance_id=instance_id, parent_id=parent_id or last_backup_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 return run_with_quotas(context.tenant, {'backups': 1}, _create_resources)
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)
def create( cls, context, name, flavor_id, image_id, databases, users, service_type, volume_size, backup_id, availability_zone=None, ): client = create_nova_client(context) try: flavor = client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {"instances": 1} if CONF.trove_volume_support: validate_volume_size(volume_size) deltas["volumes"] = volume_size else: if volume_size is not None: raise exception.VolumeNotSupported() ephemeral_support = CONF.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) def _create_resources(): security_groups = None if backup_id is not None: backup_info = Backup.get_by_id(context, backup_id) if backup_info.is_running: raise exception.BackupNotCompleteError(backup_id=backup_id) location = backup_info.location LOG.info(_("Checking if backup exist in '%s'") % location) if not Backup.check_object_exist(context, location): raise exception.BackupFileNotFound(location=location) db_info = DBInstance.create( name=name, flavor_id=flavor_id, tenant_id=context.tenant, volume_size=volume_size, service_type=service_type, task_status=InstanceTasks.BUILDING, ) LOG.debug( _("Tenant %(tenant)s created new " "Trove instance %(db)s...") % {"tenant": context.tenant, "db": db_info.id} ) service_status = InstanceServiceStatus.create(instance_id=db_info.id, status=ServiceStatuses.NEW) if CONF.trove_dns_support: dns_client = create_dns_client(context) hostname = dns_client.determine_hostname(db_info.id) db_info.hostname = hostname db_info.save() if CONF.trove_security_groups_support: security_group = SecurityGroup.create_for_instance(db_info.id, context) if CONF.trove_security_groups_rules_support: SecurityGroupRule.create_sec_group_rule( security_group, CONF.trove_security_group_rule_protocol, CONF.trove_security_group_rule_port, CONF.trove_security_group_rule_port, CONF.trove_security_group_rule_cidr, context, ) security_groups = [security_group["name"]] task_api.API(context).create_instance( db_info.id, name, flavor, image_id, databases, users, service_type, volume_size, security_groups, backup_id, availability_zone, ) return SimpleInstance(context, db_info, service_status) return run_with_quotas(context.tenant, deltas, _create_resources)
def create(cls, context, instance, name, description=None, parent_id=None, incremental=False): """ 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 :return: """ 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) ds = instance_model.datastore ds_version = instance_model.datastore_version manager = (datastore_models.DatastoreVersion.load_by_uuid( ds_version.id).manager) if (not CONF.get(manager).enable_cluster_instance_backup and instance_model.cluster_id is not None): raise exception.ClusterInstanceOperationNotSupported() parent = None parent_backup = None parent_backup_id = None last_backup_id = 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. if parent_id == 'last': # Need to assign parent_id to a new variable # parent_backup_id, otherwise an unbound variable error # will be thrown parent_backup = Backup.get_last_completed(context, instance_id, True) if parent_backup is None: raise exception.NotFound() parent_backup_id = parent_backup.id else: parent_backup_id = parent_id _parent = cls.get_by_id(context, parent_backup_id) parent = { 'id': parent_backup_id, '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 try: db_info = DBBackup.create(name=name, description=description, tenant_id=context.tenant, state=BackupState.NEW, instance_id=instance_id, parent_id=parent_backup_id or last_backup_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 return run_with_quotas(context.tenant, {'backups': 1}, _create_resources)
def create(cls, context, name, flavor_id, image_id, databases, users, datastore, datastore_version, volume_size, backup_id, availability_zone=None, nics=None, configuration_id=None, slave_of_id=None, cluster_config=None): datastore_cfg = CONF.get(datastore_version.manager) client = create_nova_client(context) try: flavor = client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {'instances': 1} volume_support = datastore_cfg.volume_support if volume_support: validate_volume_size(volume_size) deltas['volumes'] = volume_size # Instance volume should have enough space for the backup # Backup, and volume sizes are in GBs target_size = volume_size else: target_size = flavor.disk # local_storage if volume_size is not None: raise exception.VolumeNotSupported() if datastore_cfg.device_path: if flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) target_size = flavor.ephemeral # ephemeral_Storage if backup_id is not None: backup_info = Backup.get_by_id(context, backup_id) if backup_info.is_running: raise exception.BackupNotCompleteError(backup_id=backup_id) if backup_info.size > target_size: raise exception.BackupTooLarge(backup_size=backup_info.size, disk_size=target_size) if not backup_info.check_swift_object_exist( context, verify_checksum=CONF.verify_swift_checksum_on_restore): raise exception.BackupFileNotFound( location=backup_info.location) if (backup_info.datastore_version_id and backup_info.datastore.name != datastore.name): raise exception.BackupDatastoreMismatchError( datastore1=backup_info.datastore.name, datastore2=datastore.name) if slave_of_id: replication_support = datastore_cfg.replication_strategy if not replication_support: raise exception.ReplicationNotSupported( datastore=datastore.name) try: # looking for replica source replica_source = DBInstance.find_by(context, id=slave_of_id, deleted=False) if replica_source.slave_of_id: raise exception.Forbidden( _("Cannot create a replica of a replica %(id)s.") % {'id': slave_of_id}) except exception.ModelNotFoundError: LOG.exception( _("Cannot create a replica of %(id)s " "as that instance could not be found.") % {'id': slave_of_id}) raise exception.NotFound(uuid=slave_of_id) if not nics: nics = [] if CONF.default_neutron_networks: nics = [{ "net-id": net_id } for net_id in CONF.default_neutron_networks] + nics def _create_resources(): if cluster_config: cluster_id = cluster_config.get("id", None) shard_id = cluster_config.get("shard_id", None) instance_type = cluster_config.get("instance_type", None) else: cluster_id = shard_id = instance_type = None db_info = DBInstance.create( name=name, flavor_id=flavor_id, tenant_id=context.tenant, volume_size=volume_size, datastore_version_id=datastore_version.id, task_status=InstanceTasks.BUILDING, configuration_id=configuration_id, slave_of_id=slave_of_id, cluster_id=cluster_id, shard_id=shard_id, type=instance_type) LOG.debug("Tenant %(tenant)s created new Trove instance %(db)s.", { 'tenant': context.tenant, 'db': db_info.id }) # if a configuration group is associated with an instance, # generate an overrides dict to pass into the instance creation # method config = Configuration(context, configuration_id) overrides = config.get_configuration_overrides() service_status = InstanceServiceStatus.create( instance_id=db_info.id, status=tr_instance.ServiceStatuses.NEW) if CONF.trove_dns_support: dns_client = create_dns_client(context) hostname = dns_client.determine_hostname(db_info.id) db_info.hostname = hostname db_info.save() root_password = None if cls.get_root_on_create( datastore_version.manager) and not backup_id: root_password = utils.generate_random_password() task_api.API(context).create_instance( db_info.id, name, flavor, image_id, databases, users, datastore_version.manager, datastore_version.packages, volume_size, backup_id, availability_zone, root_password, nics, overrides, slave_of_id, cluster_config) return SimpleInstance(context, db_info, service_status, root_password) return run_with_quotas(context.tenant, deltas, _create_resources)
def create(cls, context, name, flavor_id, image_id, databases, users, service_type, volume_size, backup_id, availability_zone=None): client = create_nova_client(context) try: flavor = client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {'instances': 1} if CONF.trove_volume_support: validate_volume_size(volume_size) deltas['volumes'] = volume_size else: if volume_size is not None: raise exception.VolumeNotSupported() ephemeral_support = CONF.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) if backup_id is not None: backup_info = Backup.get_by_id(context, backup_id) if backup_info.is_running: raise exception.BackupNotCompleteError(backup_id=backup_id) if not backup_info.check_swift_object_exist( context, verify_checksum=CONF.verify_swift_checksum_on_restore): raise exception.BackupFileNotFound( location=backup_info.location) def _create_resources(): db_info = DBInstance.create(name=name, flavor_id=flavor_id, tenant_id=context.tenant, volume_size=volume_size, service_type=service_type, task_status=InstanceTasks.BUILDING) LOG.debug(_("Tenant %(tenant)s created new " "Trove instance %(db)s...") % {'tenant': context.tenant, 'db': db_info.id}) service_status = InstanceServiceStatus.create( instance_id=db_info.id, status=rd_instance.ServiceStatuses.NEW) if CONF.trove_dns_support: dns_client = create_dns_client(context) hostname = dns_client.determine_hostname(db_info.id) db_info.hostname = hostname db_info.save() root_password = None if CONF.root_on_create and not backup_id: root_password = uuidutils.generate_uuid() task_api.API(context).create_instance(db_info.id, name, flavor, image_id, databases, users, service_type, volume_size, backup_id, availability_zone, root_password) return SimpleInstance(context, db_info, service_status, root_password) return run_with_quotas(context.tenant, deltas, _create_resources)
def create(cls, context, name, flavor_id, image_id, databases, users, datastore, datastore_version, volume_size, backup_id, availability_zone=None, nics=None, configuration_id=None, slave_of_id=None, cluster_config=None, replica_count=None): datastore_cfg = CONF.get(datastore_version.manager) client = create_nova_client(context) try: flavor = client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {'instances': 1} volume_support = datastore_cfg.volume_support if volume_support: validate_volume_size(volume_size) deltas['volumes'] = volume_size # Instance volume should have enough space for the backup # Backup, and volume sizes are in GBs target_size = volume_size else: target_size = flavor.disk # local_storage if volume_size is not None: raise exception.VolumeNotSupported() if datastore_cfg.device_path: if flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) target_size = flavor.ephemeral # ephemeral_Storage if backup_id: backup_info = Backup.get_by_id(context, backup_id) if not backup_info.is_done_successfuly: raise exception.BackupNotCompleteError( backup_id=backup_id, state=backup_info.state) if backup_info.size > target_size: raise exception.BackupTooLarge( backup_size=backup_info.size, disk_size=target_size) if not backup_info.check_swift_object_exist( context, verify_checksum=CONF.verify_swift_checksum_on_restore): raise exception.BackupFileNotFound( location=backup_info.location) if (backup_info.datastore_version_id and backup_info.datastore.name != datastore.name): raise exception.BackupDatastoreMismatchError( datastore1=backup_info.datastore.name, datastore2=datastore.name) if slave_of_id: replication_support = datastore_cfg.replication_strategy if not replication_support: raise exception.ReplicationNotSupported( datastore=datastore.name) try: # looking for replica source replica_source = DBInstance.find_by( context, id=slave_of_id, deleted=False) if replica_source.slave_of_id: raise exception.Forbidden( _("Cannot create a replica of a replica %(id)s.") % {'id': slave_of_id}) # load the replica source status to check if # source is available load_simple_instance_server_status( context, replica_source) replica_source_instance = Instance( context, replica_source, None, InstanceServiceStatus.find_by( context, instance_id=slave_of_id)) replica_source_instance.validate_can_perform_action() except exception.ModelNotFoundError: LOG.exception( _("Cannot create a replica of %(id)s " "as that instance could not be found.") % {'id': slave_of_id}) raise exception.NotFound(uuid=slave_of_id) elif replica_count and replica_count != 1: raise exception.Forbidden(_( "Replica count only valid when creating replicas. Cannot " "create %(count)d instances.") % {'count': replica_count}) multi_replica = slave_of_id and replica_count and replica_count > 1 instance_count = replica_count if multi_replica else 1 if not nics: nics = [] if CONF.default_neutron_networks: nics = [{"net-id": net_id} for net_id in CONF.default_neutron_networks] + nics def _create_resources(): if cluster_config: cluster_id = cluster_config.get("id", None) shard_id = cluster_config.get("shard_id", None) instance_type = cluster_config.get("instance_type", None) else: cluster_id = shard_id = instance_type = None ids = [] names = [] root_passwords = [] root_password = None for instance_index in range(0, instance_count): db_info = DBInstance.create( name=name, flavor_id=flavor_id, tenant_id=context.tenant, volume_size=volume_size, datastore_version_id=datastore_version.id, task_status=InstanceTasks.BUILDING, configuration_id=configuration_id, slave_of_id=slave_of_id, cluster_id=cluster_id, shard_id=shard_id, type=instance_type) LOG.debug("Tenant %(tenant)s created new Trove instance " "%(db)s.", {'tenant': context.tenant, 'db': db_info.id}) instance_id = db_info.id instance_name = name ids.append(instance_id) names.append(instance_name) root_passwords.append(None) # change the name to be name + replica_number if more than one if multi_replica: replica_number = instance_index + 1 names[instance_index] += '-' + str(replica_number) setattr(db_info, 'name', names[instance_index]) db_info.save() # if a configuration group is associated with an instance, # generate an overrides dict to pass into the instance creation # method config = Configuration(context, configuration_id) overrides = config.get_configuration_overrides() service_status = InstanceServiceStatus.create( instance_id=instance_id, status=tr_instance.ServiceStatuses.NEW) if CONF.trove_dns_support: dns_client = create_dns_client(context) hostname = dns_client.determine_hostname(instance_id) db_info.hostname = hostname db_info.save() if cls.get_root_on_create( datastore_version.manager) and not backup_id: root_password = utils.generate_random_password() root_passwords[instance_index] = root_password if instance_count > 1: instance_id = ids instance_name = names root_password = root_passwords task_api.API(context).create_instance( instance_id, instance_name, flavor, image_id, databases, users, datastore_version.manager, datastore_version.packages, volume_size, backup_id, availability_zone, root_password, nics, overrides, slave_of_id, cluster_config) return SimpleInstance(context, db_info, service_status, root_password) return run_with_quotas(context.tenant, deltas, _create_resources)
def create(cls, context, name, flavor_id, image_id, databases, users, datastore, datastore_version, volume_size, backup_id, availability_zone=None, nics=None, configuration_id=None): client = create_nova_client(context) try: flavor = client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {'instances': 1} if CONF.trove_volume_support: validate_volume_size(volume_size) deltas['volumes'] = volume_size else: if volume_size is not None: raise exception.VolumeNotSupported() ephemeral_support = CONF.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) if backup_id is not None: backup_info = Backup.get_by_id(context, backup_id) if backup_info.is_running: raise exception.BackupNotCompleteError(backup_id=backup_id) if not backup_info.check_swift_object_exist( context, verify_checksum=CONF.verify_swift_checksum_on_restore): raise exception.BackupFileNotFound( location=backup_info.location) if not nics and CONF.default_neutron_networks: nics = [] for net_id in CONF.default_neutron_networks: nics.append({"net-id": net_id}) def _create_resources(): db_info = DBInstance.create(name=name, flavor_id=flavor_id, tenant_id=context.tenant, volume_size=volume_size, datastore_version_id= datastore_version.id, task_status=InstanceTasks.BUILDING, configuration_id=configuration_id) LOG.debug(_("Tenant %(tenant)s created new " "Trove instance %(db)s...") % {'tenant': context.tenant, 'db': db_info.id}) # if a configuration group is associated with an instance, # generate an overrides dict to pass into the instance creation # method overrides = Configuration.get_configuration_overrides( context, configuration_id) service_status = InstanceServiceStatus.create( instance_id=db_info.id, status=tr_instance.ServiceStatuses.NEW) if CONF.trove_dns_support: dns_client = create_dns_client(context) hostname = dns_client.determine_hostname(db_info.id) db_info.hostname = hostname db_info.save() root_password = None if cls.get_root_on_create( datastore_version.manager) and not backup_id: root_password = utils.generate_random_password() task_api.API(context).create_instance(db_info.id, name, flavor, image_id, databases, users, datastore_version.manager, datastore_version.packages, volume_size, backup_id, availability_zone, root_password, nics, overrides) return SimpleInstance(context, db_info, service_status, root_password) return run_with_quotas(context.tenant, deltas, _create_resources)
def create(cls, context, instance_id, name, description=None, group_id=None, backup_type=None, expire_at=None, init=False, service_image_id=None, parent_id=None): if parent_id is not None: parent_id = str(parent_id) LOG.info("parent_id:%s, parent_id.len:%s", parent_id, len(parent_id.strip())) if len(parent_id.strip()) == 0: parent_id = None _parent_id = parent_id from trove.instance.models import Instance instance_id = utils.get_id_from_href(instance_id) instance_model = Instance.load(context, instance_id) if init: if instance_model.db_info.server_status != 'ACTIVE': msg = ("Instance is not currently available for an action to be " "performed (server_status was %s).", instance_model.db_info.server_status) LOG.error(msg) raise exception.UnprocessableEntity(msg) else: instance_model.validate_can_perform_action() if instance_model.type == DBInstanceType.MASTER: try: standby_id = InstanceGroupItem.get_by_gid_type(context, instance_model.group_id, DBInstanceType.STANDBY).instance_id instance_model = Instance.load(context, standby_id) instance_model.validate_can_perform_action() instance_id = standby_id except Exception as e: LOG.error(e) raise e if group_id is None: raise exception.TroveError("group_id can't None") if backup_type is None or backup_type not in [Type.SNAPSHOT, Type.AUTOBACKUP]: raise exception.TroveError("instType can't None, only accept value: snapshot or autobackup ") if backup_type == Type.SNAPSHOT: expire_time = 0 _parent_id = None # force full elif backup_type == Type.AUTOBACKUP: expire_time = int(expire_at) if parent_id and parent_id == '0': _parent_id = None # force full elif parent_id and parent_id != '0': try: backup_parent = cls.get_by_id(context, parent_id) LOG.debug("backup_parent:%s", backup_parent) except: raise exception.NotFound("not found backup with parent_id: %s" % parent_id) if not backup_parent: raise exception.NotFound("not found backup with parent_id: %s" % parent_id) elif parent_id is None: LOG.debug("parent_id is None:%s", parent_id) last_backup_chain = cls.get_last_backup_chain(group_id) backup_incremental_chain_size = CONF.backup_incremental_chain_size LOG.info("last_backup_chain: %s, backup_incremental_chain_size: %s", last_backup_chain, backup_incremental_chain_size) if len(last_backup_chain) == 0 \ or len(last_backup_chain) >= int(backup_incremental_chain_size): _parent_id = None # create full else: compare_instance = None try: compare_instance = InstanceGroupItem.get_by_gid_type(context, group_id, DBInstanceType.STANDBY) except exception.NotFound: # not has standby try: compare_instance = InstanceGroupItem.get_by_gid_type(context, group_id, DBInstanceType.SINGLE) except exception.NotFound: # not has single pass if compare_instance: compare_id = compare_instance.instance_id switched = False for b in last_backup_chain: # has standby if b["instance_id"] != compare_id: switched = True # create full LOG.debug("last_backup_chain: %s, switched: %s, backup_instance_id: %s, b.instance_id: %s" , last_backup_chain, switched, compare_id, b["instance_id"]) break if not switched: parent = last_backup_chain.pop() # create incremental _parent_id = parent["id"] else: # not found standby and single _parent_id = None # create full LOG.debug("create backup use parent_id: %s", _parent_id) def _create_resources(): try: db_info = models.DBBackup.create(name=name, description=description, tenant_id=context.tenant, state=models.BackupState.NEW, instance_id=instance_id, deleted=False, group_id=group_id, type=backup_type, expire_at=expire_time, service_image_id=service_image_id, parent_id=_parent_id) except exception.InvalidModelError as ex: LOG.exception("Unable to create Backup record:") msg = "Unable to create Backup record, group_id %s, instance_id %s, parent_id %s " % (group_id, _instance_id, _parent_id) AlarmRpc(context).alarm(context.tenant, level=AlarmRpc.LEVEL_ERROR, _type=AlarmRpc.TYPE_TASKMANAGER, message=msg+str(ex)) raise exception.BackupCreationError(str(ex)) api.API(context).create_backup(db_info.id, instance_id) return db_info return run_with_quotas(context.tenant, {'backups': 1}, _create_resources)
def create(cls, context, name, flavor_id, image_id, databases, users, datastore, datastore_version, volume_size, backup_id, availability_zone=None, nics=None, configuration_id=None, slave_of_id=None, cluster_config=None): datastore_cfg = CONF.get(datastore_version.manager) client = create_nova_client(context) try: flavor = client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {'instances': 1} volume_support = datastore_cfg.volume_support if volume_support: validate_volume_size(volume_size) deltas['volumes'] = volume_size else: if volume_size is not None: raise exception.VolumeNotSupported() ephemeral_support = datastore_cfg.device_path if ephemeral_support: if flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) if backup_id is not None: backup_info = Backup.get_by_id(context, backup_id) if backup_info.is_running: raise exception.BackupNotCompleteError(backup_id=backup_id) if not backup_info.check_swift_object_exist( context, verify_checksum=CONF.verify_swift_checksum_on_restore): raise exception.BackupFileNotFound( location=backup_info.location) if (backup_info.datastore_version_id and backup_info.datastore.name != datastore.name): raise exception.BackupDatastoreMismatchError( datastore1=backup_info.datastore.name, datastore2=datastore.name) if slave_of_id: replication_support = datastore_cfg.replication_strategy if not replication_support: raise exception.ReplicationNotSupported( datastore=datastore.name) if not nics: nics = [] if CONF.default_neutron_networks: nics = [{"net-id": net_id} for net_id in CONF.default_neutron_networks] + nics def _create_resources(): if cluster_config: cluster_id = cluster_config.get("id", None) shard_id = cluster_config.get("shard_id", None) instance_type = cluster_config.get("instance_type", None) else: cluster_id = shard_id = instance_type = None db_info = DBInstance.create(name=name, flavor_id=flavor_id, tenant_id=context.tenant, volume_size=volume_size, datastore_version_id= datastore_version.id, task_status=InstanceTasks.BUILDING, configuration_id=configuration_id, slave_of_id=slave_of_id, cluster_id=cluster_id, shard_id=shard_id, type=instance_type) LOG.debug("Tenant %(tenant)s created new Trove instance %(db)s." % {'tenant': context.tenant, 'db': db_info.id}) # if a configuration group is associated with an instance, # generate an overrides dict to pass into the instance creation # method config = Configuration(context, configuration_id) overrides = config.get_configuration_overrides() service_status = InstanceServiceStatus.create( instance_id=db_info.id, status=tr_instance.ServiceStatuses.NEW) if CONF.trove_dns_support: dns_client = create_dns_client(context) hostname = dns_client.determine_hostname(db_info.id) db_info.hostname = hostname db_info.save() root_password = None if cls.get_root_on_create( datastore_version.manager) and not backup_id: root_password = utils.generate_random_password() task_api.API(context).create_instance(db_info.id, name, flavor, image_id, databases, users, datastore_version.manager, datastore_version.packages, volume_size, backup_id, availability_zone, root_password, nics, overrides, slave_of_id, cluster_config) return SimpleInstance(context, db_info, service_status, root_password) return run_with_quotas(context.tenant, deltas, _create_resources)
def create(cls, context, name, flavor_id, image_id, databases, users, service_type, volume_size, backup_id): client = create_nova_client(context) try: flavor = client.flavors.get(flavor_id) except nova_exceptions.NotFound: raise exception.FlavorNotFound(uuid=flavor_id) deltas = {'instances': 1} if CONF.trove_volume_support: validate_volume_size(volume_size) deltas['volumes'] = volume_size else: if volume_size is not None: raise exception.VolumeNotSupported() ephemeral_support = CONF.device_path if ephemeral_support and flavor.ephemeral == 0: raise exception.LocalStorageNotSpecified(flavor=flavor_id) def _create_resources(): security_groups = None if backup_id is not None: backup_info = Backup.get_by_id(context, backup_id) if backup_info.is_running: raise exception.BackupNotCompleteError(backup_id=backup_id) location = backup_info.location LOG.info(_("Checking if backup exist in '%s'") % location) if not Backup.check_object_exist(context, location): raise exception.BackupFileNotFound(location=location) db_info = DBInstance.create(name=name, flavor_id=flavor_id, tenant_id=context.tenant, volume_size=volume_size, service_type=service_type, task_status=InstanceTasks.BUILDING) LOG.debug( _("Tenant %s created new Trove instance %s...") % (context.tenant, db_info.id)) service_status = InstanceServiceStatus.create( instance_id=db_info.id, status=ServiceStatuses.NEW) if CONF.trove_dns_support: dns_client = create_dns_client(context) hostname = dns_client.determine_hostname(db_info.id) db_info.hostname = hostname db_info.save() if CONF.trove_security_groups_support: security_group = SecurityGroup.create_for_instance( db_info.id, context) security_groups = [security_group["name"]] task_api.API(context).create_instance(db_info.id, name, flavor, image_id, databases, users, service_type, volume_size, security_groups, backup_id) return SimpleInstance(context, db_info, service_status) return run_with_quotas(context.tenant, deltas, _create_resources)