예제 #1
0
    def test_disconnect_image_disk(self, mock_active_vioses, mock_rm_maps):
        # vio_to_vg is a single-entry response.  Wrap it and put it in a list
        # to act as the feed for FeedTaskFx and FeedTask.
        feed = [pvm_vios.VIOS.wrap(self.vio_to_vg)]
        mock_active_vioses.return_value = feed
        ft_fx = pvm_fx.FeedTaskFx(feed)
        self.useFixture(ft_fx)

        # The mock return values
        mock_rm_maps.return_value = True

        # Need the driver to return the actual UUID of the VIOS in the feed,
        # to match the FeedTask.
        self.mock_vg_uuid.return_value = (feed[0].uuid, 'vg_uuid')

        # Create the feed task
        local = self.get_ls(self.apt)
        inst = mock.Mock(uuid=fx.FAKE_INST_UUID)

        # As initialized above, remove_maps returns True to trigger update.
        local.disconnect_image_disk(mock.MagicMock(),
                                    inst,
                                    stg_ftsk=None,
                                    disk_type=[disk_dvr.DiskType.BOOT])
        self.assertEqual(1, mock_rm_maps.call_count)
        self.assertEqual(1, ft_fx.patchers['update'].mock.call_count)
        mock_rm_maps.assert_called_once_with(feed[0],
                                             fx.FAKE_INST_UUID_PVM,
                                             match_func=mock.ANY)
예제 #2
0
    def test_dlt_vopt_no_map(self, mock_vop_valid, mock_vm_id, rm_vg_stor):
        feed = [pvm_vios.VIOS.wrap(self.vio_to_vg)]
        ft_fx = pvm_fx.FeedTaskFx(feed)
        self.useFixture(ft_fx)

        # Set up the mock data.
        self.apt.read.side_effect = [self.vio_to_vg, self.vg_to_vio]
        mock_vm_id.return_value = '2'

        def validate_remove_stor(vg_w, vopts=None):
            vopts = {} if vopts is None else vopts
            self.assertIsInstance(vg_w, pvm_stor.VG)
            self.assertEqual(1, len(vopts))
            self.assertIsInstance(vopts[0], pvm_stor.VOptMedia)

        rm_vg_stor.side_effect = validate_remove_stor

        # Count the number of SCSI mappings beforehand
        num_maps_before = len(feed[0].scsi_mappings)

        # Invoke the operation
        cfg_dr = m.ConfigDrivePowerVM(self.apt, 'fake_host')
        cfg_dr.vios_uuid = feed[0].uuid
        cfg_dr.dlt_vopt('2', remove_mappings=False)

        # The storage should have been removed
        self.assertTrue(rm_vg_stor.called)

        # The mappings should have changed
        self.assertTrue(ft_fx.patchers['update'].mock.called)
        # But the number should be the same (the vopt mapping was replaced)
        self.assertEqual(num_maps_before, len(feed[0].scsi_mappings))
예제 #3
0
    def test_attach_vopt(self, mock_validate, mock_build_map, mock_add_map):
        # to act as the feed for FeedTaskFx and FeedTask.
        feed = [pvm_vios.VIOS.wrap(self.vio_to_vg)]
        ft_fx = pvm_fx.FeedTaskFx(feed)
        self.useFixture(ft_fx)

        mock_instance = mock.MagicMock(name='fake-instance')

        cfg_dr_builder = m.ConfigDrivePowerVM(self.apt, 'fake_host')
        cfg_dr_builder.vios_uuid = feed[0].uuid
        vopt = mock.Mock()
        self.apt.read.return_value = self.vio_to_vg

        def validate_build(host_uuid, vios_w, lpar_uuid, vopt_elem):
            self.assertEqual('fake_host', host_uuid)
            self.assertIsInstance(vios_w, pvm_vios.VIOS)
            self.assertEqual('lpar_uuid', lpar_uuid)
            self.assertEqual(vopt, vopt_elem)
            return 'map'

        mock_build_map.side_effect = validate_build

        def validate_add(vios_w, mapping):
            self.assertIsInstance(vios_w, pvm_vios.VIOS)
            self.assertEqual(mapping, 'map')
            return 'added'

        mock_add_map.side_effect = validate_add

        cfg_dr_builder._attach_vopt(mock_instance, 'lpar_uuid', vopt)

        # Make sure they were called and validated
        self.assertEqual(1, mock_build_map.call_count)
        self.assertEqual(1, mock_add_map.call_count)
        self.assertEqual(1, ft_fx.patchers['update'].mock.call_count)
