class TestVmSyncFunctions(unittest.TestCase):

    def mock_rabbitcli(self, exchange, exchange_type, process_message=None):
        class MockRabbitMQCommonClient(RabbitMQCommonClient):
            def publish_message(self, message, routing_key=None, reply_to=None, exchange=None, correlation_id=None, on_fail=None):
                return
        return MockRabbitMQCommonClient

    @mock.patch('imgstorage.imgstoragevm.RabbitMQCommonClient')
    def setUp(self, mock_rabbit_vm):
        self.vm_client = VmDaemon()
        mock_rabbit_vm.publish_message = MagicMock()
        self.vm_client.process_message = MagicMock()
        
        self.vm_client.ZPOOL = 'tank'
        self.vm_client.SQLITE_DB = '/tmp/test_db_%s'%uuid.uuid4()
        self.vm_client.run()

    def tearDown(self):
        os.remove(self.vm_client.SQLITE_DB)

    @mock.patch('imgstorage.imgstoragevm.runCommand')
    def test_run_sync_initial_synced(self, mockRunCommand):
        zvol = 'vm-hpcdev-pub03-1-vol'
        target = 'iqn.2001-04.com.nas-0-1-%s'%zvol
        bdev = 'sdc'
        mockRunCommand.side_effect = self.create_iscsiadm_side_effect(target, bdev, 1)
        with sqlite3.connect(self.vm_client.SQLITE_DB) as con:
            cur = con.cursor()
            cur.execute('INSERT INTO sync_queue VALUES (?,?,?,?,?,?,?)',(zvol, 'iqn.2001-04.com.nas-0-1-%s'%zvol, 12345, 'reply_to', 'corr_id', 0, 1))
            con.commit()


        self.vm_client.run_sync()
        print mockRunCommand.mock_calls
        mockRunCommand.assert_any_call(['dmsetup', 'suspend', '/dev/mapper/%s-snap'%zvol])
        mockRunCommand.assert_any_call(['dmsetup', 'reload', '/dev/mapper/%s-snap'%zvol, '--table', '0 12345 snapshot-merge /dev/zvol/tank/%s /dev/zvol/tank/%s-temp-write P 16'%(zvol, zvol)])
        mockRunCommand.assert_any_call(['dmsetup', 'resume', '/dev/mapper/%s-snap'%zvol])
        mockRunCommand.assert_any_call(['dmsetup', 'reload', '/dev/mapper/%s-snap'%zvol, '--table', '0 12345 linear /dev/zvol/tank/%s 0'%(zvol)])
        mockRunCommand.assert_any_call(['zfs', 'destroy', 'tank/%s-temp-write'%zvol])
        mockRunCommand.assert_any_call(['iscsiadm', '-m', 'node', '-T', 'iqn.2001-04.com.nas-0-1-%s'%zvol, '-u'])

        print  mockRunCommand.call_count
        assert 10 == mockRunCommand.call_count
        self.vm_client.queue_connector.publish_message.assert_called_with({'action': 'zvol_synced', 'status': 'success', 'zvol': zvol}, u'reply_to', correlation_id=u'corr_id')


    @mock.patch('imgstorage.imgstoragevm.runCommand')
    def test_run_sync_initial_not_synced(self, mockRunCommand):
        zvol = 'vm-hpcdev-pub03-2-vol'
        target = 'iqn.2001-04.com.nas-0-1-%s'%zvol
        bdev = 'sdc'
        mockRunCommand.side_effect = self.create_iscsiadm_side_effect(target, bdev, 2)
        with sqlite3.connect(self.vm_client.SQLITE_DB) as con:
            cur = con.cursor()
            cur.execute('INSERT INTO sync_queue VALUES (?,?,?,?,?,?,?)',(zvol, 'iqn.2001-04.com.nas-0-1-%s'%zvol, 12345, 'reply_to', 'corr_id', 0, 1))
            con.commit()


        self.vm_client.run_sync()
        print mockRunCommand.mock_calls
        mockRunCommand.assert_any_call(['dmsetup', 'suspend', '/dev/mapper/%s-snap'%zvol])
        mockRunCommand.assert_any_call(['dmsetup', 'reload', '/dev/mapper/%s-snap'%zvol, '--table', '0 12345 snapshot-merge /dev/zvol/tank/%s /dev/zvol/tank/%s-temp-write P 16'%(zvol, zvol)])
        mockRunCommand.assert_any_call(['dmsetup', 'resume', '/dev/mapper/%s-snap'%zvol])

        print  mockRunCommand.call_count
        assert 4 == mockRunCommand.call_count
        assert not self.vm_client.queue_connector.publish_message.called, 'rabbotmq message was sent and should not have been'

    """ Testing zvol sync """
    @mock.patch('imgstorage.imgstoragevm.runCommand')
    @mock.patch('imgstorage.imgstoragevm.time.time',return_value=111)
    def test_sync_zvol_success(self, mockTime, mockRunCommand):
        zvol= 'vm-hpcdev-pub03-1-vol'
        target = 'iqn.2001-04.com.nas-0-1-%s'%zvol
        bdev = 'sdc'
        mockRunCommand.side_effect = self.create_iscsiadm_side_effect(target, bdev)
        self.vm_client.sync_zvol(
            {'action': 'sync_zvol', 'zvol':zvol, 'target':target},
            BasicProperties(reply_to='reply_to', message_id='message_id'))
        with sqlite3.connect(self.vm_client.SQLITE_DB) as con:
            cur = con.cursor()
            cur.execute('SELECT * FROM sync_queue')
            self.assertSequenceEqual(cur.fetchone(), [zvol, target, 12345, 'reply_to','message_id',0,111])

    
    @mock.patch('imgstorage.imgstoragevm.runCommand')
    def test_get_dev_list(self, mockRunCommand):
        zvol= 'vm-hpcdev-pub03-1-vol'
        target = 'iqn.2001-04.com.nas-0-1-%s'%zvol
        bdev = 'sdc'
        mockRunCommand.side_effect = self.create_iscsiadm_side_effect(target, bdev)
        dev_list = self.vm_client.get_dev_list()
        self.assertEqual(dev_list, {
            zvol: {'status': 'snapshot-merge', 'target': target, 'dev': '%s-snap'%zvol, 'synced': '32/73400320 32', 'bdev': bdev, 'size': 36}, 
            'vm-hpcdev-pub03-4-vol': {'status': 'linear', 'dev': 'vm-hpcdev-pub03-4-vol-snap', 'size': 36}, 
            'vm-hpcdev-pub03-2-vol': {'status': 'snapshot-merge', 'synced': '1321232/73400320 2592', 'dev': 'vm-hpcdev-pub03-2-vol-snap', 'size': 36}
        })
        print self.vm_client.get_dev_list()

    def create_iscsiadm_side_effect(self, target, bdev, dmsetup_return_line=None):
        def iscsiadm_side_effect(*args, **kwargs):
            if args[0][:3] == ['iscsiadm', '-m', 'session']:        return (iscsiadm_session_response%(target, bdev)).splitlines() # list local devices
            elif args[0][:3] == ['iscsiadm', '-m', 'discovery']:    return (iscsiadm_discovery_response%target).splitlines() # find remote targets
            elif args[0][:3] == ['iscsiadm', '-m', 'node']:         return '\n'.splitlines() # connect to iscsi target
            elif args[0][:2] == ['dmsetup', 'status']:
                if(not dmsetup_return_line):
                    return dmsetup_status_response.splitlines()
                else:
                    return [dmsetup_status_response.splitlines()[dmsetup_return_line][len('vm-hpcdev-pub03-1-vol-snap: '):]]
            elif args[0][0] == 'blockdev':                          return '12345'.splitlines()
        return iscsiadm_side_effect



    def check_zvol_busy(self, zvol):
        with sqlite3.connect(self.vm_client.SQLITE_DB) as con:
            cur = con.cursor()
            cur.execute('SELECT count(*) from sync_queue where zvol = ?',[zvol])
            num_rows = cur.fetchone()[0]
            return num_rows > 0

    def assertSequenceEqual(self, it1, it2):
        self.assertEqual(tuple(it1), tuple(it2))
