Esempio n. 1
0
def list_ha_workers(profile, hostname, name_filter, non_running, plain_display):
    """Lists HA workers"""

    cs = CosmicSQL(server=profile, dry_run=False)

    ha_workers = cs.list_ha_workers(hostname)
    if not ha_workers:
        return f"No HA workers found"

    table_headers = [
        "Domain",
        "VM",
        "Type",
        "VM state",
        "Created (-2H)",
        "HAworker step taken",
        "Step",
        "Hypervisor",
        "Mgt server"
    ]
    table_format = 'plain' if plain_display else 'pretty'
    table_data = []

    for (domain, vm_name, vm_type, state, created, taken, step, host, mgt_server, ha_state) in ha_workers:
        if not vm_name:
            continue
        if non_running and state == 'Running':
            continue
        if name_filter and name_filter not in vm_name:
            continue

        display_name = (vm_name[:28] + '..') if len(vm_name) >= 31 else vm_name
        if mgt_server:
            mgt_server = mgt_server.split('.')[0]
        host = host.split('.')[0]

        table_data.append([domain, display_name, vm_type, state, created, taken, step, host, mgt_server])

    return tabulate(table_data, headers=table_headers, tablefmt=table_format)
class TestCosmicSQL(TestCase):
    def setUp(self):
        pymysql_connect_patcher = patch('pymysql.connect')
        self.mock_connect = pymysql_connect_patcher.start()
        self.addCleanup(pymysql_connect_patcher.stop)
        self.mock_cursor = self.mock_connect.return_value.cursor.return_value

        self.cs = CosmicSQL(server='localhost',
                            password='******',
                            dry_run=False)

    @tempdir()
    def test_load_from_config(self, tmp):
        config = (b"[testmariadb]\n"
                  b"host = 10.0.0.1\n"
                  b"port = 3706\n"
                  b"user = test_user\n"
                  b"password = test_password\n")

        tmp.write('config', config)
        with patch('cosmicops.config.Path.cwd') as path_cwd_mock:
            path_cwd_mock.return_value = Path(tmp.path)
            cs = CosmicSQL(server='testmariadb')

        self.assertEqual('10.0.0.1', cs.server)
        self.assertEqual(3706, cs.port)
        self.assertEqual('test_user', cs.user)
        self.assertEqual('test_password', cs.password)

        with patch('pathlib.Path.cwd') as path_cwd_mock:
            path_cwd_mock.return_value = Path(tmp.path)
            self.assertRaises(RuntimeError, CosmicSQL, server='dummy')

    @tempdir()
    def test_load_from_config_with_defaults(self, tmp):
        config = (b"[testmariadb]\n" b"password = test_password\n")

        tmp.write('config', config)
        with patch('cosmicops.config.Path.cwd') as path_cwd_mock:
            path_cwd_mock.return_value = Path(tmp.path)
            cs = CosmicSQL(server='testmariadb')

        self.assertEqual('testmariadb', cs.server)
        self.assertEqual(3306, cs.port)
        self.assertEqual('cloud', cs.user)
        self.assertEqual('test_password', cs.password)

    @tempdir()
    def test_load_from_config_without_password(self, tmp):
        config = (b"[testmariadb]\n" b"host = 10.0.0.1\n")

        tmp.write('config', config)
        with patch('cosmicops.config.Path.cwd') as path_cwd_mock:
            path_cwd_mock.return_value = Path(tmp.path)
            self.assertRaises(configparser.NoOptionError,
                              CosmicSQL,
                              server='testmariadb')

    @tempdir()
    def test_get_all_dbs_from_config(self, tmp):
        config = (b"[dummy]\n"
                  b"foo = bar\n"
                  b"[db1]\n"
                  b"host = db1\n"
                  b"[db2]\n"
                  b"host = db2\n"
                  b"[db3]\n"
                  b"host = db3\n")

        tmp.write('config', config)
        with patch('cosmicops.config.Path.cwd') as path_cwd_mock:
            path_cwd_mock.return_value = Path(tmp.path)
            self.assertListEqual(['db1', 'db2', 'db3'],
                                 CosmicSQL.get_all_dbs_from_config())

    def test_connect_failure(self):
        self.mock_connect.side_effect = pymysql.Error('Mock connection error')
        self.assertRaises(pymysql.Error,
                          CosmicSQL,
                          server='localhost',
                          password='******')

    def test_kill_jobs_of_instance(self):
        self.assertTrue(self.cs.kill_jobs_of_instance('1'))

        self.mock_cursor.execute.assert_has_calls([
            call('DELETE FROM `async_job` WHERE `instance_id` = %s', ('1', )),
            call('DELETE FROM `vm_work_job` WHERE `vm_instance_id` = %s',
                 ('1', )),
            call('DELETE FROM `sync_queue` WHERE `sync_objid` = %s', ('1', ))
        ])
        self.assertEqual(3, self.mock_connect.return_value.commit.call_count)

    def test_kill_jobs_of_instance_dry_run(self):
        self.cs = CosmicSQL(server='localhost',
                            password='******',
                            dry_run=True)

        self.assertTrue(self.cs.kill_jobs_of_instance('1'))

        self.mock_cursor.execute.assert_has_calls([
            call('DELETE FROM `async_job` WHERE `instance_id` = %s', ('1', )),
            call('DELETE FROM `vm_work_job` WHERE `vm_instance_id` = %s',
                 ('1', )),
            call('DELETE FROM `sync_queue` WHERE `sync_objid` = %s', ('1', ))
        ])
        self.mock_connect.return_value.commit.assert_not_called()

    def test_kill_jobs_of_instance_query_failure(self):
        self.mock_cursor.execute.side_effect = pymysql.Error(
            'Mock query error')

        self.assertFalse(self.cs.kill_jobs_of_instance('i-1-VM'))

    def test_list_ha_workers(self):
        self.assertIsNotNone(self.cs.list_ha_workers())

        self.mock_cursor.execute.assert_called_with(ANY)
        self.mock_cursor.fetchall.assert_called()

    def test_list_ha_workers_with_hostname(self):
        self.assertIsNotNone(self.cs.list_ha_workers('host1'))

        self.mock_cursor.execute.assert_called_with(ANY)

    def test_list_ha_workers_query_failure(self):
        self.mock_cursor.execute.side_effect = pymysql.Error(
            'Mock query error')

        self.assertRaises(pymysql.Error, self.cs.list_ha_workers)
        self.mock_cursor.close.assert_called_once()

    def test_get_ip_address_data(self):
        self.assertIsNotNone(self.cs.get_ip_address_data('192.168.1.1'))

        self.assertIn("public_ip_address LIKE '%192.168.1.1%'",
                      self.mock_cursor.execute.call_args[0][0])
        self.assertIn("ip4_address LIKE '%192.168.1.1%'",
                      self.mock_cursor.execute.call_args[0][0])

    def test_get_ip_address_data_bridge(self):
        self.assertIsNotNone(self.cs.get_ip_address_data_bridge('192.168.1.1'))

        self.assertIn("user_ip_address.public_ip_address LIKE '%192.168.1.1%'",
                      self.mock_cursor.execute.call_args[0][0])

    def test_get_ip_address_data_infra(self):
        self.assertIsNotNone(self.cs.get_ip_address_data_infra('192.168.1.1'))

        self.assertIn("nics.ip4_address LIKE '%192.168.1.1%'",
                      self.mock_cursor.execute.call_args[0][0])

    def test_get_mac_address_data(self):
        self.assertIsNotNone(self.cs.get_mac_address_data('aa:bb:cc:dd:ee:ff'))

        self.assertIn("mac_address LIKE '%aa:bb:cc:dd:ee:ff%'",
                      self.mock_cursor.execute.call_args[0][0])

    def test_get_instance_id_from_name(self):
        self.assertIsNotNone(self.cs.get_instance_id_from_name('instance'))

        self.assertIn("instance_name = 'instance'",
                      self.mock_cursor.execute.call_args[0][0])

    def test_get_disk_offering_id_from_name(self):
        self.assertIsNotNone(
            self.cs.get_disk_offering_id_from_name('disk_offering'))

        self.assertIn("name = 'disk_offering'",
                      self.mock_cursor.execute.call_args[0][0])

    def test_get_service_offering_id_from_name(self):
        self.assertIsNotNone(
            self.cs.get_service_offering_id_from_name('service_offering'))

        self.assertIn("name = 'service_offering'",
                      self.mock_cursor.execute.call_args[0][0])

    def test_get_affinity_group_id_from_name(self):
        self.assertIsNotNone(
            self.cs.get_affinity_group_id_from_name('affinity_group'))

        self.assertIn("name = 'affinity_group'",
                      self.mock_cursor.execute.call_args[0][0])

    def test_update_zwps_to_cwps(self):
        self.cs.get_instance_id_from_name = Mock(return_value='instance_id')
        self.cs.get_disk_offering_id_from_name = Mock(
            return_value='disk_offering_id')

        self.assertTrue(
            self.cs.update_zwps_to_cwps('instance_name', 'disk_offering_name'))
        self.assertIn("disk_offering_id=",
                      self.mock_cursor.execute.call_args[0][0])
        self.assertIn("instance_id=", self.mock_cursor.execute.call_args[0][0])
        self.assertEqual(('disk_offering_id', 'instance_id'),
                         self.mock_cursor.execute.call_args[0][1])

    def test_update_service_offering_of_vm(self):
        self.cs.get_instance_id_from_name = Mock(return_value='instance_id')
        self.cs.get_service_offering_id_from_name = Mock(
            return_value='service_offering_id')

        self.assertTrue(
            self.cs.update_service_offering_of_vm('instance_name',
                                                  'service_offering_name'))
        self.assertIn("service_offering_id=",
                      self.mock_cursor.execute.call_args[0][0])
        self.assertIn("id=", self.mock_cursor.execute.call_args[0][0])
        self.assertEqual(('service_offering_id', 'instance_id'),
                         self.mock_cursor.execute.call_args[0][1])

    def test_get_volume_size(self):
        self.assertIsNotNone(self.cs.get_volume_size('path1'))

        self.assertIn("path = 'path1'",
                      self.mock_cursor.execute.call_args[0][0])

    def test_update_volume_size(self):
        self.cs.get_instance_id_from_name = Mock(return_value='instance_id')

        self.assertTrue(
            self.cs.update_volume_size('instance_name', 'path', 4321))
        self.assertIn("size=", self.mock_cursor.execute.call_args[0][0])
        self.assertIn("instance_id=", self.mock_cursor.execute.call_args[0][0])
        self.assertIn("path=", self.mock_cursor.execute.call_args[0][0])
        self.assertEqual((4321, 'path', 'instance_id'),
                         self.mock_cursor.execute.call_args[0][1])

    def test_add_vm_to_affinity_group(self):
        self.cs.get_instance_id_from_name = Mock(return_value='instance_id')
        self.cs.get_affinity_group_id_from_name = Mock(
            return_value='affinity_group_id')

        self.assertTrue(
            self.cs.add_vm_to_affinity_group('instance_name',
                                             'affinity_group_name'))
        self.assertIn("(instance_id, affinity_group_id)",
                      self.mock_cursor.execute.call_args[0][0])
        self.assertEqual(('instance_id', 'affinity_group_id'),
                         self.mock_cursor.execute.call_args[0][1])