def setUp(self): super(FloatingIpsBulkTest, self).setUp() pool = CONF.default_floating_pool interface = CONF.public_interface self.ip_pool = [ { 'address': "10.10.10.1", 'pool': pool, 'interface': interface, 'host': None }, { 'address': "10.10.10.2", 'pool': pool, 'interface': interface, 'host': None }, { 'address': "10.10.10.3", 'pool': pool, 'interface': interface, 'host': "testHost" }, ] self.compute.db.floating_ip_bulk_create(context.get_admin_context(), self.ip_pool) self.addCleanup(self.compute.db.floating_ip_bulk_destroy, context.get_admin_context(), self.ip_pool)
def setUp(self): super(FloatingIpsBulkTest, self).setUp() pool = CONF.default_floating_pool interface = CONF.public_interface self.ip_pool = [ { 'address': "10.10.10.1", 'pool': pool, 'interface': interface, 'host': None }, { 'address': "10.10.10.2", 'pool': pool, 'interface': interface, 'host': None }, { 'address': "10.10.10.3", 'pool': pool, 'interface': interface, 'host': "testHost" }, ] self.compute.db.floating_ip_bulk_create( context.get_admin_context(), self.ip_pool) self.addCleanup(self.compute.db.floating_ip_bulk_destroy, context.get_admin_context(), self.ip_pool)
def test_service_enabled_on_create_based_on_flag(self): self.flags(enable_new_services=True) host = 'foo' binary = 'patron-fake' app = service.Service.create(host=host, binary=binary) app.start() app.stop() ref = db.service_get(context.get_admin_context(), app.service_id) db.service_destroy(context.get_admin_context(), app.service_id) self.assertFalse(ref['disabled'])
def test_post_start_hook_child_cell(self): self.mox.StubOutWithMock(self.driver, 'start_servers') self.mox.StubOutWithMock(context, 'get_admin_context') self.mox.StubOutWithMock(self.cells_manager, '_update_our_parents') self.driver.start_servers(self.msg_runner) context.get_admin_context().AndReturn(self.ctxt) self.cells_manager._update_our_parents(self.ctxt) self.mox.ReplayAll() self.cells_manager.post_start_hook()
def setUp(self): super(NetworkPolicyTestCase, self).setUp() policy.reset() policy.init() self.context = context.get_admin_context()
def ec2_snap_id_to_uuid(ec2_id): """Get the corresponding UUID for the given ec2-id.""" ctxt = context.get_admin_context() # NOTE(jgriffith) first strip prefix to get just the numeric int_id = ec2_id_to_id(ec2_id) return get_snapshot_uuid_from_int_id(ctxt, int_id)
def _create_instance_with_availability_zone(self, zone_name): def create(*args, **kwargs): self.assertIn('availability_zone', kwargs) self.assertEqual('patron', kwargs['availability_zone']) return old_create(*args, **kwargs) old_create = compute_api.API.create self.stubs.Set(compute_api.API, 'create', create) image_href = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' flavor_ref = ('http://localhost' + self.base_url + 'flavors/3') body = { 'server': { 'name': 'server_test', 'imageRef': image_href, 'flavorRef': flavor_ref, 'metadata': { 'hello': 'world', 'open': 'stack', }, 'availability_zone': zone_name, }, } admin_context = context.get_admin_context() db.service_create(admin_context, {'host': 'host1_zones', 'binary': "patron-compute", 'topic': 'compute', 'report_count': 0}) agg = db.aggregate_create(admin_context, {'name': 'agg1'}, {'availability_zone': 'patron'}) db.aggregate_host_add(admin_context, agg['id'], 'host1_zones') return self.req, body
def setUp(self): super(SchedulerReportClientTestCase, self).setUp() self.context = context.get_admin_context() self.flags(use_local=True, group='conductor') self.client = scheduler_report_client.SchedulerReportClient()
def test_attach_volume_to_server(self): self.stubs.Set(cinder.API, 'get', fakes.stub_volume_get) self.stubs.Set(cinder.API, 'check_attach', lambda *a, **k: None) self.stubs.Set(cinder.API, 'reserve_volume', lambda *a, **k: None) device_name = '/dev/vdd' bdm = objects.BlockDeviceMapping() bdm['device_name'] = device_name self.stubs.Set(compute_manager.ComputeManager, "reserve_block_device_name", lambda *a, **k: bdm) self.stubs.Set(compute_manager.ComputeManager, 'attach_volume', lambda *a, **k: None) self.stubs.Set(objects.BlockDeviceMapping, 'get_by_volume_id', classmethod(lambda *a, **k: None)) volume = fakes.stub_volume_get(None, context.get_admin_context(), 'a26887c6-c47b-4654-abb5-dfadf7d3f803') subs = { 'volume_id': volume['id'], 'device': device_name } server_id = self._post_server() response = self._do_post('servers/%s/os-volume_attachments' % server_id, 'attach-volume-to-server-req', subs) subs.update(self._get_regexes()) self._verify_response('attach-volume-to-server-resp', subs, response, 200)
def get_flavor_access_by_flavor_id(flavorid, ctxt=None): """Retrieve flavor access list by flavor id.""" if ctxt is None: ctxt = context.get_admin_context() flavor = objects.Flavor.get_by_flavor_id(ctxt, flavorid) return flavor.projects
def _create_fake_pci_device(self, ctxt=None): if not ctxt: ctxt = context.get_admin_context() self.mox.StubOutWithMock(db, 'pci_device_get_by_addr') db.pci_device_get_by_addr(ctxt, 1, 'a').AndReturn(fake_db_dev) self.mox.ReplayAll() self.pci_device = pci_device.PciDevice.get_by_dev_addr(ctxt, 1, 'a')
def _metadata_as_json(self, version, path): metadata = {'uuid': self.uuid} if self.launch_metadata: metadata['meta'] = self.launch_metadata if self.files: metadata['files'] = self.files if self.extra_md: metadata.update(self.extra_md) if self.network_config: metadata['network_config'] = self.network_config if self.instance.key_name: metadata['public_keys'] = { self.instance.key_name: self.instance.key_data } keypair = keypair_obj.KeyPair.get_by_name( context.get_admin_context(), self.instance.user_id, self.instance.key_name) metadata['keys'] = [ {'name': keypair.name, 'type': keypair.type, 'data': keypair.public_key} ] metadata['hostname'] = self._get_hostname() metadata['name'] = self.instance.display_name metadata['launch_index'] = self.instance.launch_index metadata['availability_zone'] = self.availability_zone if self._check_os_version(GRIZZLY, version): metadata['random_seed'] = base64.b64encode(os.urandom(512)) self.set_mimetype(MIME_TYPE_APPLICATION_JSON) return jsonutils.dumps(metadata)
def test_deallocate_for_instance(self): instance = fake_instance.fake_instance_obj(context.get_admin_context()) self._test_network_api('deallocate_for_instance', rpc_method='call', requested_networks=self.DefaultArg(None), instance=instance, version='1.11')
def test_flavor_manage_permissions(self): """Ensure that regular users can't create or delete flavors. """ ctx = context.get_admin_context() flav1 = {'flavor': rand_flavor()} # Ensure user can't create flavor resp = self.user_api.api_post('flavors', flav1, check_response_status=False) self.assertEqual(403, resp.status) # ... and that it didn't leak through self.assertRaises(ex.FlavorNotFound, db.flavor_get_by_flavor_id, ctx, flav1['flavor']['id']) # Create the flavor as the admin user self.api.api_post('flavors', flav1) # Ensure user can't delete flavors from our cloud resp = self.user_api.api_delete('flavors/%s' % flav1['flavor']['id'], check_response_status=False) self.assertEqual(403, resp.status) # ... and ensure that we didn't actually delete the flavor, # this will throw an exception if we did. db.flavor_get_by_flavor_id(ctx, flav1['flavor']['id'])
def _init_aggregates(self): elevated = context_module.get_admin_context() aggs = objects.AggregateList.get_all(elevated) for agg in aggs: self.aggs_by_id[agg.id] = agg for host in agg.hosts: self.host_aggregates_map[host].add(agg.id)
def _async_init_instance_info(): context = context_module.get_admin_context() LOG.debug("START:_async_init_instance_info") self._instance_info = {} compute_nodes = objects.ComputeNodeList.get_all(context).objects LOG.debug("Total number of compute nodes: %s", len(compute_nodes)) # Break the queries into batches of 10 to reduce the total number # of calls to the DB. batch_size = 10 start_node = 0 end_node = batch_size while start_node <= len(compute_nodes): curr_nodes = compute_nodes[start_node:end_node] start_node += batch_size end_node += batch_size filters = {"host": [curr_node.host for curr_node in curr_nodes]} result = objects.InstanceList.get_by_filters(context, filters) instances = result.objects LOG.debug("Adding %s instances for hosts %s-%s", len(instances), start_node, end_node) for instance in instances: host = instance.host if host not in self._instance_info: self._instance_info[host] = {"instances": {}, "updated": False} inst_dict = self._instance_info[host] inst_dict["instances"][instance.uuid] = instance # Call sleep() to cooperatively yield time.sleep(0) LOG.debug("END:_async_init_instance_info")
def test_list_resizing_instances(self): instances = [{'image_ref': '1', 'host': CONF.host, 'id': '1', 'uuid': '123', 'vm_state': vm_states.RESIZED, 'task_state': None}] all_instances = [fake_instance.fake_instance_obj(None, **instance) for instance in instances] image_cache_manager = imagecache.ImageCacheManager() self.mox.StubOutWithMock(objects.block_device.BlockDeviceMappingList, 'get_by_instance_uuid') ctxt = context.get_admin_context() objects.block_device.BlockDeviceMappingList.get_by_instance_uuid( ctxt, '123').AndReturn(swap_bdm_256) self.mox.ReplayAll() running = image_cache_manager._list_running_instances(ctxt, all_instances) self.assertEqual(1, len(running['used_images'])) self.assertEqual((1, 0, ['instance-00000001']), running['used_images']['1']) self.assertEqual(set(['instance-00000001', '123', 'instance-00000001_resize', '123_resize']), running['instance_names']) self.assertEqual(1, len(running['image_popularity'])) self.assertEqual(1, running['image_popularity']['1'])
def _create_instance_with_availability_zone(self, zone_name): def create(*args, **kwargs): self.assertIn('availability_zone', kwargs) self.assertEqual('patron', kwargs['availability_zone']) return old_create(*args, **kwargs) old_create = compute_api.API.create self.stubs.Set(compute_api.API, 'create', create) image_href = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' flavor_ref = ('http://localhost' + self.base_url + 'flavors/3') body = { 'server': { 'name': 'server_test', 'imageRef': image_href, 'flavorRef': flavor_ref, 'metadata': { 'hello': 'world', 'open': 'stack', }, 'availability_zone': zone_name, }, } admin_context = context.get_admin_context() db.service_create( admin_context, { 'host': 'host1_zones', 'binary': "patron-compute", 'topic': 'compute', 'report_count': 0 }) agg = db.aggregate_create(admin_context, {'name': 'agg1'}, {'availability_zone': 'patron'}) db.aggregate_host_add(admin_context, agg['id'], 'host1_zones') return self.req, body
def setUp(self): super(ExtendedFloatingIpTestV21, self).setUp() self.stubs.Set(compute.api.API, "get", compute_api_get) self.stubs.Set(network.api.API, "get_floating_ip", network_api_get_floating_ip) self.stubs.Set(network.api.API, "get_floating_ip_by_address", network_api_get_floating_ip_by_address) self.stubs.Set(network.api.API, "get_floating_ips_by_project", network_api_get_floating_ips_by_project) self.stubs.Set(network.api.API, "release_floating_ip", network_api_release) self.stubs.Set(network.api.API, "disassociate_floating_ip", network_api_disassociate) self.stubs.Set(network.api.API, "get_instance_id_by_floating_address", get_instance_by_floating_ip_addr) self.stubs.Set(compute_utils, "get_nw_info_for_instance", stub_nw_info(self.stubs)) fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs) self.stubs.Set(db, 'instance_get', fake_instance_get) self.context = context.get_admin_context() self._create_floating_ips() self.ext_mgr = extensions.ExtensionManager() self.ext_mgr.extensions = {} self.ext_mgr.extensions['os-floating-ips'] = True self.ext_mgr.extensions['os-extended-floating-ips'] = True self.controller = self.floating_ips.FloatingIPController() self.manager = self.floating_ips.\ FloatingIPActionController(self.ext_mgr) self.fake_req = fakes.HTTPRequest.blank('')
def kill(self): """Destroy the service object in the datastore.""" self.stop() try: self.conductor_api.service_destroy(context.get_admin_context(), self.service_id) except exception.NotFound: LOG.warning(_LW("Service killed that has no database entry"))
def __init__(self, host, binary, topic, manager, report_interval=None, periodic_enable=None, periodic_fuzzy_delay=None, periodic_interval_max=None, db_allowed=True, *args, **kwargs): super(Service, self).__init__() self.host = host self.binary = binary self.topic = topic self.manager_class_name = manager # NOTE(russellb) We want to make sure to create the servicegroup API # instance early, before creating other things such as the manager, # that will also create a servicegroup API instance. Internally, the # servicegroup only allocates a single instance of the driver API and # we want to make sure that our value of db_allowed is there when it # gets created. For that to happen, this has to be the first instance # of the servicegroup API. self.servicegroup_api = servicegroup.API(db_allowed=db_allowed) manager_class = importutils.import_class(self.manager_class_name) self.manager = manager_class(host=self.host, *args, **kwargs) self.rpcserver = None self.report_interval = report_interval self.periodic_enable = periodic_enable self.periodic_fuzzy_delay = periodic_fuzzy_delay self.periodic_interval_max = periodic_interval_max self.saved_args, self.saved_kwargs = args, kwargs self.backdoor_port = None self.conductor_api = conductor.API(use_local=db_allowed) self.conductor_api.wait_until_ready(context.get_admin_context())
def test_deallocate_for_instance_with_expected_networks(self): instance = fake_instance.fake_instance_obj(context.get_admin_context()) self._test_network_api('deallocate_for_instance', rpc_method='call', instance=instance, requested_networks={}, version='1.11')
def setUp(self): super(FloatingIpDNSTestV21, self).setUp() self.stubs.Set(network.api.API, "get_dns_domains", network_get_dns_domains) self.stubs.Set(network.api.API, "get_dns_entries_by_address", network_get_dns_entries_by_address) self.stubs.Set(network.api.API, "get_dns_entries_by_name", network_get_dns_entries_by_name) self.stubs.Set(network.api.API, "get_floating_ip", network_api_get_floating_ip) self.stubs.Set(network.api.API, "add_dns_entry", network_add_dns_entry) self.stubs.Set(network.api.API, "modify_dns_entry", network_modify_dns_entry) self.stubs.Set(network.api.API, "create_public_dns_domain", network_create_public_dns_domain) self.stubs.Set(network.api.API, "create_private_dns_domain", network_create_private_dns_domain) self.context = context.get_admin_context() self._create_floating_ip() temp = self.floating_ip_dns.FloatingIPDNSDomainController() self.domain_controller = temp self.entry_controller = self.floating_ip_dns.\ FloatingIPDNSEntryController() self.req = fakes.HTTPRequest.blank('')
def init_host_floating_ips(self): """Configures floating ips owned by host.""" admin_context = context.get_admin_context() try: floating_ips = objects.FloatingIPList.get_by_host(admin_context, self.host) except exception.NotFound: return for floating_ip in floating_ips: if floating_ip.fixed_ip_id: try: fixed_ip = floating_ip.fixed_ip except exception.FixedIpNotFound: LOG.debug('Fixed ip %s not found', floating_ip.fixed_ip_id) continue interface = CONF.public_interface or floating_ip.interface try: self.l3driver.add_floating_ip(floating_ip.address, fixed_ip.address, interface, fixed_ip.network) except processutils.ProcessExecutionError: LOG.debug('Interface %s not found', interface) raise exception.NoFloatingIpInterface(interface=interface)
def test_attach_volume_to_server(self): self.stubs.Set(cinder.API, 'get', fakes.stub_volume_get) self.stubs.Set(cinder.API, 'check_attach', lambda *a, **k: None) self.stubs.Set(cinder.API, 'reserve_volume', lambda *a, **k: None) device_name = '/dev/vdd' bdm = objects.BlockDeviceMapping() bdm['device_name'] = device_name self.stubs.Set(compute_manager.ComputeManager, "reserve_block_device_name", lambda *a, **k: bdm) self.stubs.Set(compute_manager.ComputeManager, 'attach_volume', lambda *a, **k: None) self.stubs.Set(objects.BlockDeviceMapping, 'get_by_volume_id', classmethod(lambda *a, **k: None)) volume = fakes.stub_volume_get(None, context.get_admin_context(), 'a26887c6-c47b-4654-abb5-dfadf7d3f803') subs = {'volume_id': volume['id'], 'device': device_name} server_id = self._post_server() response = self._do_post( 'servers/%s/os-volume_attachments' % server_id, 'attach-volume-to-server-req', subs) subs.update(self._get_regexes()) self._verify_response('attach-volume-to-server-resp', subs, response, 200)
def revoke_certs_by_project(project_id): """Revoke all project certs.""" # NOTE(vish): This is somewhat useless because we can just shut down # the vpn. admin = context.get_admin_context() for cert in db.certificate_get_all_by_project(admin, project_id): revoke_cert(cert['project_id'], cert['file_name'])
def test_get_instances_security_groups_bindings(self): servers = [{'id': test_security_groups.FAKE_UUID1}, {'id': test_security_groups.FAKE_UUID2}] sg1 = self._create_sg_template(name='test1').get('security_group') sg2 = self._create_sg_template(name='test2').get('security_group') # test name='' is replaced with id sg3 = self._create_sg_template(name='').get('security_group') net = self._create_network() self._create_port( network_id=net['network']['id'], security_groups=[sg1['id'], sg2['id']], device_id=test_security_groups.FAKE_UUID1) self._create_port( network_id=net['network']['id'], security_groups=[sg2['id'], sg3['id']], device_id=test_security_groups.FAKE_UUID2) expected = {test_security_groups.FAKE_UUID1: [{'name': sg1['name']}, {'name': sg2['name']}], test_security_groups.FAKE_UUID2: [{'name': sg2['name']}, {'name': sg3['id']}]} security_group_api = self.controller.security_group_api bindings = ( security_group_api.get_instances_security_groups_bindings( context.get_admin_context(), servers)) self.assertEqual(bindings, expected)
def setUp(self): super(FloatingIPBulkV21, self).setUp() self.context = context.get_admin_context() self.controller = self.floating_ips_bulk.FloatingIPBulkController() self.req = fakes.HTTPRequest.blank('') self.admin_req = fakes.HTTPRequest.blank('', use_admin_context=True)
def _async_init_instance_info(): context = context_module.get_admin_context() LOG.debug("START:_async_init_instance_info") self._instance_info = {} compute_nodes = objects.ComputeNodeList.get_all(context).objects LOG.debug("Total number of compute nodes: %s", len(compute_nodes)) # Break the queries into batches of 10 to reduce the total number # of calls to the DB. batch_size = 10 start_node = 0 end_node = batch_size while start_node <= len(compute_nodes): curr_nodes = compute_nodes[start_node:end_node] start_node += batch_size end_node += batch_size filters = { "host": [curr_node.host for curr_node in curr_nodes] } result = objects.InstanceList.get_by_filters(context, filters) instances = result.objects LOG.debug("Adding %s instances for hosts %s-%s", len(instances), start_node, end_node) for instance in instances: host = instance.host if host not in self._instance_info: self._instance_info[host] = { "instances": {}, "updated": False } inst_dict = self._instance_info[host] inst_dict["instances"][instance.uuid] = instance # Call sleep() to cooperatively yield time.sleep(0) LOG.debug("END:_async_init_instance_info")
def test_flavor_manage_func(self): """Basic flavor creation lifecycle testing. - Creating a flavor - Ensure it's in the database - Ensure it's in the listing - Delete it - Ensure it's hidden in the database """ ctx = context.get_admin_context() flav1 = { 'flavor': rand_flavor(), } # Create flavor and ensure it made it to the database self.api.api_post('flavors', flav1) flav1db = db.flavor_get_by_flavor_id(ctx, flav1['flavor']['id']) self.assertFlavorDbEqual(flav1['flavor'], flav1db) # Ensure new flavor is seen in the listing resp = self.api.api_get('flavors') self.assertFlavorInList(flav1['flavor'], resp.body) # Delete flavor and ensure it was removed from the database self.api.api_delete('flavors/%s' % flav1['flavor']['id']) self.assertRaises(ex.FlavorNotFound, db.flavor_get_by_flavor_id, ctx, flav1['flavor']['id']) resp = self.api.api_delete('flavors/%s' % flav1['flavor']['id'], check_response_status=False) self.assertEqual(404, resp.status)
def _save_instance_password_if_sshkey_present(self, new_pass): sshkey = self.instance.get('key_data') if sshkey and sshkey.startswith("ssh-rsa"): ctxt = context.get_admin_context() enc = crypto.ssh_encrypt_text(sshkey, new_pass) self.instance.system_metadata.update( password.convert_password(ctxt, base64.b64encode(enc))) self.instance.save()
def _create_fake_pci_device(self): def fake_pci_device_get_by_addr(ctxt, id, addr): return test_pci_device.fake_db_dev ctxt = context.get_admin_context() self.stubs.Set(db, 'pci_device_get_by_addr', fake_pci_device_get_by_addr) self.pci_device = objects.PciDevice.get_by_dev_addr(ctxt, 1, 'a')
def get_metadata_by_address(conductor_api, address): ctxt = context.get_admin_context() fixed_ip = network.API().get_fixed_ip_by_address(ctxt, address) return get_metadata_by_instance_id(conductor_api, fixed_ip['instance_uuid'], address, ctxt)
def test_get_by_id(self): ctxt = context.get_admin_context() fake_migration = fake_db_migration() self.mox.StubOutWithMock(db, 'migration_get') db.migration_get(ctxt, fake_migration['id']).AndReturn(fake_migration) self.mox.ReplayAll() mig = migration.Migration.get_by_id(ctxt, fake_migration['id']) self.compare_obj(mig, fake_migration)
def id_to_ec2_vol_id(volume_id): """Get or create an ec2 volume ID (vol-[base 16 number]) from uuid.""" if uuidutils.is_uuid_like(volume_id): ctxt = context.get_admin_context() int_id = get_int_id_from_volume_uuid(ctxt, volume_id) return id_to_ec2_id(int_id, 'vol-%08x') else: return id_to_ec2_id(volume_id, 'vol-%08x')
def _force_reclaim(self): # Make sure that compute manager thinks the instance is # old enough to be expired the_past = timeutils.utcnow() + datetime.timedelta(hours=1) timeutils.set_time_override(override_time=the_past) self.addCleanup(timeutils.clear_time_override) ctxt = context.get_admin_context() self.compute._reclaim_queued_deletes(ctxt)
def setUp(self): super(TestUpdateInstanceCache, self).setUp() self.context = context.get_admin_context() self.instance = objects.Instance(uuid=FAKE_UUID) vifs = [network_model.VIF(id='super_vif')] self.nw_info = network_model.NetworkInfo(vifs) self.nw_json = fields.NetworkModel.to_primitive(self, 'network_info', self.nw_info)
def kill(self): """Destroy the service object in the datastore.""" self.stop() try: self.conductor_api.service_destroy(context.get_admin_context(), self.service_id) except exception.NotFound: LOG.warning(_LW('Service killed that has no database entry'))
def setUp(self): super(AvailabilityZoneTestCases, self).setUp() self.host = 'me' self.availability_zone = 'patron-test' self.default_az = CONF.default_availability_zone self.default_in_az = CONF.internal_service_availability_zone self.context = context.get_admin_context() self.agg = self._create_az('az_agg', self.availability_zone)
def setUp(self): super(VolumeApiTestV2, self).setUp() self.flags( osapi_compute_extension=[ 'patron.api.openstack.compute.contrib.select_extensions'], osapi_compute_ext_list=['Volumes']) self.context = context.get_admin_context() self.app = self._get_app()
def test_config_drive_update_instance(self, mock_required): inst = fake_instance.fake_instance_obj(context.get_admin_context()) inst.config_drive = '' configdrive.update_instance(inst) self.assertTrue(inst.config_drive) inst.config_drive = True configdrive.update_instance(inst) self.assertTrue(inst.config_drive)
def test_get_by_dev_id(self): ctxt = context.get_admin_context() self.mox.StubOutWithMock(db, 'pci_device_get_by_id') db.pci_device_get_by_id(ctxt, 1).AndReturn(fake_db_dev) self.mox.ReplayAll() self.pci_device = pci_device.PciDevice.get_by_dev_id(ctxt, 1) self.assertEqual(self.pci_device.product_id, 'p') self.assertEqual(self.pci_device.obj_what_changed(), set()) self.assertRemotes()