Beispiel #2
0
class TestVmSyncFunctions(unittest.TestCase):
    def mock_rabbitcli(self, exchange, exchange_type, process_message=None):
        class MockRabbitMQCommonClient(RabbitMQCommonClient):
            def publish_message(self,
                                message,
                                routing_key=None,
                                reply_to=None,
                                exchange=None,
                                correlation_id=None,
                                on_fail=None):
                return

        return MockRabbitMQCommonClient

    @mock.patch('imgstorage.imgstoragevm.RabbitMQCommonClient')
    def setUp(self, mock_rabbit_vm):
        self.vm_client = VmDaemon()
        mock_rabbit_vm.publish_message = MagicMock()
        self.vm_client.process_message = MagicMock()

        self.vm_client.ZPOOL = 'tank'
        self.vm_client.SQLITE_DB = '/tmp/test_db_%s' % uuid.uuid4()
        self.vm_client.run()

    def tearDown(self):
        os.remove(self.vm_client.SQLITE_DB)

    @mock.patch('imgstorage.imgstoragevm.runCommand')
    def test_run_sync_initial_synced(self, mockRunCommand):
        zvol = 'vm-hpcdev-pub03-1-vol'
        target = 'iqn.2001-04.com.nas-0-1-%s' % zvol
        bdev = 'sdc'
        mockRunCommand.side_effect = self.create_iscsiadm_side_effect(
            target, bdev, 1)
        with sqlite3.connect(self.vm_client.SQLITE_DB) as con:
            cur = con.cursor()
            cur.execute('INSERT INTO sync_queue VALUES (?,?,?,?,?,?,?)',
                        (zvol, 'iqn.2001-04.com.nas-0-1-%s' % zvol, 12345,
                         'reply_to', 'corr_id', 0, 1))
            con.commit()

        self.vm_client.run_sync()
        print mockRunCommand.mock_calls
        mockRunCommand.assert_any_call(
            ['dmsetup', 'suspend',
             '/dev/mapper/%s-snap' % zvol])
        mockRunCommand.assert_any_call([
            'dmsetup', 'reload',
            '/dev/mapper/%s-snap' % zvol, '--table',
            '0 12345 snapshot-merge /dev/zvol/tank/%s /dev/zvol/tank/%s-temp-write P 16'
            % (zvol, zvol)
        ])
        mockRunCommand.assert_any_call(
            ['dmsetup', 'resume',
             '/dev/mapper/%s-snap' % zvol])
        mockRunCommand.assert_any_call([
            'dmsetup', 'reload',
            '/dev/mapper/%s-snap' % zvol, '--table',
            '0 12345 linear /dev/zvol/tank/%s 0' % (zvol)
        ])
        mockRunCommand.assert_any_call(
            ['zfs', 'destroy', 'tank/%s-temp-write' % zvol])
        mockRunCommand.assert_any_call([
            'iscsiadm', '-m', 'node', '-T',
            'iqn.2001-04.com.nas-0-1-%s' % zvol, '-u'
        ])

        print mockRunCommand.call_count
        assert 10 == mockRunCommand.call_count
        self.vm_client.queue_connector.publish_message.assert_called_with(
            {
                'action': 'zvol_synced',
                'status': 'success',
                'zvol': zvol
            },
            u'reply_to',
            correlation_id=u'corr_id')

    @mock.patch('imgstorage.imgstoragevm.runCommand')
    def test_run_sync_initial_not_synced(self, mockRunCommand):
        zvol = 'vm-hpcdev-pub03-2-vol'
        target = 'iqn.2001-04.com.nas-0-1-%s' % zvol
        bdev = 'sdc'
        mockRunCommand.side_effect = self.create_iscsiadm_side_effect(
            target, bdev, 2)
        with sqlite3.connect(self.vm_client.SQLITE_DB) as con:
            cur = con.cursor()
            cur.execute('INSERT INTO sync_queue VALUES (?,?,?,?,?,?,?)',
                        (zvol, 'iqn.2001-04.com.nas-0-1-%s' % zvol, 12345,
                         'reply_to', 'corr_id', 0, 1))
            con.commit()

        self.vm_client.run_sync()
        print mockRunCommand.mock_calls
        mockRunCommand.assert_any_call(
            ['dmsetup', 'suspend',
             '/dev/mapper/%s-snap' % zvol])
        mockRunCommand.assert_any_call([
            'dmsetup', 'reload',
            '/dev/mapper/%s-snap' % zvol, '--table',
            '0 12345 snapshot-merge /dev/zvol/tank/%s /dev/zvol/tank/%s-temp-write P 16'
            % (zvol, zvol)
        ])
        mockRunCommand.assert_any_call(
            ['dmsetup', 'resume',
             '/dev/mapper/%s-snap' % zvol])

        print mockRunCommand.call_count
        assert 4 == mockRunCommand.call_count
        assert not self.vm_client.queue_connector.publish_message.called, 'rabbotmq message was sent and should not have been'

    """ Testing zvol sync """

    @mock.patch('imgstorage.imgstoragevm.runCommand')
    @mock.patch('imgstorage.imgstoragevm.time.time', return_value=111)
    def test_sync_zvol_success(self, mockTime, mockRunCommand):
        zvol = 'vm-hpcdev-pub03-1-vol'
        target = 'iqn.2001-04.com.nas-0-1-%s' % zvol
        bdev = 'sdc'
        mockRunCommand.side_effect = self.create_iscsiadm_side_effect(
            target, bdev)
        self.vm_client.sync_zvol(
            {
                'action': 'sync_zvol',
                'zvol': zvol,
                'target': target
            }, BasicProperties(reply_to='reply_to', message_id='message_id'))
        with sqlite3.connect(self.vm_client.SQLITE_DB) as con:
            cur = con.cursor()
            cur.execute('SELECT * FROM sync_queue')
            self.assertSequenceEqual(
                cur.fetchone(),
                [zvol, target, 12345, 'reply_to', 'message_id', 0, 111])

    @mock.patch('imgstorage.imgstoragevm.runCommand')
    def test_get_dev_list(self, mockRunCommand):
        zvol = 'vm-hpcdev-pub03-1-vol'
        target = 'iqn.2001-04.com.nas-0-1-%s' % zvol
        bdev = 'sdc'
        mockRunCommand.side_effect = self.create_iscsiadm_side_effect(
            target, bdev)
        dev_list = self.vm_client.get_dev_list()
        self.assertEqual(
            dev_list, {
                zvol: {
                    'status': 'snapshot-merge',
                    'target': target,
                    'dev': '%s-snap' % zvol,
                    'synced': '32/73400320 32',
                    'bdev': bdev,
                    'size': 36
                },
                'vm-hpcdev-pub03-4-vol': {
                    'status': 'linear',
                    'dev': 'vm-hpcdev-pub03-4-vol-snap',
                    'size': 36
                },
                'vm-hpcdev-pub03-2-vol': {
                    'status': 'snapshot-merge',
                    'synced': '1321232/73400320 2592',
                    'dev': 'vm-hpcdev-pub03-2-vol-snap',
                    'size': 36
                }
            })
        print self.vm_client.get_dev_list()

    def create_iscsiadm_side_effect(self,
                                    target,
                                    bdev,
                                    dmsetup_return_line=None):
        def iscsiadm_side_effect(*args, **kwargs):
            if args[0][:3] == ['iscsiadm', '-m', 'session']:
                return (iscsiadm_session_response %
                        (target, bdev)).splitlines()  # list local devices
            elif args[0][:3] == ['iscsiadm', '-m', 'discovery']:
                return (iscsiadm_discovery_response %
                        target).splitlines()  # find remote targets
            elif args[0][:3] == ['iscsiadm', '-m', 'node']:
                return '\n'.splitlines()  # connect to iscsi target
            elif args[0][:2] == ['dmsetup', 'status']:
                if (not dmsetup_return_line):
                    return dmsetup_status_response.splitlines()
                else:
                    return [
                        dmsetup_status_response.splitlines()
                        [dmsetup_return_line]
                        [len('vm-hpcdev-pub03-1-vol-snap: '):]
                    ]
            elif args[0][0] == 'blockdev':
                return '12345'.splitlines()

        return iscsiadm_side_effect

    def check_zvol_busy(self, zvol):
        with sqlite3.connect(self.vm_client.SQLITE_DB) as con:
            cur = con.cursor()
            cur.execute('SELECT count(*) from sync_queue where zvol = ?',
                        [zvol])
            num_rows = cur.fetchone()[0]
            return num_rows > 0

    def assertSequenceEqual(self, it1, it2):
        self.assertEqual(tuple(it1), tuple(it2))