예제 #4
0
    def test_connect_image_disk_no_update(self, mock_active_vioses,
                                          mock_add_map, mock_build_map):
        # vio_to_vg is a single-entry response.  Wrap it and put it in a list
        # to act as the feed for FeedTaskFx and FeedTask.
        feed = [pvm_vios.VIOS.wrap(self.vio_to_vg)]
        mock_active_vioses.return_value = feed
        ft_fx = pvm_fx.FeedTaskFx(feed)
        self.useFixture(ft_fx)

        # The mock return values
        mock_add_map.return_value = False
        self.mock_vg_uuid.return_value = (feed[0].uuid, 'vg_uuid')
        mock_build_map.return_value = 'fake_map'

        # Need the driver to return the actual UUID of the VIOS in the feed,
        # to match the FeedTask.
        local = self.get_ls(self.apt)
        inst = mock.Mock(uuid=fx.FAKE_INST_UUID)

        # As initialized above, remove_maps returns True to trigger update.
        local.connect_disk(mock.MagicMock(),
                           inst,
                           mock.MagicMock(),
                           stg_ftsk=None)
        self.assertEqual(1, mock_add_map.call_count)
        mock_add_map.assert_called_once_with(feed[0], 'fake_map')
        self.assertEqual(0, ft_fx.patchers['update'].mock.call_count)
예제 #5
0
    def test_post_exec(self):
        def log_func(msg):
            def _log(*a, **k):
                ftfx.log(msg)

            return _log

        def log_task(msg):
            return tf_task.FunctorTask(log_func(msg), name='functor_%s' % msg)

        # Limit the feed to two to keep the logging sane
        ftfx = self.useFixture(fx.FeedTaskFx(self.entries[:2]))
        # Make the logging predictable by limiting to one thread
        ftsk = tx.FeedTask('post_exec', lpar.LPAR.getter(None), max_workers=1)

        # First prove that a FeedTask with *only* post-execs can run.
        ftsk.add_post_execute(log_task('post1'))
        ftsk.add_post_execute(log_task('post2'))
        ftsk.execute()
        # Note that no GETs or locks happen
        self.assertEqual(['post1', 'post2'], ftfx.get_log())

        # Now add regular subtasks
        ftfx.reset_log()
        ftsk.add_functor_subtask(log_func('main1'))
        ftsk.add_functor_subtask(log_func('main2'))
        ftsk.execute()
        # One GET, up front.  Posts happen at the end.
        self.assertEqual([
            'get', 'lock', 'main1', 'main2', 'unlock', 'lock', 'main1',
            'main2', 'unlock', 'post1', 'post2'
        ], ftfx.get_log())
예제 #6
0
 def setUp(self):
     super(TestScrub3, self).setUp()
     self.adpt = self.useFixture(fx.AdapterFx()).adpt
     self.vio_feed = [vios.VIOS.wrap(tju.load_file(VIOS_ENTRY2, self.adpt))]
     self.txfx = self.useFixture(fx.FeedTaskFx(self.vio_feed))
     self.logfx = self.useFixture(fx.LoggingFx())
     self.ftsk = tx.FeedTask('scrub', self.vio_feed)
