def save(self): updates = self.obj_get_changes() projects = updates.pop('projects', None) extra_specs = updates.pop('extra_specs', None) if updates: raise exception.ObjectActionError( action='save', reason='read-only fields were changed') if extra_specs is not None: deleted_keys = (set(self._orig_extra_specs.keys()) - set(extra_specs.keys())) added_keys = self.extra_specs else: added_keys = deleted_keys = None if projects is not None: deleted_projects = set(self._orig_projects) - set(projects) added_projects = set(projects) - set(self._orig_projects) else: added_projects = deleted_projects = None # NOTE(danms): The first remotable method we call will reset # our of the original values for projects and extra_specs. Thus, # we collect the added/deleted lists for both above and /then/ # call these methods to update them. if added_keys or deleted_keys: self.save_extra_specs(self.extra_specs, deleted_keys) if added_projects or deleted_projects: self.save_projects(added_projects, deleted_projects)
def create(self): updates = self.obj_get_changes() if 'id' in updates: raise exception.ObjectActionError(action='create', reason='Already Created') db_agent = db.agent_build_create(self._context, updates) self._from_db_object(self._context, self, db_agent)
def create(self): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason='already created') updates = self.obj_get_changes() db_service = db.service_create(self._context, updates) self._from_db_object(self._context, self, db_service)
def create(self): updates = self._get_primitive_changes() if 'id' in updates: raise exception.ObjectActionError(action='create', reason='already created') db_network = db.network_create_safe(self._context, updates) self._from_db_object(self._context, self, db_network)
def save(self): updates = self.obj_get_changes() if 'address' in updates: raise exception.ObjectActionError(action='save', reason='address is not mutable') db.fixed_ip_update(self._context, str(self.address), updates) self.obj_reset_changes()
def wrapper(self, *args, **kwargs): if args and isinstance(args[0], context.RequestContext): raise exception.ObjectActionError( action=fn.__name__, reason='Calling remotables with context is deprecated') if self._context is None: raise exception.OrphanedObjectError(method=fn.__name__, objtype=self.obj_name()) if NovaObject.indirection_api: updates, result = NovaObject.indirection_api.object_action( self._context, self, fn.__name__, args, kwargs) for key, value in updates.iteritems(): if key in self.fields: field = self.fields[key] # NOTE(ndipanov): Since NovaObjectSerializer will have # deserialized any object fields into objects already, # we do not try to deserialize them again here. if isinstance(value, NovaObject): setattr(self, key, value) else: setattr(self, key, field.from_primitive(self, key, value)) self.obj_reset_changes() self._changed_fields = set(updates.get('obj_what_changed', [])) return result else: return fn(self, *args, **kwargs)
def obj_load_attr(self, attrname): if not self._context: raise exception.OrphanedObjectError(method='obj_load_attr', objtype=self.obj_name()) LOG.debug("Lazy-loading `%(attr)s' on %(name)s id %(id)s", { 'attr': attrname, 'name': self.obj_name(), 'id': self.id, }) if attrname != 'compute_node': raise exception.ObjectActionError( action='obj_load_attr', reason='attribute %s not lazy-loadable' % attrname) if self.binary == 'patron-compute': # Only n-cpu services have attached compute_node(s) compute_nodes = objects.ComputeNodeList.get_all_by_host( self._context, self.host) else: # NOTE(sbauza); Previous behaviour was raising a ServiceNotFound, # we keep it for backwards compatibility raise exception.ServiceNotFound(service_id=self.id) # NOTE(sbauza): Some drivers (VMware, Ironic) can have multiple nodes # for the same service, but for keeping same behaviour, returning only # the first elem of the list self.compute_node = compute_nodes[0]
def obj_load_attr(self, attrname): # NOTE(danms): Only projects could be lazy-loaded right now if attrname != 'projects': raise exception.ObjectActionError(action='obj_load_attr', reason='unable to load %s' % attrname) self._load_projects()
def _create(self, context, update_or_create=False): """Create the block device record in the database. In case the id field is set on the object, and if the instance is set raise an ObjectActionError. Resets all the changes on the object. Returns None :param context: security context used for database calls :param update_or_create: consider existing block devices for the instance based on the device name and swap, and only update the ones that match. Normally only used when creating the instance for the first time. """ cell_type = cells_opts.get_cell_type() if cell_type == 'api': raise exception.ObjectActionError( action='create', reason='BlockDeviceMapping cannot be ' 'created in the API cell.') if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason='already created') updates = self.obj_get_changes() if 'instance' in updates: raise exception.ObjectActionError(action='create', reason='instance assigned') cells_create = update_or_create or None if update_or_create: db_bdm = db.block_device_mapping_update_or_create(context, updates, legacy=False) else: db_bdm = db.block_device_mapping_create(context, updates, legacy=False) self._from_db_object(context, self, db_bdm) if cell_type == 'compute': cells_api = cells_rpcapi.CellsAPI() cells_api.bdm_update_or_create_at_top(context, self, create=cells_create)
def bulk_create(self, context, fixed_ips): ips = [] for fixedip in fixed_ips: ip = obj_base.obj_to_primitive(fixedip) if 'id' in ip: raise exception.ObjectActionError(action='create', reason='already created') ips.append(ip) db.fixed_ip_bulk_create(context, ips)
def create(self): updates = self.obj_get_changes() if 'id' in updates: raise exception.ObjectActionError(action='create', reason='already created') if 'address' in updates: updates['address'] = str(updates['address']) db_fixedip = db.fixed_ip_create(self._context, updates) self._from_db_object(self._context, self, db_fixedip)
def create(self): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason='already created') updates = self.obj_get_changes() self._convert_stats_to_db_format(updates) self._convert_host_ip_to_db_format(updates) self._convert_supported_instances_to_db_format(updates) self._convert_pci_stats_to_db_format(updates) db_compute = db.compute_node_create(self._context, updates) self._from_db_object(self._context, self, db_compute)
def create(self): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason='already created') updates = self.obj_get_changes() parent_group = updates.pop('parent_group', None) if parent_group: updates['parent_group_id'] = parent_group.id grantee_group = updates.pop('grantee_group', None) if grantee_group: updates['group_id'] = grantee_group.id db_rule = db.security_group_rule_create(self._context, updates) self._from_db_object(self._context, self, db_rule)
def destroy(self): if not self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='destroy', reason='already destroyed') db.block_device_mapping_destroy(self._context, self.id) delattr(self, base.get_attrname('id')) cell_type = cells_opts.get_cell_type() if cell_type == 'compute': cells_api = cells_rpcapi.CellsAPI() cells_api.bdm_destroy_at_top(self._context, self.instance_uuid, device_name=self.device_name, volume_id=self.volume_id)
def create(self): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason='already created') updates = self.obj_get_changes() expected_attrs = [] for attr in OPTIONAL_FIELDS: if attr in updates: expected_attrs.append(attr) projects = updates.pop('projects', []) db_flavor = db.flavor_create(self._context, updates, projects=projects) self._from_db_object(self._context, self, db_flavor, expected_attrs=expected_attrs)
def obj_set_defaults(self, *attrs): if not attrs: attrs = [ name for name, field in self.fields.items() if field.default != obj_fields.UnspecifiedDefault ] for attr in attrs: default = copy.deepcopy(self.fields[attr].default) if default is obj_fields.UnspecifiedDefault: raise exception.ObjectActionError( action='set_defaults', reason='No default set for field %s' % attr) if not self.obj_attr_is_set(attr): setattr(self, attr, default)
def save(self): updates = self.obj_get_changes() if 'instance' in updates: raise exception.ObjectActionError(action='save', reason='instance changed') updates.pop('id', None) updated = db.block_device_mapping_update(self._context, self.id, updates, legacy=False) self._from_db_object(self._context, self, updated) cell_type = cells_opts.get_cell_type() if cell_type == 'compute': cells_api = cells_rpcapi.CellsAPI() cells_api.bdm_update_or_create_at_top(self._context, self)
def obj_load_attr(self, attrname): if attrname not in BLOCK_DEVICE_OPTIONAL_ATTRS: raise exception.ObjectActionError( action='obj_load_attr', reason='attribute %s not lazy-loadable' % attrname) if not self._context: raise exception.OrphanedObjectError(method='obj_load_attr', objtype=self.obj_name()) LOG.debug("Lazy-loading `%(attr)s' on %(name)s uuid %(uuid)s", { 'attr': attrname, 'name': self.obj_name(), 'uuid': self.uuid, }) self.instance = objects.Instance.get_by_uuid(self._context, self.instance_uuid) self.obj_reset_changes(fields=['instance'])
def create(self): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason='already created') updates = self.obj_get_changes() payload = dict(updates) updates.pop('id', None) policies = updates.pop('policies', None) members = updates.pop('members', None) db_inst = db.instance_group_create(self._context, updates, policies=policies, members=members) self._from_db_object(self._context, self, db_inst) payload['server_group_id'] = self.uuid compute_utils.notify_about_server_group_update(self._context, "create", payload)
def create(self): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason='already created') self._assert_no_hosts('create') updates = self.obj_get_changes() payload = dict(updates) if 'metadata' in updates: # NOTE(danms): For some reason the notification format is weird payload['meta_data'] = payload.pop('metadata') compute_utils.notify_about_aggregate_update(self._context, "create.start", payload) metadata = updates.pop('metadata', None) db_aggregate = db.aggregate_create(self._context, updates, metadata=metadata) self._from_db_object(self._context, self, db_aggregate) payload['aggregate_id'] = self.id compute_utils.notify_about_aggregate_update(self._context, "create.end", payload)
def obj_make_compatible(self, primitive, target_version): """Make an object representation compatible with a target version. This is responsible for taking the primitive representation of an object and making it suitable for the given target_version. This may mean converting the format of object attributes, removing attributes that have been added since the target version, etc. In general: - If a new version of an object adds a field, this routine should remove it for older versions. - If a new version changed or restricted the format of a field, this should convert it back to something a client knowing only of the older version will tolerate. - If an object that this object depends on is bumped, then this object should also take a version bump. Then, this routine should backlevel the dependent object (by calling its obj_make_compatible()) if the requested version of this object is older than the version where the new dependent object was added. :param:primitive: The result of self.obj_to_primitive() :param:target_version: The version string requested by the recipient of the object :raises: patron.exception.UnsupportedObjectError if conversion is not possible for some reason """ for key, field in self.fields.items(): if not isinstance( field, (obj_fields.ObjectField, obj_fields.ListOfObjectsField)): continue if not self.obj_attr_is_set(key): continue if key not in self.obj_relationships: # NOTE(danms): This is really a coding error and shouldn't # happen unless we miss something raise exception.ObjectActionError(action='obj_make_compatible', reason='No rule for %s' % key) self._obj_make_obj_compatible(primitive, target_version, key)
def create(self): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason='already created') values = { 'instance_uuid': self.instance_uuid, 'code': self.code, 'message': self.message, 'details': self.details, 'host': self.host, } db_fault = db.instance_fault_create(self._context, values) self._from_db_object(self._context, self, db_fault) self.obj_reset_changes() # Cells should only try sending a message over to patron-cells # if cells is enabled and we're not the API cell. Otherwise, # if the API cell is calling this, we could end up with # infinite recursion. if cells_opts.get_cell_type() == 'compute': try: cells_rpcapi.CellsAPI().instance_fault_create_at_top( self._context, db_fault) except Exception: LOG.exception(_LE("Failed to notify cells of instance fault"))
def _assert_no_hosts(self, action): if 'hosts' in self.obj_what_changed(): raise exception.ObjectActionError(action=action, reason='hosts updated inline')
def remove_access(self, project_id): if 'projects' in self.obj_what_changed(): raise exception.ObjectActionError(action='remove_access', reason='projects modified') db.flavor_access_remove(self._context, self.flavorid, project_id) self._load_projects()
def create(self): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason='already created') db_vmap = db.ec2_volume_create(self._context, self.uuid) self._from_db_object(self._context, self, db_vmap)