Exemple #1
0
 def setUp(self):
     super(TestNetworkModel, self).setUp()
     model = network_model.NetworkInfo()
     self.field = fields.Field(fields.NetworkModel())
     self.coerce_good_values = [(model, model), (model.json(), model)]
     self.coerce_bad_values = [[], 'foo']
     self.to_primitive_values = [(model, model.json())]
     self.from_primitive_values = [(model.json(), model)]
Exemple #2
0
 def setUp(self):
     super(TestSet, self).setUp()
     self.field = fields.Field(fields.Set(FakeFieldType()))
     self.coerce_good_values = [(set(['foo',
                                      'bar']), set(['*foo*', '*bar*']))]
     self.coerce_bad_values = [['foo'], {'foo': 'bar'}]
     self.to_primitive_values = [(set(['foo']), tuple(['!foo!']))]
     self.from_primitive_values = [(tuple(['!foo!']), set(['foo']))]
Exemple #3
0
 def setUp(self):
     super(TestDict, self).setUp()
     self.field = fields.Field(fields.Dict(FakeFieldType()))
     self.coerce_good_values = [({'foo': 'bar'}, {'foo': '*bar*'}),
                                ({'foo': 1}, {'foo': '*1*'})]
     self.coerce_bad_values = [{1: 'bar'}, 'foo']
     self.to_primitive_values = [({'foo': 'bar'}, {'foo': '!bar!'})]
     self.from_primitive_values = [({'foo': '!bar!'}, {'foo': 'bar'})]
 def setUp(self):
     super(TestNetworkVIFModel, self).setUp()
     model = network_model.VIF('6c197bc7-820c-40d5-8aff-7116b993e793')
     primitive = jsonutils.dumps(model)
     self.field = fields.Field(fields.NetworkVIFModel())
     self.coerce_good_values = [(model, model), (primitive, model)]
     self.coerce_bad_values = [[], 'foo']
     self.to_primitive_values = [(model, primitive)]
     self.from_primitive_values = [(primitive, model)]
 def setUp(self):
     super(TestXenAddress, self).setUp()
     self.field = fields.Field(fields.XenAddressField())
     self.coerce_good_values = [('000100', '000100'), ('768', '768')]
     self.coerce_bad_values = [
         '1',
         '00100',
     ]
     self.to_primitive_values = self.coerce_good_values
     self.from_primitive_values = self.coerce_good_values
Exemple #6
0
 def setUp(self):
     super(TestIPV6Network, self).setUp()
     self.field = fields.Field(fields.IPV6Network())
     good = ['::1/128', '::1/64', '::1/0']
     self.coerce_good_values = [(x, netaddr.IPNetwork(x)) for x in good]
     self.coerce_bad_values = [
         '192.168.0.0/f', '192.168.0.0/foo', '::1/129', '192.168.0.0/-1'
     ]
     self.to_primitive_values = [(netaddr.IPNetwork(x), x) for x in good]
     self.from_primitive_values = [(x, netaddr.IPNetwork(x)) for x in good]
 def setUp(self):
     super(TestIDEAddress, self).setUp()
     self.field = fields.Field(fields.IDEAddressField())
     self.coerce_good_values = [('0:0', '0:0')]
     self.coerce_bad_values = [
         '0:2',
         '00',
         '0',
     ]
     self.to_primitive_values = self.coerce_good_values
     self.from_primitive_values = self.coerce_good_values
Exemple #8
0
 def setUp(self):
     super(TestCIDR, self).setUp()
     self.field = fields.Field(fields.CIDR())
     good = ['192.168.0.1/24', '192.168.0.0/16', '192.168.0.0/8',
             '192.168.0.0/0', '1.2.3.4/32', '1.2.3.4/22', '0/0',
             '::1/128', '::1/64', '::1/0']
     self.coerce_good_values = [(x, x) for x in good]
     self.coerce_bad_values = ['192.168.0.0', '192.168.0.0/f',
                               '192.168.0.0/foo', '192.168.0.0/33',
                               '::1/129', '192.168.0.0/-1']
     self.to_primitive_values = [(x, x) for x in good]
     self.from_primitive_values = self.to_primitive_values
 def setUp(self):
     super(TestSCSIAddress, self).setUp()
     self.field = fields.Field(fields.SCSIAddressField())
     self.coerce_good_values = [('1:0:2:0', '1:0:2:0')]
     self.coerce_bad_values = [
         '1:0:2',
         '-:0:2:0',
         '1:-:2:0',
         '1:0:-:0',
         '1:0:2:-',
     ]
     self.to_primitive_values = self.coerce_good_values
     self.from_primitive_values = self.coerce_good_values