예제 #7
0
    def setUp(self):
        super(TestNPIVAdapter, self).setUp()

        self.adpt = self.useFixture(pvm_fx.AdapterFx()).adpt

        def resp(file_name):
            return pvmhttp.load_pvm_resp(file_name,
                                         adapter=self.adpt).get_response()

        self.vios_feed_resp = resp(VIOS_FEED)
        self.wwpn1 = '21000024FF649104'
        self.wwpn2 = '21000024FF649107'
        self.vios_uuid = '3443DB77-AED1-47ED-9AA5-3DB9C6CF7089'
        self.slot_mgr = mock.Mock()

        # Set up the transaction manager
        feed = pvm_vios.VIOS.wrap(self.vios_feed_resp)
        self.ft_fx = pvm_fx.FeedTaskFx(feed)
        self.useFixture(self.ft_fx)

        # Set up the mocks for the internal volume driver
        name = 'nova_powervm.virt.powervm.volume.npiv.NPIVVolumeAdapter.'
        self.mock_port_count_p = mock.patch(name + '_ports_per_fabric')
        self.mock_port_count = self.mock_port_count_p.start()
        self.mock_port_count.return_value = 1

        self.mock_fabric_names_p = mock.patch(name + '_fabric_names')
        self.mock_fabric_names = self.mock_fabric_names_p.start()
        self.mock_fabric_names.return_value = ['A']

        self.mock_fabric_ports_p = mock.patch(name + '_fabric_ports')
        self.mock_fabric_ports = self.mock_fabric_ports_p.start()
        self.mock_fabric_ports.return_value = [self.wwpn1, self.wwpn2]

        @mock.patch('pypowervm.wrappers.virtual_io_server.VIOS.getter')
        @mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid')
        def init_vol_adpt(mock_pvm_uuid, mock_getter):
            con_info = {
                'serial': 'id',
                'data': {
                    'initiator_target_map': {
                        'i1': ['t1'],
                        'i2': ['t2', 't3']
                    },
                    'target_lun': '1'
                }
            }
            mock_inst = mock.MagicMock()
            mock_pvm_uuid.return_value = '1234'

            # The getter can just return the VIOS values (to remove a read
            # that would otherwise need to be mocked).
            mock_getter.return_value = feed

            return npiv.NPIVVolumeAdapter(self.adpt, 'host_uuid', mock_inst,
                                          con_info)

        self.vol_drv = init_vol_adpt()
예제 #8
0
    def setUp(self):
        super(TestISCSIAdapter, self).setUp()
        self.adpt = self.useFixture(pvm_fx.AdapterFx()).adpt

        self.vios_feed_resp = load_file(VIOS_FEED)

        self.feed = pvm_vios.VIOS.wrap(self.vios_feed_resp)
        self.ft_fx = pvm_fx.FeedTaskFx(self.feed)
        self.useFixture(self.ft_fx)

        self.adpt.read.return_value = self.vios_feed_resp

        @mock.patch('pypowervm.wrappers.virtual_io_server.VIOS', autospec=True)
        @mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid')
        @mock.patch('pypowervm.tasks.partition.get_mgmt_partition',
                    autospec=True)
        @mock.patch('pypowervm.tasks.hdisk.discover_iscsi_initiator',
                    autospec=True)
        def init_vol_adpt(mock_initiator, mock_mgmt_part, mock_pvm_uuid,
                          mock_vios):
            self.trans_type = 'iscsi'
            self.iqn = 'iqn.2016-08.bar.foo:target'
            self.lun = '1'
            self.host_ip = '10.0.0.1'
            self.user = '******'
            self.password = '******'
            self.serial = 'f042c68a-c5a5-476a-ba34-2f6d43f4226c'
            con_info = {
                'serial': self.serial,
                'driver_volume_type': self.trans_type,
                'data': {
                    'target_iqn': self.iqn,
                    'target_lun': self.lun,
                    'target_portal': self.host_ip,
                    'auth_username': self.user,
                    'auth_password': self.password
                },
            }
            mock_inst = mock.MagicMock()
            mock_pvm_uuid.return_value = '1234'
            mock_initiator.return_value = 'initiatior iqn'
            # The getter can just return the VIOS values (to remove a read
            # that would otherwise need to be mocked).
            mock_vios.getter.return_value = self.feed
            return iscsi.IscsiVolumeAdapter(self.adpt, 'host_uuid', mock_inst,
                                            con_info)
        self.vol_drv = init_vol_adpt()

        # setup system_metadata tests
        self.devname = "/dev/fake"
        self.slot_mgr = mock.Mock()
        self.slot_mgr.build_map.get_vscsi_slot.return_value = 62, 'the_lua'
