def test_create_backup_with_volumes(self, mock_cinder_client, mock_nova_client, mock_glance_client, mock_neutron_client): vm_resource = Resource(id="vm_id_2", type=constants.SERVER_RESOURCE_TYPE, name="fake_vm") protect_operation = self.plugin.get_protect_operation(vm_resource) mock_cinder_client.return_value = self.cinder_client mock_nova_client.return_value = self.nova_client mock_glance_client.return_value = self.glance_client mock_neutron_client.return_value = self.neutron_client checkpoint = Checkpoint() checkpoint.resource_graph = [ FakeGraphNode(value=Resource(type='OS::Nova::Server', id='vm_id_2', name='None'), child_nodes=[ FakeGraphNode(value=Resource( type='OS::Cinder::Volume', id='vol_id_1', name=None), child_nodes=()) ]) ] call_hooks(protect_operation, checkpoint, vm_resource, self.cntxt, {}) self.assertEqual( constants.RESOURCE_STATUS_AVAILABLE, fake_bank._plugin. _objects["/resource_data/checkpoint_id/vm_id_2/status"]) resource_definition = { "resource_id": "vm_id_2", 'boot_metadata': { 'boot_device_type': 'volume' }, "server_metadata": { "availability_zone": "nova", "networks": ["network_id_2"], "floating_ips": [], "flavor": "flavor_id", "key_name": None, "security_groups": "default", }, 'attach_metadata': { 'vol_id_1': { 'attachment_id': '', 'bootable': '', 'device': '/dev/vdb', 'host_name': '', 'id': 'attach_id_1', 'server_id': 'vm_id_2', 'volume_id': 'vol_id_1' } }, } self.assertEqual( fake_bank._plugin. _objects["/resource_data/checkpoint_id/vm_id_2/metadata"], resource_definition)
def test_graph_building(self): A = Resource(_FAKE_TYPE, "A", 'nameA') B = Resource(_FAKE_TYPE, "B", 'nameB') C = Resource(_FAKE_TYPE, "C", 'nameC') test_matrix = ( ( {A: [B], B: [C], C: []}, (A, C) ), ( {A: [C], B: [C], C: []}, (A, C) ), ) for g, resources in test_matrix: self._fake_plugin.graph = g result_graph = self.protectable_registry.build_graph(None, resources) self.assert_graph(result_graph, g) self.protectable_registry._protectable_map = {}
def test_list_resources(self, mock_volume_list): plugin = VolumeProtectablePlugin(self._context) mock_volume_list.return_value = \ [vol_info('123', [], 'name123'), vol_info('456', [], 'name456')] self.assertEqual([Resource('OS::Cinder::Volume', '123', 'name123'), Resource('OS::Cinder::Volume', '456', 'name456')], plugin.list_resources(self._context))
def test_get_dependent_resources(self, mock_server_list): plugin = ServerProtectablePlugin(self._context) server_info = collections.namedtuple('server_info', ['id', 'name']) mock_server_list.return_value = [ server_info(id='123', name='name123'), server_info(id='456', name='name456')] self.assertEqual([Resource('OS::Nova::Server', '123', 'name123'), Resource('OS::Nova::Server', '456', 'name456')], plugin.get_dependent_resources(self._context, None))
def test_get_server_dependent_resources(self, mock_volume_list): plugin = VolumeProtectablePlugin(self._context) attached = [{'server_id': 'abcdef', 'name': 'name'}] mock_volume_list.return_value = [ vol_info('123', attached, 'name123'), vol_info('456', [], 'name456'), ] self.assertEqual([Resource('OS::Cinder::Volume', '123', 'name123')], plugin.get_dependent_resources( self._context, Resource("OS::Nova::Server", 'abcdef', 'name')))
def test_list_resources(self, mock_volume_list): plugin = VolumeProtectablePlugin(self._context) mock_volume_list.return_value = [ vol_info('123', [], 'name123', 'available', 'az1'), vol_info('456', [], 'name456', 'available', 'az1'), ] self.assertEqual([ Resource('OS::Cinder::Volume', '123', 'name123', {'availability_zone': 'az1'}), Resource('OS::Cinder::Volume', '456', 'name456', {'availability_zone': 'az1'}) ], plugin.list_resources(self._context))
def test_list_resources(self, mock_instance_list): plugin = DatabaseInstanceProtectablePlugin(self._context) instance_info = collections.namedtuple('instance_info', ['id', 'name', 'status']) mock_instance_list.return_value = [ instance_info(id='123', name='name123', status='ACTIVE'), instance_info(id='456', name='name456', status='ACTIVE') ] self.assertEqual([ Resource('OS::Trove::Instance', '123', 'name123'), Resource('OS::Trove::Instance', '456', 'name456') ], plugin.list_resources(self._context))
def test_list_resources(self, mock_share_list): plugin = ShareProtectablePlugin(self._context) share_info = collections.namedtuple('share_info', ['id', 'name', 'status']) mock_share_list.return_value = [ share_info(id='123', name='name123', status='available'), share_info(id='456', name='name456', status='available') ] self.assertEqual([ Resource('OS::Manila::Share', '123', 'name123'), Resource('OS::Manila::Share', '456', 'name456') ], plugin.list_resources(self._context))
def test_list_protectable_instances(self, mocker): mocker.return_value = [Resource(type='OS::Nova::Server', id='123456', name='name123'), Resource(type='OS::Nova::Server', id='654321', name='name654')] fake_cntx = mock.MagicMock() result = self.pro_manager.list_protectable_instances( fake_cntx, 'OS::Nova::Server') self.assertEqual([{'id': '123456', 'name': 'name123'}, {'id': '654321', 'name': 'name654'}], result)
def test_list_protectable_dependents(self, mocker): mocker.return_value = [Resource(type='OS::Cinder::Volume', id='123456', name='name123'), Resource(type='OS::Cinder::Volume', id='654321', name='name654')] fake_cntx = mock.MagicMock() result = self.pro_manager.list_protectable_dependents( fake_cntx, 'fake_id', 'OS::Nova::Server') self.assertEqual([{'type': 'OS::Cinder::Volume', 'id': '123456', 'name': 'name123', 'extra_info': None}, {'type': 'OS::Cinder::Volume', 'id': '654321', 'name': 'name654', 'extra_info': None}], result)
def test_create_backup_with_volumes(self): vm_resource = Resource(id="vm_id_2", type=constants.SERVER_RESOURCE_TYPE, name="fake_vm") vol_resource = Resource(id="vol_id_1", type=constants.VOLUME_RESOURCE_TYPE, name="fake_vol") vol_node = ResourceNode(value=vol_resource, child_nodes=[]) vm_node = ResourceNode(value=vm_resource, child_nodes=[vol_node]) backup_name = "fake_backup" self.plugin._cinder_client = mock.MagicMock() self.plugin._cinder_client.return_value = self.cinder_client self.plugin._nova_client = mock.MagicMock() self.plugin._nova_client.return_value = self.nova_client self.plugin._glance_client = mock.MagicMock() self.plugin._glance_client.return_value = self.glance_client self.plugin._neutron_client = mock.MagicMock() self.plugin._neutron_client.return_value = self.neutron_client self.plugin.create_backup(self.cntxt, self.checkpoint, node=vm_node, backup_name=backup_name) self.assertEqual( fake_bank._plugin. _objects["/resource_data/checkpoint_id/vm_id_2/status"], constants.RESOURCE_STATUS_PROTECTING) resource_definition = { "resource_id": "vm_id_2", "attach_metadata": { "vol_id_1": "/dev/vdb" }, "server_metadata": { "availability_zone": "nova", "networks": ["network_id_2"], "floating_ips": [], "flavor": "flavor_id", "key_name": None, "security_groups": "default", }, } self.assertEqual( fake_bank._plugin. _objects["/resource_data/checkpoint_id/vm_id_2/metadata"], resource_definition)
def test_list_resources(self, mock_server_list, mock_generate_session): plugin = ServerProtectablePlugin(self._context) mock_generate_session.return_value = keystone_session.Session( auth=None) server_info = collections.namedtuple('server_info', ['id', 'name', 'status']) mock_server_list.return_value = [ server_info(id='123', name='name123', status='ACTIVE'), server_info(id='456', name='name456', status='ACTIVE') ] self.assertEqual([ Resource('OS::Nova::Server', '123', 'name123'), Resource('OS::Nova::Server', '456', 'name456') ], plugin.list_resources(self._context))
def get_flow(context, protectable_registry, workflow_engine, plan, provider, checkpoint): # The 'extra-info' field of resources in plan is optional # The extra_info field of the resource is a dict. # The dict can not be handled by build_graph. It will throw a # error. TypeError: unhashable type: 'dict' resources = set() for item in plan.get("resources"): item["extra_info"] = None resources.add(Resource(**item)) resource_graph = protectable_registry.build_graph(context, resources) checkpoint.resource_graph = resource_graph checkpoint.commit() flow_name = "Protect_" + plan.get('id') protection_flow = workflow_engine.build_flow(flow_name, 'linear') plugins = provider.load_plugins() resources_task_flow = resource_flow.build_resource_flow( operation_type=constants.OPERATION_PROTECT, context=context, workflow_engine=workflow_engine, resource_graph=resource_graph, plugins=plugins, parameters=plan.get('parameters'), ) workflow_engine.add_tasks( protection_flow, InitiateProtectTask(), resources_task_flow, CompleteProtectTask(), ) flow_engine = workflow_engine.get_engine(protection_flow, store={'checkpoint': checkpoint}) return flow_engine
def test_protect_fail_volume(self, mock_cinder_create): resource = Resource( id="123", type=constants.VOLUME_RESOURCE_TYPE, name="test", ) checkpoint = self._get_checkpoint() operation = self.plugin.get_protect_operation(resource) mock_cinder_create.return_value = self.cinder_client with mock.patch.multiple( self.cinder_client, volumes=mock.DEFAULT, backups=mock.DEFAULT, volume_snapshots=mock.DEFAULT, ) as mocks: mocks['volumes'].get.return_value = mock.Mock() mocks['volumes'].get.return_value.status = 'error' mocks['backups'].backups.create = BackupResponse( '456', 'creating', '---', 0) mocks['backups'].backups.get = BackupResponse( '456', 'error', 'creating', 2) mocks['volume_snapshots'].get.return_value = BackupResponse( '789', 'creating', '---', 0) mocks['volume_snapshots'].get = BackupResponse( '789', 'available', 'creating', 2) self.assertRaises(exception.CreateBackupFailed, call_hooks, operation, checkpoint, resource, self.cntxt, {})
def get_flow(context, workflow_engine, operation_type, plan, provider, checkpoint): protectable_registry = ProtectableRegistry() resources = set(Resource(**item) for item in plan.get("resources")) resource_graph = protectable_registry.build_graph(context, resources) checkpoint.resource_graph = resource_graph checkpoint.commit() flow_name = "Protect_" + plan.get('id') protection_flow = workflow_engine.build_flow(flow_name, 'linear') plugins = provider.load_plugins() resources_task_flow = resource_flow.build_resource_flow( operation_type=operation_type, context=context, workflow_engine=workflow_engine, resource_graph=resource_graph, plugins=plugins, parameters=plan.get('parameters'), ) workflow_engine.add_tasks( protection_flow, InitiateProtectTask(), resources_task_flow, CompleteProtectTask(), ) flow_engine = workflow_engine.get_engine(protection_flow, store={'checkpoint': checkpoint}) return flow_engine
def list_protectable_dependents(self, context, protectable_id, protectable_type): LOG.info( "Start to list dependents of resource (type:%(type)s, " "id:%(id)s)", { 'type': protectable_type, 'id': protectable_id }) parent_resource = Resource(type=protectable_type, id=protectable_id, name="", extra_info=None) registry = self.protectable_registry try: dependent_resources = registry.fetch_dependent_resources( context, parent_resource) except exception.ListProtectableResourceFailed as err: LOG.error("List dependent resources of (%(res)s) failed: %(err)s", { 'res': parent_resource, 'err': six.text_type(err) }) raise result = [] for resource in dependent_resources: result.append( dict(type=resource.type, id=resource.id, name=resource.name, extra_info=resource.extra_info)) return result
def test_protect_succeed(self, mock_cinder_create): resource = Resource( id="123", type=constants.VOLUME_RESOURCE_TYPE, name="test", ) checkpoint = self._get_checkpoint() section = checkpoint.get_resource_bank_section() operation = self.plugin.get_protect_operation(resource) section.update_object = mock.MagicMock() mock_cinder_create.return_value = self.cinder_client with mock.patch.multiple( self.cinder_client, volumes=mock.DEFAULT, backups=mock.DEFAULT, volume_snapshots=mock.DEFAULT, ) as mocks: mocks['volumes'].get.return_value = mock.Mock() mocks['volumes'].get.return_value.status = 'available' mocks['backups'].create = BackupResponse('456', 'creating', '---', 0) mocks['backups'].get = BackupResponse('456', 'available', 'creating', 2) mocks['volume_snapshots'].get.return_value = BackupResponse( '789', 'creating', '---', 0) mocks['volume_snapshots'].get = BackupResponse( '789', 'available', 'creating', 2) call_hooks(operation, checkpoint, resource, self.cntxt, {})
def test_create_backup_with_server_id_in_extra_info( self, mock_glance_create, mock_nova_create, mock_status_poll, mock_generate_session): cfg.CONF.set_default('nova_endpoint', 'http://127.0.0.1:8774/v2.1', 'nova_client') self.nova_client = client_factory.ClientFactory.create_client( "nova", self.cntxt) mock_generate_session.return_value = keystone_session.Session( auth=None) resource = Resource(id="123", type=constants.IMAGE_RESOURCE_TYPE, name='fake', extra_info={'server_id': 'fake_server_id'}) protect_operation = self.plugin.get_protect_operation(resource) mock_glance_create.return_value = self.glance_client self.glance_client.images.get = mock.MagicMock() self.glance_client.images.return_value = Image(disk_format="", container_format="", status="active") mock_nova_create.return_value = self.nova_client self.nova_client.servers.get = mock.MagicMock() self.nova_client.servers.get.return_value = Server(status='ACTIVE') self.nova_client.servers.image_create = mock.MagicMock() self.nova_client.servers.image_create.return_value = '345' fake_bank_section.update_object = mock.MagicMock() self.glance_client.images.data = mock.MagicMock() self.glance_client.images.data.return_value = [] mock_status_poll.return_value = True call_hooks(protect_operation, self.checkpoint, resource, self.cntxt, {})
def get_flow(context, protectable_registry, workflow_engine, plan, provider, checkpoint): resources = set(Resource(**item) for item in plan.get("resources")) resource_graph = protectable_registry.build_graph(context, resources) checkpoint.resource_graph = resource_graph checkpoint.commit() operation_log = utils.create_operation_log(context, checkpoint) flow_name = "Protect_" + plan.get('id') protection_flow = workflow_engine.build_flow(flow_name, 'linear') plugins = provider.load_plugins() parameters = plan.get('parameters') resources_task_flow = resource_flow.build_resource_flow( operation_type=constants.OPERATION_PROTECT, context=context, workflow_engine=workflow_engine, resource_graph=resource_graph, plugins=plugins, parameters=parameters, ) workflow_engine.add_tasks( protection_flow, InitiateProtectTask(), resources_task_flow, CompleteProtectTask(), ) flow_engine = workflow_engine.get_engine(protection_flow, store={ 'context': context, 'checkpoint': checkpoint, 'operation_log': operation_log }) return flow_engine
def test_create_snapshot(self, mock_manila_create, mock_status_poll): resource = Resource(id="123", type=constants.SHARE_RESOURCE_TYPE, name='fake') fake_bank_section.update_object = mock.MagicMock() protect_operation = self.plugin.get_protect_operation(resource) mock_manila_create.return_value = self.manila_client self.manila_client.shares.get = mock.MagicMock() self.manila_client.shares.return_value = Share( status="available" ) fake_bank_section.update_object = mock.MagicMock() self.manila_client.share_snapshots.create = mock.MagicMock() self.manila_client.share_snapshots.create.return_value = Snapshot( id="1234", status="available" ) self.manila_client.share_snapshots.get = mock.MagicMock() self.manila_client.share_snapshots.get.return_value = Snapshot( id="1234", status="available" ) mock_status_poll.return_value = True call_hooks(protect_operation, self.checkpoint, resource, self.cntxt, {})
def test_create_backup(self, mock_freezer_create, mock_status_poll): resource = Resource(id="123", type=constants.VOLUME_RESOURCE_TYPE, name='fake') fake_bank_section.update_object = mock.MagicMock() protect_operation = self.plugin.get_protect_operation(resource) mock_freezer_create.return_value = self.freezer_client mock_status_poll.return_value = True self.freezer_client.clients.list = mock.MagicMock() self.freezer_client.clients.list.return_value = [ { 'client_id': 'fake_client_id' } ] self.freezer_client.jobs.create = mock.MagicMock() self.freezer_client.jobs.create.return_value = "123" self.freezer_client.jobs.start_job = mock.MagicMock() self.freezer_client.jobs.get = mock.MagicMock() self.freezer_client.jobs.get.return_value = { 'job_actions': [] } self.freezer_client.jobs.delete = mock.MagicMock() call_hooks(protect_operation, self.checkpoint, resource, self.cntxt, {})
def test_restore_fail_volume_1(self, mock_update_restore, mock_cinder_create): resource = Resource( id="123", type=constants.VOLUME_RESOURCE_TYPE, name="fake", ) checkpoint = self._get_checkpoint() section = checkpoint.get_resource_bank_section() section.update_object('metadata', { 'backup_id': '456', }) operation = self.plugin.get_restore_operation(resource) mock_cinder_create.return_value = self.cinder_client with mock.patch.multiple( self.cinder_client, volumes=mock.DEFAULT, restores=mock.DEFAULT, ) as mocks: volume_id = 456 mocks['volumes'].get.return_value = mock.Mock() mocks['volumes'].get.return_value.status = 'error' mocks['restores'].restore = RestoreResponse(volume_id) self.assertRaises(exception.RestoreResourceFailed, call_hooks, operation, checkpoint, resource, self.cntxt, {}, **{'restore': None}) mock_update_restore.assert_called_with( None, resource.type, volume_id, constants.RESOURCE_STATUS_ERROR, 'Error creating volume')
def test_verify_succeed(self, mock_update_verify, mock_cinder_create): resource = Resource( id="123", type=constants.VOLUME_RESOURCE_TYPE, name="fake", ) checkpoint = self.checkpoint section = checkpoint.get_resource_bank_section(resource) section.update_object('metadata', { 'snapshot_id': '456', }) parameters = {} operation = self.plugin.get_verify_operation(resource) mock_cinder_create.return_value = self.cinder_client with mock.patch.multiple( self.cinder_client, volume_snapshots=mock.DEFAULT, volumes=mock.DEFAULT, ) as mocks: volume_id = '123' mocks['volume_snapshots'].get.return_value = mock.Mock() mocks['volume_snapshots'].get.return_value.status = 'available' fake_bank_section.get_object = mock.MagicMock() fake_bank_section.get_object.return_value = {"snapshot_id": "456"} call_hooks(operation, checkpoint, resource, self.cntxt, parameters, **{ 'verify': None, 'new_resources': {} }) mock_update_verify.assert_called_with(None, resource.type, volume_id, 'available')
def test_delete_backup(self, mock_freezer_create, mock_status_poll): resource = Resource(id="123", type=constants.VOLUME_RESOURCE_TYPE, name='fake') delete_operation = self.plugin.get_delete_operation(resource) fake_bank_section.update_object = mock.MagicMock() fake_bank_section.get_object = mock.MagicMock() fake_bank_section.get_object.return_value = { 'job_info': { 'description': '123', 'job_actions': [{ 'freezer_action': { 'backup_name': 'test', 'action': 'backup', 'mode': 'cinder', 'cinder_vol_id': 'test', 'storage': 'swift', 'container': 'karbor/123' } }] } } mock_freezer_create.return_value = self.freezer_client mock_status_poll.return_value = True self.freezer_client.jobs.create = mock.MagicMock() self.freezer_client.jobs.create.return_value = '321' self.freezer_client.jobs.start_job = mock.MagicMock() self.freezer_client.jobs.get = mock.MagicMock() self.freezer_client.jobs.get.return_value = { 'job_actions': [] } self.freezer_client.jobs.delete = mock.MagicMock() call_hooks(delete_operation, self.checkpoint, resource, self.cntxt, {})
def test_create_backup(self, mock_trove_create, mock_status_poll): resource = Resource(id="123", type=constants.DATABASE_RESOURCE_TYPE, name='fake') fake_bank_section.update_object = mock.MagicMock() protect_operation = self.plugin.get_protect_operation(resource) mock_trove_create.return_value = self.trove_client self.trove_client.instances.get = mock.MagicMock() self.trove_client.instances.return_value = Database( status="ACTIVE" ) fake_bank_section.update_object = mock.MagicMock() self.trove_client.backups.create = mock.MagicMock() self.trove_client.backups.create.return_value = Backup( id="1234", status="COMPLETED" ) self.trove_client.backups.get = mock.MagicMock() self.trove_client.backups.get.return_value = Backup( id="1234", status="COMPLETED" ) mock_status_poll.return_value = True call_hooks(protect_operation, self.checkpoint, resource, self.cntxt, {})
def test_delete_fail(self, mock_cinder_create): resource = Resource( id="123", type=constants.VOLUME_RESOURCE_TYPE, name="test", ) checkpoint = self._get_checkpoint() section = checkpoint.get_resource_bank_section() section.update_object('metadata', { 'backup_id': '456', }) operation = self.plugin.get_delete_operation(resource) mock_cinder_create.return_value = self.cinder_client with mock.patch.object(self.cinder_client, 'backups') as backups: backups.delete = BackupResponse('456', 'deleting', '---', 0) backups.get = BackupResponse('456', 'error', 'deleting', 2) self.assertRaises( exception.DeleteResourceFailed, call_hooks, operation, checkpoint, resource, self.cntxt, {} )
def list_protectable_dependents(self, context, protectable_id, protectable_type, protectable_name): LOG.info( "Start to list dependents of resource (type:%(type)s, " "id:%(id)s, name:%(name)s)", { 'type': protectable_type, 'id': protectable_id, 'name': protectable_name }) parent_resource = Resource(type=protectable_type, id=protectable_id, name=protectable_name) registry = self.protectable_registry try: dependent_resources = registry.fetch_dependent_resources( context, parent_resource) except exception.ListProtectableResourceFailed as err: LOG.error("List dependent resources of (%(res)s) failed: %(err)s", { 'res': parent_resource, 'err': six.text_type(err) }) raise return [resource.to_dict() for resource in dependent_resources]
def test_delete_backup(self, mock_glance_client): resource = Resource(id="vm_id_1", type=constants.SERVER_RESOURCE_TYPE, name="fake_vm") fake_bank._plugin._objects[ "/resource_data/checkpoint_id/vm_id_1/metadata"] = { "resource_id": "vm_id_1", "attach_metadata": {}, "server_metadata": { "availability_zone": "nova", "networks": ["network_id_1"], "floating_ips": [], "flavor": "flavor_id", "key_name": None, "security_groups": "default", }, "snapshot_id": "image_id_2", "snapshot_metadata": { "disk_format": "", "container_format": "", "name": "snapshot_checkpoint_id@vm_id_1" } } delete_operation = self.plugin.get_delete_operation(resource) mock_glance_client.return_value = self.glance_client fake_bank._plugin._objects[ "/resource_data/checkpoint_id/vm_id_1/data_0"] = "image_data_1" fake_bank._plugin._objects[ "/resource_data/checkpoint_id/vm_id_1/data_1"] = "image_data_1" call_hooks(delete_operation, self.checkpoint, resource, self.cntxt, {})
def test_create_backup(self, mock_neutron_create): resource = Resource(id="network_id_1", type=constants.NETWORK_RESOURCE_TYPE, name="test") fake_bank_section.update_object = mock.MagicMock() protect_operation = self.plugin.get_protect_operation(resource) mock_neutron_create.return_value = self.neutron_client self.neutron_client.list_networks = mock.MagicMock() self.neutron_client.list_networks.return_value = FakeNetworks self.neutron_client.list_subnets = mock.MagicMock() self.neutron_client.list_subnets.return_value = FakeSubnets self.neutron_client.list_ports = mock.MagicMock() self.neutron_client.list_ports.return_value = FakePorts self.neutron_client.list_routers = mock.MagicMock() self.neutron_client.list_routers.return_value = FakeRoutes self.neutron_client.list_security_groups = mock.MagicMock() self.neutron_client.list_security_groups.return_value = FakeSecGroup call_hooks(protect_operation, self.checkpoint, resource, self.cntxt, {})
def test_show_resource(self, mock_volume_get): plugin = VolumeProtectablePlugin(self._context) vol_info = namedtuple('vol_info', ['id', 'name']) mock_volume_get.return_value = \ vol_info(id='123', name='name123') self.assertEqual(Resource('OS::Cinder::Volume', '123', 'name123'), plugin.show_resource(self._context, "123"))