Exemple #10
0
 def setUp(self):
     super(TestPCIAddress, self).setUp()
     self.field = fields.Field(fields.PCIAddressField())
     self.coerce_good_values = [('0000:00:02.0', '0000:00:02.0')]
     self.coerce_bad_values = [
         '000:00:02.0',
         '0000:0:02.0',
         '0000:00:2.0',
         '0000:00:02.',
         '-000:00:02.0',
         '0000:0-:02.0',
         '0000:00:-2.0',
         '0000:00:02.-',
         '000000:02.0',
         '0000:0:02.0',
         '0000:00:020',
     ]
     self.to_primitive_values = self.coerce_good_values
     self.from_primitive_values = self.coerce_good_values
Exemple #11
0
    def setUp(self):
        class TestableObject(obj_base.NovaObject):
            def __eq__(self, value):
                # NOTE(danms): Be rather lax about this equality thing to
                # satisfy the assertEqual() in test_from_primitive(). We
                # just want to make sure the right type of object is re-created
                return value.__class__.__name__ == TestableObject.__name__

        class OtherTestableObject(obj_base.NovaObject):
            pass

        test_inst = TestableObject()
        super(TestObject, self).setUp()
        self.field = fields.Field(fields.Object('TestableObject'))
        self.coerce_good_values = [(test_inst, test_inst)]
        self.coerce_bad_values = [OtherTestableObject(), 1, 'foo']
        self.to_primitive_values = [(test_inst, test_inst.obj_to_primitive())]
        self.from_primitive_values = [(test_inst.obj_to_primitive(), test_inst)
                                      ]
Exemple #12
0
class SecurityGroupRule(base.NovaPersistentObject, base.NovaObject):
    # Version 1.0: Initial version
    VERSION = '1.0'

    fields = {
        'id': fields.IntegerField(),
        'protocol': fields.StringField(nullable=True),
        'from_port': fields.IntegerField(nullable=True),
        'to_port': fields.IntegerField(nullable=True),
        'cidr': fields.Field(fields.CIDR(), nullable=True),
        'parent_group': fields.ObjectField('SecurityGroup', nullable=True),
        'grantee_group': fields.ObjectField('SecurityGroup', nullable=True),
    }

    @staticmethod
    def _from_db_subgroup(context, db_group):
        if db_group is None:
            return None
        return security_group.SecurityGroup._from_db_object(
            context, security_group.SecurityGroup(), db_group)

    @staticmethod
    def _from_db_object(context, rule, db_rule, expected_attrs=None):
        if expected_attrs is None:
            expected_attrs = []
        for field in rule.fields:
            if field in expected_attrs:
                rule[field] = rule._from_db_subgroup(context, db_rule[field])
            elif field not in OPTIONAL_ATTRS:
                rule[field] = db_rule[field]
        rule._context = context
        rule.obj_reset_changes()
        return rule

    @base.remotable_classmethod
    def get_by_id(cls, context, rule_id):
        db_rule = db.security_group_rule_get(context, rule_id)
        return cls._from_db_object(context, cls(), db_rule)
Exemple #13
0
 class Bar(base.NovaObject):
     fields = {'foo': fields.Field(fields.String())}
Exemple #14
0
class TestSubclassedObject(RandomMixInWithNoFields, MyObj):
    fields = {'new_field': fields.Field(fields.String())}
Exemple #15
0
 class Foo(base.NovaObject):
     fields = {'foobar': fields.Field(fields.Integer())}