예제 #9
0
    def setUp(self):
        super(TestFileIOVolumeAdapter, self).setUp()

        # Needed for the volume adapter
        self.adpt = self.useFixture(pvm_fx.AdapterFx()).adpt
        mock_inst = mock.MagicMock(uuid='2BC123')

        self.vol_drv = FakeFileIOVolAdapter(self.adpt, 'host_uuid', mock_inst,
                                            dict(serial='volid1'))

        self.fake_vios = pvm_vios.VIOS.bld(
            self.adpt, 'vios1',
            pvm_bp.PartitionMemoryConfiguration.bld(self.adpt, 1024),
            pvm_bp.PartitionMemoryConfiguration.bld(self.adpt, 0.1, 1))
        self.feed = [pvm_vios.VIOS.wrap(self.fake_vios.entry)]
        ftskfx = pvm_fx.FeedTaskFx(self.feed)
        self.useFixture(ftskfx)
예제 #10
0
    def test_disconnect_disk(self, mock_active_vioses, mock_build_map,
                             mock_remove_maps, mock_find_maps, mock_vio_uuids):
        # vio is a single-entry response.  Wrap it and put it in a list
        # to act as the feed for FeedTaskFx and FeedTask.
        feed = [self.vio_wrap]
        ft_fx = pvm_fx.FeedTaskFx(feed)
        mock_active_vioses.return_value = feed
        self.useFixture(ft_fx)

        # The mock return values
        mock_build_map.return_value = 'fake_map'

        # Need the driver to return the actual UUID of the VIOS in the feed,
        # to match the FeedTask.
        ssp = self._get_ssp_stor()
        mock_vio_uuids.return_value = [self.vio_wrap.uuid]

        # Make the LU's to remove
        def mklu(udid):
            lu = pvm_stg.LU.bld(None, 'lu_%s' % udid, 1)
            lu._udid('27%s' % udid)
            return lu

        lu1 = mklu('abc')
        lu2 = mklu('def')

        def remove_resp(vios_w,
                        client_lpar_id,
                        match_func=None,
                        include_orphans=False):
            return [
                mock.Mock(backing_storage=lu1),
                mock.Mock(backing_storage=lu2)
            ]

        mock_remove_maps.side_effect = remove_resp
        mock_find_maps.side_effect = remove_resp

        # As initialized above, remove_maps returns True to trigger update.
        lu_list = ssp.disconnect_disk(self.instance, stg_ftsk=None)
        self.assertEqual({lu1, lu2}, set(lu_list))
        mock_remove_maps.assert_called_once_with(self.vio_wrap,
                                                 fx.FAKE_INST_UUID_PVM,
                                                 match_func=mock.ANY)
        self.vio_wrap.update.assert_called_once_with(timeout=mock.ANY)