class VIFMigrateData(obj_base.NovaObject):
    # Version 1.0: Initial version
    VERSION = '1.0'

    # The majority of the fields here represent a port binding on the
    # **destination** host during a live migration. The vif_type, among
    # other fields, could be different from the existing binding on the
    # source host, which is represented by the "source_vif" field.
    fields = {
        'port_id': fields.StringField(),
        'vnic_type': fields.StringField(),  # TODO(sean-k-mooney): make enum?
        'vif_type': fields.StringField(),
        # vif_details is a dict whose contents are dependent on the vif_type
        # and can be any number of types for the values, so we just store it
        # as a serialized dict
        'vif_details_json': fields.StringField(),
        # profile is in the same random dict of terrible boat as vif_details
        # so it's stored as a serialized json string
        'profile_json': fields.StringField(),
        'host': fields.StringField(),
        # The source_vif attribute is a copy of the VIF network model
        # representation of the port on the source host which can be used
        # for filling in blanks about the VIF (port) when building a
        # configuration reference for the destination host.
        # NOTE(mriedem): This might not be sufficient based on how the
        # destination host is configured for all vif types. See the note in
        # the libvirt driver here: https://review.openstack.org/#/c/551370/
        # 29/nova/virt/libvirt/driver.py@7036
        'source_vif': fields.Field(fields.NetworkVIFModel()),
    }

    @property
    def vif_details(self):
        return jsonutils.loads(self.vif_details_json)

    @vif_details.setter
    def vif_details(self, vif_details_dict):
        self.vif_details_json = jsonutils.dumps(vif_details_dict)

    @property
    def profile(self):
        return jsonutils.loads(self.profile_json)

    @profile.setter
    def profile(self, profile_dict):
        self.profile_json = jsonutils.dumps(profile_dict)

    def get_dest_vif(self):
        """Get a destination VIF representation of this object.

        This method takes the source_vif and updates it to include the
        destination host port binding information using the other fields
        on this object.

        :return: nova.network.model.VIF object
        """
        if 'source_vif' not in self:
            raise exception.ObjectActionError(action='get_dest_vif',
                                              reason='source_vif is not set')
        vif = copy.deepcopy(self.source_vif)
        vif['type'] = self.vif_type
        vif['vnic_type'] = self.vnic_type
        vif['profile'] = self.profile
        vif['details'] = self.vif_details
        return vif