예제 #11
0
    def setUp(self, vios_feed_file, p_wwpn1, p_wwpn2):
        super(BaseVSCSITest, self).setUp()
        self.adpt = self.useFixture(pvm_fx.AdapterFx()).adpt

        def resp(file_name):
            return pvmhttp.load_pvm_resp(file_name,
                                         adapter=self.adpt).get_response()

        self.vios_feed_resp = resp(vios_feed_file)

        self.feed = pvm_vios.VIOS.wrap(self.vios_feed_resp)
        self.ft_fx = pvm_fx.FeedTaskFx(self.feed)
        self.useFixture(self.ft_fx)

        self.adpt.read.return_value = self.vios_feed_resp

        @mock.patch('pypowervm.wrappers.virtual_io_server.VIOS.getter')
        @mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid')
        def init_vol_adpt(mock_pvm_uuid, mock_getter):
            con_info = {
                'serial': 'id',
                'data': {
                    'initiator_target_map': {
                        p_wwpn1: ['t1'],
                        p_wwpn2: ['t2', 't3']
                    },
                    'target_lun': '1',
                    'volume_id': 'a_volume_identifier',
                    'pg83NAA': '4567'
                },
            }
            mock_inst = mock.MagicMock()
            mock_pvm_uuid.return_value = '1234'

            # The getter can just return the VIOS values (to remove a read
            # that would otherwise need to be mocked).
            mock_getter.return_value = self.feed

            return vscsi.PVVscsiFCVolumeAdapter(self.adpt, 'host_uuid',
                                                mock_inst, con_info)

        self.vol_drv = init_vol_adpt()
예제 #12
0
    def test_dlt_vopt(self, mock_vop_valid, mock_vm_id, rm_vg_stor):
        feed = [pvm_vios.VIOS.wrap(self.vio_to_vg)]
        ft_fx = pvm_fx.FeedTaskFx(feed)
        self.useFixture(ft_fx)

        # Set up the mock data.
        self.apt.read.side_effect = [self.vio_to_vg, self.vg_to_vio]
        mock_vm_id.return_value = '2'

        # Make sure that the first update is a VIO and doesn't have the vopt
        # mapping
        def validate_update(*kargs, **kwargs):
            vol_grp = kargs[0]
            # This is the VG update.  Make sure there are no optical medias
            # anymore.
            self.assertEqual(0, len(vol_grp.vmedia_repos[0].optical_media))
            return vol_grp.entry

        self.apt.update_by_path.side_effect = validate_update

        def validate_remove_stor(vg_w, vopts=None):
            vopts = {} if vopts is None else vopts
            self.assertIsInstance(vg_w, pvm_stor.VG)
            self.assertEqual(1, len(vopts))
            self.assertIsInstance(vopts[0], pvm_stor.VOptMedia)

        rm_vg_stor.side_effect = validate_remove_stor

        # Count the number of SCSI mappings beforehand
        num_maps_before = len(feed[0].scsi_mappings)

        # Invoke the operation
        cfg_dr = m.ConfigDrivePowerVM(self.apt, 'fake_host')
        cfg_dr.vios_uuid = feed[0].uuid
        cfg_dr.dlt_vopt('2')

        self.assertEqual(num_maps_before - 1, len(feed[0].scsi_mappings))
        self.assertTrue(ft_fx.patchers['update'].mock.called)
        self.assertTrue(rm_vg_stor.called)
예제 #13
0
    def test_connect_disk_no_update(self, mock_active_vioses, mock_add_map,
                                    mock_build_map, mock_vio_uuids):
        # vio is a single-entry response.  Wrap it and put it in a list
        # to act as the feed for FeedTaskFx and FeedTask.
        feed = [self.vio_wrap]
        mock_active_vioses.return_value = feed
        ft_fx = pvm_fx.FeedTaskFx(feed)
        self.useFixture(ft_fx)

        # The mock return values
        mock_add_map.return_value = None
        mock_build_map.return_value = 'fake_map'

        # Need the driver to return the actual UUID of the VIOS in the feed,
        # to match the FeedTask.
        ssp = self._get_ssp_stor()
        mock_vio_uuids.return_value = [self.vio_wrap.uuid]
        inst = mock.Mock(uuid=fx.FAKE_INST_UUID)

        # As initialized above, add_maps returns False to skip update.
        ssp.connect_disk(inst, mock.Mock(), stg_ftsk=None)
        mock_add_map.assert_called_once_with(self.vio_wrap, 'fake_map')
        self.vio_wrap.update.assert_not_called()