class InstanceInfoCache(base.NovaPersistentObject, base.NovaObject,
                        base.NovaObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Converted network_info to store the model.
    # Version 1.2: Added new() and update_cells kwarg to save().
    # Version 1.3: Added delete()
    # Version 1.4: String attributes updated to support unicode
    # Version 1.5: Actually set the deleted, created_at, updated_at, and
    #              deleted_at attributes
    VERSION = '1.5'

    fields = {
        'instance_uuid': fields.UUIDField(),
        'network_info': fields.Field(fields.NetworkModel(), nullable=True),
    }

    @staticmethod
    def _from_db_object(context, info_cache, db_obj):
        for field in info_cache.fields:
            info_cache[field] = db_obj[field]
        info_cache.obj_reset_changes()
        info_cache._context = context
        return info_cache

    @classmethod
    def new(cls, context, instance_uuid):
        """Create an InfoCache object that can be used to create the DB
        entry for the first time.

        When save()ing this object, the info_cache_update() DB call
        will properly handle creating it if it doesn't exist already.
        """
        info_cache = cls()
        info_cache.instance_uuid = instance_uuid
        info_cache.network_info = None
        info_cache._context = context
        # Leave the fields dirty
        return info_cache

    @base.remotable_classmethod
    def get_by_instance_uuid(cls, context, instance_uuid):
        db_obj = db.instance_info_cache_get(context, instance_uuid)
        if not db_obj:
            raise exception.InstanceInfoCacheNotFound(
                instance_uuid=instance_uuid)
        return cls._from_db_object(context, cls(context), db_obj)

    @staticmethod
    def _info_cache_cells_update(ctxt, info_cache):
        cell_type = cells_opts.get_cell_type()
        if cell_type != 'compute':
            return
        cells_api = cells_rpcapi.CellsAPI()
        try:
            cells_api.instance_info_cache_update_at_top(ctxt, info_cache)
        except Exception:
            LOG.exception(
                _LE("Failed to notify cells of instance info "
                    "cache update"))

    @base.remotable
    def save(self, update_cells=True):
        if 'network_info' in self.obj_what_changed():
            nw_info_json = self.fields['network_info'].to_primitive(
                self, 'network_info', self.network_info)
            rv = db.instance_info_cache_update(self._context,
                                               self.instance_uuid,
                                               {'network_info': nw_info_json})
            self._from_db_object(self._context, self, rv)
            if update_cells and rv:
                self._info_cache_cells_update(self._context, rv)
        self.obj_reset_changes()

    @base.remotable
    def delete(self):
        db.instance_info_cache_delete(self._context, self.instance_uuid)

    @base.remotable
    def refresh(self):
        current = self.__class__.get_by_instance_uuid(self._context,
                                                      self.instance_uuid)
        current._context = None

        for field in self.fields:
            if self.obj_attr_is_set(field) and self[field] != current[field]:
                self[field] = current[field]

        self.obj_reset_changes()
Exemple #18
0
 def setUp(self):
     super(TestNonNegativeInteger, self).setUp()
     self.field = fields.Field(fields.NonNegativeInteger())
     self.coerce_bad_values.extend(['-2', '4.2'])
class InstanceInfoCache(base.NovaPersistentObject, base.NovaObject):
    # Version 1.0: Initial version
    # Version 1.1: Converted network_info to store the model.
    # Version 1.2: Added new() and update_cells kwarg to save().
    # Version 1.3: Added delete()
    # Version 1.4: String attributes updated to support unicode
    # Version 1.5: Actually set the deleted, created_at, updated_at, and
    #              deleted_at attributes
    VERSION = '1.5'

    fields = {
        'instance_uuid': fields.UUIDField(),
        'network_info': fields.Field(fields.NetworkModel(), nullable=True),
    }

    @staticmethod
    def _from_db_object(context, info_cache, db_obj):
        for field in info_cache.fields:
            setattr(info_cache, field, db_obj[field])
        info_cache.obj_reset_changes()
        info_cache._context = context
        return info_cache

    @classmethod
    def new(cls, context, instance_uuid):
        """Create an InfoCache object that can be used to create the DB
        entry for the first time.

        When save()ing this object, the info_cache_update() DB call
        will properly handle creating it if it doesn't exist already.
        """
        info_cache = cls()
        info_cache.instance_uuid = instance_uuid
        info_cache.network_info = None
        info_cache._context = context
        # Leave the fields dirty
        return info_cache

    @base.remotable_classmethod
    def get_by_instance_uuid(cls, context, instance_uuid):
        db_obj = db.instance_info_cache_get(context, instance_uuid)
        if not db_obj:
            raise exception.InstanceInfoCacheNotFound(
                instance_uuid=instance_uuid)
        return cls._from_db_object(context, cls(context), db_obj)

    # TODO(stephenfin): Remove 'update_cells' in version 2.0
    @base.remotable
    def save(self, update_cells=True):
        if 'network_info' in self.obj_what_changed():
            nw_info_json = self.fields['network_info'].to_primitive(
                self, 'network_info', self.network_info)
            rv = db.instance_info_cache_update(self._context,
                                               self.instance_uuid,
                                               {'network_info': nw_info_json})
            self._from_db_object(self._context, self, rv)
        self.obj_reset_changes()

    @base.remotable
    def delete(self):
        db.instance_info_cache_delete(self._context, self.instance_uuid)

    @base.remotable
    def refresh(self):
        current = self.__class__.get_by_instance_uuid(self._context,
                                                      self.instance_uuid)
        current._context = None

        for field in self.fields:
            if (self.obj_attr_is_set(field)
                    and getattr(self, field) != getattr(current, field)):
                setattr(self, field, getattr(current, field))

        self.obj_reset_changes()
Exemple #20
0
 def setUp(self):
     super(TestNonNegativeFloat, self).setUp()
     self.field = fields.Field(fields.NonNegativeFloat())
     self.coerce_bad_values.extend(['-4.2'])
Exemple #21
0
class VIFMigrateData(obj_base.NovaObject):
    # Version 1.0: Initial version
    VERSION = '1.0'

    # The majority of the fields here represent a port binding on the
    # **destination** host during a live migration. The vif_type, among
    # other fields, could be different from the existing binding on the
    # source host, which is represented by the "source_vif" field.
    fields = {
        'port_id': fields.StringField(),
        'vnic_type': fields.StringField(),  # TODO(sean-k-mooney): make enum?
        'vif_type': fields.StringField(),
        # vif_details is a dict whose contents are dependent on the vif_type
        # and can be any number of types for the values, so we just store it
        # as a serialized dict
        'vif_details_json': fields.StringField(),
        # profile is in the same random dict of terrible boat as vif_details
        # so it's stored as a serialized json string
        'profile_json': fields.StringField(),
        'host': fields.StringField(),
        # The source_vif attribute is a copy of the VIF network model
        # representation of the port on the source host which can be used
        # for filling in blanks about the VIF (port) when building a
        # configuration reference for the destination host.
        # NOTE(mriedem): This might not be sufficient based on how the
        # destination host is configured for all vif types. See the note in
        # the libvirt driver here: https://review.opendev.org/#/c/551370/
        # 29/nova/virt/libvirt/driver.py@7036
        'source_vif': fields.Field(fields.NetworkVIFModel()),
    }

    @property
    def vif_details(self):
        if 'vif_details_json' not in self:
            return {}
        return jsonutils.loads(self.vif_details_json)

    @vif_details.setter
    def vif_details(self, vif_details_dict):
        self.vif_details_json = jsonutils.dumps(vif_details_dict)

    @property
    def profile(self):
        if 'profile_json' not in self:
            return {}
        return jsonutils.loads(self.profile_json)

    @profile.setter
    def profile(self, profile_dict):
        self.profile_json = jsonutils.dumps(profile_dict)

    @property
    def supports_os_vif_delegation(self):
        return self.profile.get(OS_VIF_DELEGATION, False)

    # TODO(stephenfin): add a proper delegation field instead of storing this
    # info in the profile catch-all blob
    @supports_os_vif_delegation.setter
    def supports_os_vif_delegation(self, supported):
        # we can't simply set the attribute using dict notation since the
        # getter returns a copy of the data, not the data itself
        self.profile = dict(self.profile or {},
                            **{OS_VIF_DELEGATION: supported})

    def get_dest_vif(self):
        """Get a destination VIF representation of this object.

        This method takes the source_vif and updates it to include the
        destination host port binding information using the other fields
        on this object.

        :return: nova.network.model.VIF object
        """
        if 'source_vif' not in self:
            raise exception.ObjectActionError(action='get_dest_vif',
                                              reason='source_vif is not set')
        vif = copy.deepcopy(self.source_vif)
        vif['type'] = self.vif_type
        vif['vnic_type'] = self.vnic_type
        vif['profile'] = self.profile
        vif['details'] = self.vif_details
        vif['delegate_create'] = self.supports_os_vif_delegation
        return vif

    @classmethod
    def create_skeleton_migrate_vifs(cls, vifs):
        """Create migrate vifs for live migration.

        :param vifs: a list of VIFs.
        :return: list of VIFMigrateData object corresponding to the provided
                 VIFs.
        """
        vif_mig_data = []

        for vif in vifs:
            mig_vif = cls(port_id=vif['id'], source_vif=vif)
            vif_mig_data.append(mig_vif)
        return vif_mig_data
Exemple #22
0
class MyObj(base.NovaPersistentObject, base.NovaObject):
    VERSION = '1.6'
    fields = {
        'foo': fields.Field(fields.Integer()),
        'bar': fields.Field(fields.String()),
        'missing': fields.Field(fields.String()),
        'readonly': fields.Field(fields.Integer(), read_only=True),
        'rel_object': fields.ObjectField('MyOwnedObject', nullable=True)
    }

    @staticmethod
    def _from_db_object(context, obj, db_obj):
        self = MyObj()
        self.foo = db_obj['foo']
        self.bar = db_obj['bar']
        self.missing = db_obj['missing']
        self.readonly = 1
        return self

    def obj_load_attr(self, attrname):
        setattr(self, attrname, 'loaded!')

    @base.remotable_classmethod
    def query(cls, context):
        obj = cls(foo=1, bar='bar')
        obj.obj_reset_changes()
        return obj

    @base.remotable
    def marco(self, context):
        return 'polo'

    @base.remotable
    def _update_test(self, context):
        if context.project_id == 'alternate':
            self.bar = 'alternate-context'
        else:
            self.bar = 'updated'

    @base.remotable
    def save(self, context):
        self.obj_reset_changes()

    @base.remotable
    def refresh(self, context):
        self.foo = 321
        self.bar = 'refreshed'
        self.obj_reset_changes()

    @base.remotable
    def modify_save_modify(self, context):
        self.bar = 'meow'
        self.save()
        self.foo = 42
        self.rel_object = MyOwnedObject(baz=42)

    def obj_make_compatible(self, primitive, target_version):
        # NOTE(danms): Simulate an older version that had a different
        # format for the 'bar' attribute
        if target_version == '1.1' and 'bar' in primitive:
            primitive['bar'] = 'old%s' % primitive['bar']
Exemple #23
0
class MyOwnedObject(base.NovaPersistentObject, base.NovaObject):
    VERSION = '1.0'
    fields = {'baz': fields.Field(fields.Integer())}
class InstanceInfoCache(base.NovaPersistentObject, base.NovaObject):
    # Version 1.0: Initial version
    # Version 1.1: Converted network_info to store the model.
    # Version 1.2: Added new() and update_cells kwarg to save().
    # Version 1.3: Added delete()
    # Version 1.4: String attributes updated to support unicode
    # Version 1.5: Actually set the deleted, created_at, updated_at, and
    #              deleted_at attributes
    VERSION = '1.5'

    fields = {
        'instance_uuid': fields.UUIDField(),
        'network_info': fields.Field(fields.NetworkModel(), nullable=True),
    }

    @staticmethod
    def _from_db_object(context, info_cache, db_obj):
        for field in info_cache.fields:
            setattr(info_cache, field, db_obj[field])
        info_cache.obj_reset_changes()
        info_cache._context = context
        return info_cache

    @classmethod
    def new(cls, context, instance_uuid):
        """Create an InfoCache object that can be used to create the DB
        entry for the first time.

        When save()ing this object, the info_cache_update() DB call
        will properly handle creating it if it doesn't exist already.
        """
        info_cache = cls()
        info_cache.instance_uuid = instance_uuid
        info_cache.network_info = None
        info_cache._context = context
        # Leave the fields dirty
        return info_cache

    @base.remotable_classmethod
    def get_by_instance_uuid(cls, context, instance_uuid):
        db_obj = db.instance_info_cache_get(context, instance_uuid)
        if not db_obj:
            raise exception.InstanceInfoCacheNotFound(
                instance_uuid=instance_uuid)
        return cls._from_db_object(context, cls(context), db_obj)

    # TODO(stephenfin): Remove 'update_cells' in version 2.0
    @base.remotable
    def save(self, update_cells=True):
        if 'network_info' in self.obj_what_changed():
            nw_info_json = self.fields['network_info'].to_primitive(
                self, 'network_info', self.network_info)

            inst_uuid = self.instance_uuid

            try:
                rv = db.instance_info_cache_update(
                    self._context, inst_uuid, {'network_info': nw_info_json})
            except db_exc.DBReferenceError as exp:
                if exp.key != 'instance_uuid':
                    raise
                # NOTE(melwitt): It is possible for us to fail here with a
                # foreign key constraint violation on instance_uuid when we
                # attempt to save the instance network info cache after
                # receiving a network-changed external event from neutron
                # during a cross-cell migration. This means the instance record
                # is not found in this cell database and we can raise
                # InstanceNotFound to signal that in a way that callers know
                # how to handle.
                raise exception.InstanceNotFound(instance_id=inst_uuid)

            self._from_db_object(self._context, self, rv)
        self.obj_reset_changes()

    @base.remotable
    def delete(self):
        db.instance_info_cache_delete(self._context, self.instance_uuid)

    @base.remotable
    def refresh(self):
        current = self.__class__.get_by_instance_uuid(self._context,
                                                      self.instance_uuid)
        current._context = None

        for field in self.fields:
            if (self.obj_attr_is_set(field)
                    and getattr(self, field) != getattr(current, field)):
                setattr(self, field, getattr(current, field))

        self.obj_reset_changes()