예제 #14
0
    def setUp(self):
        super(TestRBDVolumeAdapter, self).setUp()

        # Needed for the volume adapter
        self.adpt = self.useFixture(pvm_fx.AdapterFx()).adpt
        mock_inst = mock.MagicMock(uuid='2BC123')

        self.vol_drv = FakeRBDVolAdapter(
            self.adpt, 'host_uuid', mock_inst, {
                'data': {
                    'name': 'pool/image',
                    'volume_id': 'a_vol_id'
                },
                'serial': 'volid1'
            })

        self.fake_vios = pvm_vios.VIOS.bld(
            self.adpt, 'vios1',
            pvm_bp.PartitionMemoryConfiguration.bld(self.adpt, 1024),
            pvm_bp.PartitionMemoryConfiguration.bld(self.adpt, 0.1, 1))
        self.feed = [pvm_vios.VIOS.wrap(self.fake_vios.entry)]
        ftskfx = pvm_fx.FeedTaskFx(self.feed)
        self.useFixture(ftskfx)
예제 #15
0
    def test_wrapper_task_rets(self):
        # Limit the feed to two to keep the return size sane
        ftfx = self.useFixture(fx.FeedTaskFx(self.entries[:2]))
        ftsk = tx.FeedTask('subtask_rets',
                           lpar.LPAR.getter(None),
                           update_timeout=123)
        exp_wtr = {
            wrp.uuid: {
                'wrapper': wrp,
                'the_id': wrp.id,
                'the_name': wrp.name
            }
            for wrp in ftsk.feed
        }
        called = []

        def return_wrapper_name(wrapper):
            return wrapper.name

        def return_wrapper_id(wrapper):
            return wrapper.id

        def verify_rets_implicit(wrapper_task_rets):
            called.append('implicit')
            self.assertEqual(exp_wtr, wrapper_task_rets)
            return 'verify_rets_implicit_return'

        def verify_rets_explicit(**kwargs):
            called.append('explicit')
            self.assertEqual(exp_wtr, kwargs['wrapper_task_rets'])
            return 'verify_rets_explicit_return'

        ftsk.add_functor_subtask(return_wrapper_name, provides='the_name')
        ftsk.add_functor_subtask(return_wrapper_id, provides='the_id')
        # Execute once here to make sure the return is in the right shape when
        # there are no post-execs
        self.assertEqual(
            {
                'wrapper_task_rets': {
                    self.entries[0].uuid: {
                        'the_name': self.entries[0].name,
                        'the_id': self.entries[0].id,
                        'wrapper': self.entries[0]
                    },
                    self.entries[1].uuid: {
                        'the_name': self.entries[1].name,
                        'the_id': self.entries[1].id,
                        'wrapper': self.entries[1]
                    }
                }
            }, ftsk.execute())

        ftsk.add_post_execute(
            tf_task.FunctorTask(verify_rets_implicit,
                                provides='post_exec_implicit'))
        ftsk.add_post_execute(
            tf_task.FunctorTask(verify_rets_explicit,
                                requires='wrapper_task_rets',
                                provides='post_exec_explicit'))

        ret = ftsk.execute()
        # Make sure the post-execs actually ran (to guarantee their internal
        # assertions passed).
        self.assertEqual(['implicit', 'explicit'], called)
        ftfx.patchers['update'].mock.assert_called_with(mock.ANY, timeout=123)
        # Verify that we got the returns from the subtasks AND the post-execs
        self.assertEqual(
            {
                'wrapper_task_rets': {
                    self.entries[0].uuid: {
                        'the_name': self.entries[0].name,
                        'the_id': self.entries[0].id,
                        'wrapper': self.entries[0]
                    },
                    self.entries[1].uuid: {
                        'the_name': self.entries[1].name,
                        'the_id': self.entries[1].id,
                        'wrapper': self.entries[1]
                    }
                },
                'post_exec_implicit': 'verify_rets_implicit_return',
                'post_exec_explicit': 'verify_rets_explicit_return'
            }, ret)