コード例 #1
0
 def test_list_instances_fail(self):
     self.ml.container_list.side_effect = (
         lxd_exceptions.APIError('Fake', 500))
     self.assertRaises(
         exception.NovaException,
         self.connection.list_instances
     )
コード例 #2
0
ファイル: test_container.py プロジェクト: yangkf1985/nova-lxd
 def test_container_list_fail(self):
     """
     container_list returns an exception.NovaException,
     if pylxd raises an APIError.
     """
     self.ml.container_list.side_effect = (lxd_exceptions.APIError(
         'Fake', 500))
     self.assertRaises(exception.NovaException, self.session.container_list)
コード例 #3
0
 def test_live_migration_failed(self, mock_migrate):
     """Verify that an exception is raised when live-migration
        fails.
     """
     self.flags(my_ip='fakeip')
     mock_migrate.side_effect = \
         lxd_exceptions.APIError(500, 'Fake')
     self.assertRaises(lxd_exceptions.APIError, self.driver.live_migration,
                       mock.sentinel.context, mock.sentinel.instance,
                       mock.sentinel.dest, mock.sentinel.recover_method,
                       mock.sentinel.block_migration,
                       mock.sentinel.migrate_data)
コード例 #4
0
ファイル: test_container.py プロジェクト: yangkf1985/nova-lxd
 def test_container_info_fail(self):
     """
     container_info returns a dictionary reprsentation of
     userful information about a container (ip address, pid, etc).
     Verify that the container_info returns an exception.NovaException
     when there is an APIError.
     """
     instance = stubs._fake_instance()
     self.ml.container_info.side_effect = (lxd_exceptions.APIError(
         'Fake', 500))
     self.assertRaises(exception.NovaException, self.session.container_info,
                       instance)
コード例 #5
0
 def test_container_update_fail(self, tag, side_effect, expected):
     """
     container_update will fail if the container is not found, or the
     LXD raises an API error. Verify that the exceptions are raised
     in both scenarios.
     """
     config = mock.Mock()
     instance = stubs._fake_instance()
     self.ml.container_update.side_effect = (lxd_exceptions.APIError(
         'Fake', 500))
     self.assertRaises(expected, self.session.container_update, config,
                       instance)
コード例 #6
0
class SessionSnapshotTest(test.NoDBTestCase):

    def setUp(self):
        super(SessionSnapshotTest, self).setUp()

        """This is so we can mock out pylxd API calls."""
        self.ml = stubs.lxd_mock()
        lxd_patcher = mock.patch('pylxd.api.API',
                                 mock.Mock(return_value=self.ml))
        lxd_patcher.start()
        self.addCleanup(lxd_patcher.stop)

        self.session = session.LXDAPISession()

    @stubs.annotated_data(
        ('1,', (200, fake_api.fake_operation_info_ok()))
    )
    def test_container_snapshot(self, tag, side_effect):
        snapshot = mock.Mock()
        instance = stubs._fake_instance()
        self.ml.container_snapshot_create.return_value = side_effect
        self.assertEqual(None,
                         self.session.container_snapshot(snapshot, instance))
        calls = [
            mock.call.container_snapshot_create(instance.name, snapshot),
            mock.call.wait_container_operation('/1.0/operation/1234', 200, -1)]
        self.assertEqual(calls, self.ml.method_calls)

    @stubs.annotated_data(
        ('api_fail', lxd_exceptions.APIError(500, 'Fake'),
         exception.NovaException)
    )
    def test_container_snapshot_fail(self, tag, side_effect, expected):
        snapshot = mock.Mock()
        instance = stubs._fake_instance()
        self.ml.container_snapshot_create.side_effect = side_effect
        self.assertRaises(expected,
                          self.session.container_snapshot,
                          instance.name, snapshot)

    @stubs.annotated_data(
        (1, (200, fake_api.fake_operation_info_ok()))
    )
    def test_container_publish(self, tag, side_effect):
        image = mock.Mock()
        instance = stubs._fake_instance()
        self.ml.image_export.return_value = True
        self.assertTrue(
            self.session.container_publish(image, instance))
        calls = [
            mock.call.container_publish(image)]
        self.assertEqual(calls, self.ml.method_calls)
コード例 #7
0
class SessionContainerTest(test.NoDBTestCase):

    def setUp(self):
        super(SessionContainerTest, self).setUp()

        """This is so we can mock out pylxd API calls."""
        self.ml = stubs.lxd_mock()
        lxd_patcher = mock.patch('pylxd.deprecated.api.API',
                                 mock.Mock(return_value=self.ml))
        lxd_patcher.start()
        self.addCleanup(lxd_patcher.stop)

        self.session = session.LXDAPISession()

    @stubs.annotated_data(
        ('1', (200, fake_api.fake_operation_info_ok()))
    )
    def test_container_init(self, tag, side_effect):
        """
        conatainer_init creates a container based on given config
        for a container. Check to see if we are returning the right
        pylxd calls for the LXD API.
        """
        config = mock.Mock()
        instance = stubs._fake_instance()
        self.ml.container_init.return_value = side_effect
        self.ml.operation_info.return_value = \
            (200, fake_api.fake_container_state(200))
        self.assertIsNone(self.session.container_init(config, instance))
        calls = [mock.call.container_init(config),
                 mock.call.wait_container_operation(
                     '/1.0/operation/1234', 200, -1),
                 mock.call.operation_info('/1.0/operation/1234')]
        self.assertEqual(calls, self.ml.method_calls)

    @stubs.annotated_data(
        ('api_fail', lxd_exceptions.APIError(500, 'Fake'),
         exception.NovaException),
    )
    def test_container_init_fail(self, tag, side_effect, expected):
        """
        continer_init create as container on a given LXD host. Make
        sure that we reaise an exception.NovaException if there is
        an APIError from the LXD API.
        """
        config = mock.Mock()
        instance = stubs._fake_instance()
        self.ml.container_init.side_effect = side_effect
        self.assertRaises(expected,
                          self.session.container_init, config,
                          instance)
コード例 #8
0
 def test_destroy_fail(self):
     instance = stubs._fake_instance()
     context = mock.Mock()
     network_info = mock.Mock()
     self.ml.container_destroy.side_effect = (lxd_exceptions.APIError(
         'Fake', 500))
     with test.nested(
             mock.patch.object(session.LXDAPISession, 'container_destroy'),
             mock.patch.object(session.LXDAPISession, 'container_stop'),
             mock.patch.object(self.connection, 'cleanup'),
             mock.patch.object(container_ops.LXDContainerOperations,
                               'unplug_vifs'),
     ) as (container_destroy, container_stop, cleanup, unplug_vifs):
         self.connection.destroy(context, instance, network_info)
コード例 #9
0
ファイル: test_container.py プロジェクト: yangkf1985/nova-lxd
 def test_container_state_fail(self, tag, container_defined, side_effect,
                               expected):
     """
     container_state translates LXD container status into
     what nova understands. If the API sends an APIError
     then raise an power_state.NOSTATE, same if the
     the container goes missing.
     """
     instance = stubs._fake_instance()
     if container_defined:
         self.ml.container_defined.return_value = container_defined
         self.ml.container_state.side_effect = (lxd_exceptions.APIError(
             'Fake', 500))
         self.assertEqual(expected, self.session.container_state(instance))
     if not container_defined:
         self.ml.container_defined.return_value = container_defined
         self.assertEqual(expected, self.session.container_state(instance))
コード例 #10
0
def get_lxd_error(state, data):
    status_code = data.get("error_code")
    error = data.get("error")
    raise exceptions.APIError(error, status_code)
コード例 #11
0
ファイル: test_image.py プロジェクト: wiedenmeier/pylxd
class LXDAPIImageTestObject(LXDAPITestBase):

    list_data = (
        ('list', (), ()),
        ('search', ({
            'foo': 'bar'
        }, ), ('foo=bar', )),
    )

    @annotated_data(*list_data)
    def test_list_images(self, method, args, call_args, ms):
        ms.return_value = ('200', fake_api.fake_image_list())
        self.assertEqual(['trusty'],
                         getattr(self.lxd, 'image_' + method)(*args))
        ms.assert_called_once_with('GET', '/1.0/images', *call_args)

    @annotated_data(*list_data)
    def test_list_images_fail(self, method, args, call_args, ms):
        ms.side_effect = exceptions.PyLXDException
        self.assertRaises(exceptions.PyLXDException,
                          getattr(self.lxd, 'image_' + method), *args)
        ms.assert_called_once_with('GET', '/1.0/images', *call_args)

    @annotated_data(
        (True, (('200', fake_api.fake_image_info()), )),
        (False, exceptions.APIError("404", 404)),
    )
    def test_image_defined(self, expected, side_effect, ms):
        ms.side_effect = side_effect
        self.assertEqual(expected, self.lxd.image_defined('test-image'))
        ms.assert_called_once_with('GET', '/1.0/images/test-image')

    @annotated_data(
        ('APIError', exceptions.APIError("500", 500), exceptions.APIError),
        ('PyLXDException', exceptions.PyLXDException,
         exceptions.PyLXDException))
    def test_image_defined_fail(self, tag, side_effect, expected, ms):
        ms.side_effect = side_effect
        self.assertRaises(expected, self.lxd.image_defined, ('test-image', ))
        ms.assert_called_once_with('GET', '/1.0/images/test-image')

    def test_image_info(self, ms):
        self.assertEqual(
            {
                'image_upload_date': (datetime.datetime.fromtimestamp(
                    1435669853).strftime('%Y-%m-%d %H:%M:%S')),
                'image_created_date':
                'Unknown',
                'image_expires_date':
                'Unknown',
                'image_public':
                False,
                'image_size':
                '63MB',
                'image_fingerprint':
                '04aac4257341478b49c25d22cea8a6ce'
                '0489dc6c42d835367945e7596368a37f',
                'image_architecture':
                'x86_64',
            }, self.lxd.image_info('test-image'))
        ms.assert_called_once_with('GET', '/1.0/images/test-image')

    def test_image_info_fail(self, ms):
        ms.side_effect = exceptions.PyLXDException
        self.assertRaises(exceptions.PyLXDException, self.lxd.image_info,
                          ('test-image', ))
        ms.assert_called_once_with('GET', '/1.0/images/test-image')

    dates_data = (
        ('upload', (datetime.datetime.fromtimestamp(1435669853).strftime(
            '%Y-%m-%d %H:%M:%S'))),
        ('create', 'Unknown'),
        ('expire', 'Unknown'),
    )

    @annotated_data(*dates_data)
    def test_image_date(self, method, expected, ms):
        self.assertEqual(
            expected,
            getattr(self.lxd, 'image_{}_date'.format(method))('test-image',
                                                              data=None))
        ms.assert_called_once_with('GET', '/1.0/images/test-image')

    @annotated_data(*dates_data)
    def test_image_date_fail(self, method, expected, ms):
        ms.side_effect = exceptions.PyLXDException
        self.assertRaises(exceptions.PyLXDException,
                          getattr(self.lxd, 'image_{}_date'.format(method)),
                          'test-image',
                          data=None)
        ms.assert_called_once_with('GET', '/1.0/images/test-image')
コード例 #12
0
 def test_profile_list_fail(self):
     self.ml.profile_list.side_effect = (lxd_exceptions.APIError(
         'Fake', 500))
     self.assertRaises(exception.NovaException, self.session.profile_list)
コード例 #13
0
class LXDTestDriver(test.NoDBTestCase):
    @mock.patch.object(driver, 'CONF', stubs.MockConf())
    def setUp(self):
        super(LXDTestDriver, self).setUp()
        self.ml = stubs.lxd_mock()
        lxd_patcher = mock.patch('pylxd.api.API',
                                 mock.Mock(return_value=self.ml))
        lxd_patcher.start()
        self.addCleanup(lxd_patcher.stop)

        self.connection = driver.LXDDriver(fake.FakeVirtAPI())

    def test_capabilities(self):
        self.assertFalse(self.connection.capabilities['has_imagecache'])
        self.assertFalse(self.connection.capabilities['supports_recreate'])
        self.assertFalse(
            self.connection.capabilities['supports_migrate_to_same_host'])
        self.assertTrue(
            self.connection.capabilities['supports_attach_interface'])

    def test_init_host(self):
        self.assertEqual(True, self.connection.init_host(None))

    def test_init_host_new_profile(self):
        self.ml.profile_list.return_value = []
        self.assertEqual(True, self.connection.init_host(None))

    @stubs.annotated_data(
        ('no_ping', {
            'host_ping.return_value': False
        }),
        ('ping_fail', {
            'host_ping.side_effect': (lxd_exceptions.APIError('Fake', 500))
        }),
    )
    def test_init_host_fail(self, tag, config):
        self.ml.configure_mock(**config)
        self.assertRaises(exception.HostNotFound, self.connection.init_host,
                          None)

    @stubs.annotated_data(
        ('running', {
            'state': 200,
            'mem': 0,
            'max_mem': 0
        }, power_state.RUNNING),
        ('shutdown', {
            'state': 102,
            'mem': 0,
            'max_mem': 0
        }, power_state.SHUTDOWN),
        ('crashed', {
            'state': 108,
            'mem': 0,
            'max_mem': 0
        }, power_state.CRASHED),
        ('suspend', {
            'state': 109,
            'mem': 0,
            'max_mem': 0
        }, power_state.SUSPENDED),
        ('no_state', {
            'state': 401,
            'mem': 0,
            'max_mem': 0
        }, power_state.NOSTATE),
    )
    def test_get_info(self, tag, side_effect, expected):
        instance = stubs._fake_instance()
        with mock.patch.object(
                session.LXDAPISession,
                "container_state",
        ) as state:
            state.return_value = side_effect
            info = self.connection.get_info(instance)
            self.assertEqual(
                dir(hardware.InstanceInfo(state=expected, num_cpu=2)),
                dir(info))

    @stubs.annotated_data(
        (True, 'mock-instance-1'),
        (False, 'fake-instance'),
    )
    def test_instance_exists(self, expected, name):
        self.assertEqual(
            expected,
            self.connection.instance_exists(stubs.MockInstance(name=name)))

    def test_estimate_instance_overhead(self):
        self.assertEqual({'memory_mb': 0},
                         self.connection.estimate_instance_overhead(
                             mock.Mock()))

    def test_list_instances(self):
        self.assertEqual(['mock-instance-1', 'mock-instance-2'],
                         self.connection.list_instances())

    def test_list_instances_fail(self):
        self.ml.container_list.side_effect = (lxd_exceptions.APIError(
            'Fake', 500))
        self.assertRaises(exception.NovaException,
                          self.connection.list_instances)

    @stubs.annotated_data(
        ('exists', [True], exception.InstanceExists),
        ('fail', lxd_exceptions.APIError('Fake', 500), exception.NovaException)
    )
    def test_spawn_defined(self, tag, side_effect, expected):
        instance = stubs.MockInstance()
        self.ml.container_defined.side_effect = side_effect
        self.assertRaises(expected, self.connection.spawn, {}, instance, {},
                          [], 'secret')
        self.ml.container_defined.called_once_with('mock_instance')

    @stubs.annotated_data(
        ('undefined', False),
        ('404', lxd_exceptions.APIError('Not found', 404)),
    )
    @mock.patch('oslo_concurrency.lockutils.lock')
    def test_spawn_new(self, tag, side_effect, mc):
        context = mock.Mock()
        instance = stubs.MockInstance()
        image_meta = mock.Mock()
        injected_files = mock.Mock()
        network_info = mock.Mock()
        block_device_info = mock.Mock()
        self.ml.container_defined.side_effect = [side_effect]

        with test.nested(
                mock.patch.object(self.connection.container_ops,
                                  'spawn'), ) as (create_container):
            self.connection.spawn(context, instance, image_meta,
                                  injected_files, None, network_info,
                                  block_device_info)
            self.assertTrue(create_container)

    def test_destroy_fail(self):
        instance = stubs._fake_instance()
        context = mock.Mock()
        network_info = mock.Mock()
        self.ml.container_destroy.side_effect = (lxd_exceptions.APIError(
            'Fake', 500))
        with test.nested(
                mock.patch.object(session.LXDAPISession, 'container_destroy'),
                mock.patch.object(session.LXDAPISession, 'container_stop'),
                mock.patch.object(self.connection, 'cleanup'),
                mock.patch.object(container_ops.LXDContainerOperations,
                                  'unplug_vifs'),
        ) as (container_destroy, container_stop, cleanup, unplug_vifs):
            self.connection.destroy(context, instance, network_info)

    def test_destroy(self):
        instance = stubs._fake_instance()
        context = mock.Mock()
        network_info = mock.Mock()
        with test.nested(
                mock.patch.object(session.LXDAPISession, 'container_stop'),
                mock.patch.object(session.LXDAPISession, 'container_destroy'),
                mock.patch.object(self.connection, 'cleanup'),
                mock.patch.object(container_ops.LXDContainerOperations,
                                  'unplug_vifs'),
        ) as (container_stop, container_destroy, cleanup, unplug_vifs):
            self.connection.destroy(context, instance, network_info)
            self.assertTrue(container_stop)
            self.assertTrue(container_destroy)
            self.assertTrue(cleanup)
            unplug_vifs.assert_called_with(instance, network_info)

    @mock.patch('os.path.exists', mock.Mock(return_value=True))
    @mock.patch('shutil.rmtree')
    @mock.patch('pwd.getpwuid', mock.Mock(return_value=mock.Mock(pw_uid=1234)))
    @mock.patch.object(container_ops.utils, 'execute')
    def test_cleanup(self, mr, mu):
        instance = stubs.MockInstance()
        self.assertEqual(
            None,
            self.connection.cleanup({}, instance, [], [], None, None, None))

    @mock.patch('six.moves.builtins.open')
    @mock.patch.object(container_ops.utils, 'execute')
    @mock.patch('pwd.getpwuid', mock.Mock(return_value=mock.Mock(pw_uid=1234)))
    @mock.patch('os.getuid', mock.Mock())
    @mock.patch('os.path.exists', mock.Mock(return_value=True))
    def test_get_console_output(self, me, mo):
        instance = stubs.MockInstance()
        mo.return_value.__enter__.return_value = six.BytesIO(b'fake contents')
        self.assertEqual(b'fake contents',
                         self.connection.get_console_output({}, instance))
        calls = [
            mock.call('chown',
                      '1234:1234',
                      '/var/log/lxd/fake-uuid/console.log',
                      run_as_root=True),
            mock.call('chmod',
                      '755',
                      '/fake/lxd/root/containers/fake-uuid',
                      run_as_root=True)
        ]
        self.assertEqual(calls, me.call_args_list)

    @mock.patch.object(host.compute_utils, 'get_machine_ips')
    @stubs.annotated_data(
        ('found', ['1.2.3.4']),
        ('not-found', ['4.3.2.1']),
    )
    def test_get_host_ip_addr(self, tag, return_value, mi):
        mi.return_value = return_value
        self.assertEqual('1.2.3.4', self.connection.get_host_ip_addr())

    @mock.patch('socket.gethostname', mock.Mock(return_value='fake_hostname'))
    @mock.patch('os.statvfs',
                return_value=mock.Mock(f_blocks=131072000,
                                       f_bsize=8192,
                                       f_bavail=65536000))
    @mock.patch('six.moves.builtins.open')
    @mock.patch.object(container_ops.utils, 'execute')
    def test_get_available_resource(self, me, mo, ms):
        me.return_value = ('Model name:          Fake CPU\n'
                           'Vendor ID:           FakeVendor\n'
                           'Socket(s):           10\n'
                           'Core(s) per socket:  5\n'
                           'Thread(s) per core:  4\n'
                           '\n', None)
        meminfo = mock.MagicMock()
        meminfo.__enter__.return_value = six.moves.cStringIO(
            'MemTotal: 10240000 kB\n'
            'MemFree:   2000000 kB\n'
            'Buffers:     24000 kB\n'
            'Cached:      24000 kB\n')

        mo.side_effect = [
            six.moves.cStringIO('flags: fake flag goes here\n'
                                'processor: 2\n'
                                '\n'),
            meminfo,
        ]
        value = self.connection.get_available_resource(None)
        value['cpu_info'] = json.loads(value['cpu_info'])
        value['supported_instances'] = [
            [arch.I686, hv_type.LXD, vm_mode.EXE],
            [arch.X86_64, hv_type.LXD, vm_mode.EXE],
            [arch.I686, hv_type.LXC, vm_mode.EXE],
            [arch.X86_64, hv_type.LXC, vm_mode.EXE]
        ]
        expected = {
            'cpu_info': {
                u'arch': platform.uname()[5],
                u'features': u'fake flag goes here',
                u'model': u'Fake CPU',
                u'topology': {
                    u'cores': u'5',
                    u'sockets': u'10',
                    u'threads': u'4'
                },
                u'vendor': u'FakeVendor'
            },
            'hypervisor_hostname':
            'fake_hostname',
            'hypervisor_type':
            'lxd',
            'hypervisor_version':
            '011',
            'local_gb':
            1000,
            'local_gb_used':
            500,
            'memory_mb':
            10000,
            'memory_mb_used':
            8000,
            'numa_topology':
            None,
            'supported_instances': [[arch.I686, hv_type.LXD, vm_mode.EXE],
                                    [arch.X86_64, hv_type.LXD, vm_mode.EXE],
                                    [arch.I686, hv_type.LXC, vm_mode.EXE],
                                    [arch.X86_64, hv_type.LXC, vm_mode.EXE]],
            'vcpus':
            200,
            'vcpus_used':
            0
        }
        self.assertEqual(expected, value)
        me.assert_called_once_with('lscpu')
        self.assertEqual(
            [mock.call('/proc/cpuinfo', 'r'),
             mock.call('/proc/meminfo')], mo.call_args_list)
        ms.assert_called_once_with('/fake/lxd/root')

    def test_container_reboot(self):
        instance = stubs._fake_instance()
        context = mock.Mock()
        network_info = mock.Mock()
        reboot_type = 'SOFT'
        with test.nested(
                mock.patch.object(self.connection.container_ops,
                                  'reboot')) as (reboot):
            self.connection.reboot(context, instance, network_info,
                                   reboot_type)
            self.assertTrue(reboot)

    def test_container_power_off(self):
        instance = stubs._fake_instance()
        with test.nested(
                mock.patch.object(self.connection.container_ops,
                                  'power_off')) as (power_off):
            self.connection.power_off(instance)
            self.assertTrue(power_off)

    def test_container_power_on(self):
        context = mock.Mock()
        instance = stubs._fake_instance()
        network_info = mock.Mock()
        with test.nested(
                mock.patch.object(self.connection.container_ops,
                                  'power_on')) as (power_on):
            self.connection.power_on(context, instance, network_info)
            self.assertTrue(power_on)

    @stubs.annotated_data(
        ('refresh_security_group_rules', (mock.Mock(), )),
        ('refresh_security_group_members', (mock.Mock(), )),
        ('refresh_provider_fw_rules', ),
        ('refresh_instance_security_rules', (mock.Mock(), )),
        ('ensure_filtering_rules_for_instance', (mock.Mock(), mock.Mock())),
        ('filter_defer_apply_on', ),
        ('filter_defer_apply_off', ),
        ('unfilter_instance', (mock.Mock(), mock.Mock())),
    )
    def test_firewall_calls(self, name, args=()):
        with mock.patch.object(self.connection.container_firewall,
                               'firewall_driver') as mf:
            driver_method = getattr(self.connection, name)
            firewall_method = getattr(mf, name)
            self.assertEqual(firewall_method.return_value,
                             driver_method(*args))
            firewall_method.assert_called_once_with(*args)

    @mock.patch.object(host.utils, 'execute')
    def test_get_host_uptime(self, me):
        me.return_value = ('out', 'err')
        self.assertEqual('out', self.connection.get_host_uptime())

    @mock.patch('socket.gethostname', mock.Mock(return_value='mock_hostname'))
    def test_get_available_nodes(self):
        self.assertEqual(['mock_hostname'],
                         self.connection.get_available_nodes())

    @mock.patch('socket.gethostname', mock.Mock(return_value='mock_hostname'))
    @stubs.annotated_data(
        ('mock_hostname', True),
        ('wrong_hostname', False),
    )
    def test_node_is_available(self, nodename, available):
        self.assertEqual(available,
                         self.connection.node_is_available(nodename))
コード例 #14
0
class SessionContainerTest(test.NoDBTestCase):

    def setUp(self):
        super(SessionContainerTest, self).setUp()

        """This is so we can mock out pylxd API calls."""
        self.ml = stubs.lxd_mock()
        lxd_patcher = mock.patch('pylxd.api.API',
                                 mock.Mock(return_value=self.ml))
        lxd_patcher.start()
        self.addCleanup(lxd_patcher.stop)

        self.session = session.LXDAPISession()

    @stubs.annotated_data(
        ('empty', [], []),
        ('valid', ['test'], ['test']),
    )
    def test_container_list(self, tag, side_effect, expected):
        """
        container_list returns a list of LXD containers
        found on an LXD host.
        """
        self.ml.container_list.return_value = side_effect
        self.assertEqual(expected,
                         self.session.container_list())

    def test_container_list_fail(self):
        """
        container_list returns an exception.NovaException,
        if pylxd raises an APIError.
        """
        self.ml.container_list.side_effect = (
            lxd_exceptions.APIError('Fake', 500))
        self.assertRaises(
            exception.NovaException,
            self.session.container_list)

    def test_container_update(self):
        """
        container_update updates the LXD container configuration,
        so verify that the correct pylxd calls are made.
        """
        config = mock.Mock()
        instance = stubs._fake_instance()
        self.ml.container_update.return_value = \
            (200, fake_api.fake_container_config())
        self.assertEqual((200, fake_api.fake_container_config()),
                         self.session.container_update(config, instance))
        calls = [
            mock.call.container_defined(instance.name),
            mock.call.container_update(instance.name, config)]
        self.assertEqual(calls, self.ml.method_calls)

    @stubs.annotated_data(
        ('api_fail', True, lxd_exceptions.APIError('Fake', 500),
         exception.NovaException),
        ('missing_container', False, None,
         exception.InstanceNotFound)
    )
    def test_container_update_fail(self, tag, container_defined, side_effect,
                                   expected):
        """
        container_update will fail if the container is not found, or the
        LXD raises an API error. Verify that the exceptions are raised
        in both scenarios.
        """
        config = mock.Mock()
        instance = stubs._fake_instance()
        if container_defined:
            self.ml.container_defined.return_value = container_defined
            self.ml.container_update.side_effect = (
                lxd_exceptions.APIError('Fake', 500))
            self.assertRaises(
                expected,
                self.session.container_update, config, instance)
        if not container_defined:
            self.ml.container_defined.return_value = container_defined
            self.assertRaises(
                expected,
                self.session.container_update, config, instance)

    @stubs.annotated_data(
        ('running', True),
        ('idle', False),
        ('api_failure', lxd_exceptions.APIError('Fake', '500')),
    )
    def test_container_running(self, tag, side_effect):
        """
        container_running determines if the container is running
        or not. Verify that we are returning True if the container
        is running. False if its not, raise an exception if there
        is an API error.
        """
        instance = stubs._fake_instance()
        if side_effect:
            self.ml.container_running.return_value = side_effect
            self.assertTrue(self.session.container_running(instance))
        if not side_effect:
            self.ml.container_running.return_value = side_effect
            self.assertFalse(self.session.container_running(instance))
        if tag == 'api_failure':
            self.ml.container_running.side_effect = side_effect
            self.assertRaises(
                exception.NovaException,
                self.session.container_running, instance
            )

    def test_container_state(self):
        """
        container_state translates LXD container status into
        what nova understands. Verify that status_code sends
        a power_state.RUNNING and a 108 sends a
        power_state.CRASHED.
        """
        calls = []
        self.assertEqual(calls, self.ml.method_calls)

    @stubs.annotated_data(
        ('api_fail', True, lxd_exceptions.APIError('Fake', 500),
         {'state': power_state.NOSTATE, 'mem': 0, 'max_mem': 0})
    )
    def test_container_state_fail(self, tag, container_defined, side_effect,
                                  expected):
        """
        container_state translates LXD container status into
        what nova understands. If the API sends an APIError
        then raise an power_state.NOSTATE, same if the
        the container goes missing.
        """
        instance = stubs._fake_instance()
        if container_defined:
            self.ml.container_defined.return_value = container_defined
            self.ml.container_state.side_effect = (
                lxd_exceptions.APIError('Fake', 500))
            self.assertEqual(
                expected,
                self.session.container_state(instance))
        if not container_defined:
            self.ml.container_defined.return_value = container_defined
            self.assertEqual(
                expected,
                self.session.container_state(instance))

    def test_container_config(self):
        """
        container_config returns a dictionary representation
        of the LXD container. Verify that the funciton returns
        a container_config
        """
        instance = stubs._fake_instance()
        self.ml.get_container_config.return_value = \
            (200, fake_api.fake_container_config())
        self.assertEqual(
            (200, fake_api.fake_container_config()),
            self.session.container_config(instance))

    @stubs.annotated_data(
        ('api_fail', True, lxd_exceptions.APIError('Fake', 500),
         exception.NovaException),
    )
    def test_container_config_fail(self, tag, container_defined, side_effect,
                                   expected):
        """
        container_config returns a dictionary represeation of the
        LXD container. Verify that the function raises an
        exception.NovaException when there is a APIError.
        """
        instance = stubs._fake_instance()
        if container_defined:
            self.ml.container_defined.return_value = container_defined
            self.ml.get_container_config.side_effect = side_effect
            self.assertRaises(
                expected,
                self.session.container_config, instance)

    def test_container_info(self):
        """
        container_info returns a dictonary represenation of
        useful information about a container, (ip address, pid, etc).
        Verify that the function returns the approiate dictionary
        representation for the LXD API.
        """
        instance = stubs._fake_instance()
        self.ml.container_info.return_value = \
            (200, fake_api.fake_container_info())
        self.assertEqual(
            (200, fake_api.fake_container_info()),
            self.session.container_info(instance))

    def test_container_info_fail(self):
        """
        container_info returns a dictionary reprsentation of
        userful information about a container (ip address, pid, etc).
        Verify that the container_info returns an exception.NovaException
        when there is an APIError.
        """
        instance = stubs._fake_instance()
        self.ml.container_info.side_effect = (
            lxd_exceptions.APIError('Fake', 500))
        self.assertRaises(
            exception.NovaException,
            self.session.container_info, instance)

    @stubs.annotated_data(
        ('exists', True),
        ('missing', False),
    )
    def test_container_defined(self, tag, side_effect):
        """
        container_defined returns True if the container
        exists on an LXD host, False otherwise, verify
        the apporiate return value is returned.
        """
        instance = stubs._fake_instance()
        self.ml.container_defined.return_value = side_effect
        if side_effect:
            self.assertTrue(self.session.container_defined(
                instance.name, instance))
        if not side_effect:
            self.assertFalse(self.session.container_defined(
                instance.name, instance))

    @stubs.annotated_data(
        ('1', True, (200, fake_api.fake_operation_info_ok()))
    )
    def test_container_start(self, tag, defined, side_effect=None):
        """
        containser_start starts a container on a given LXD host.
        Verify that the correct pyLXD calls are made.
        """
        instance = stubs._fake_instance()
        self.ml.container_defined.return_value = defined
        self.ml.container_start.return_value = side_effect
        self.assertEqual(None,
                         self.session.container_start(instance.name,
                                                      instance))
        calls = [mock.call.container_defined(instance.name),
                 mock.call.container_start(instance.name, -1),
                 mock.call.wait_container_operation(
            '/1.0/operation/1234', 200, -1)]
        self.assertEqual(calls, self.ml.method_calls)

    @stubs.annotated_data(
        ('container_missing', False,
         exception.InstanceNotFound),
        ('api_error', True,
         exception.NovaException,
         lxd_exceptions.APIError('Fake', 500)),
    )
    def test_container_start_fail(self, tag, container_defined,
                                  expected, side_effect=None):
        """
        container_start starts a container on a given LXD host.
        Veify that an exception.InstanceNotFound when the container
        is not found on an LXD host. Raises an exception.NovaException
        when there is an APIError.
        """
        instance = stubs._fake_instance()
        if container_defined:
            self.ml.container_defined.return_value = container_defined
            self.ml.container_start.side_effect = side_effect
            self.assertRaises(expected,
                              self.session.container_start,
                              instance.name, instance)
        if not container_defined:
            self.ml.container_defined.return_value = container_defined
            self.assertRaises(expected,
                              self.session.container_start, instance.name,
                              instance)

    @stubs.annotated_data(
        ('1', (200, fake_api.fake_operation_info_ok()))
    )
    def test_container_stop(self, tag, side_effect):
        """
        container_stop stops a container on a given LXD ost.
        Verifty that that the apprioated pylxd calls are
        made to the LXD api.
        """
        instance = stubs._fake_instance()
        self.ml.container_stop.return_value = side_effect
        self.assertEqual(None,
                         self.session.container_stop(instance.name,
                                                     instance))
        calls = [mock.call.container_defined(instance.name),
                 mock.call.container_stop(instance.name, -1),
                 mock.call.wait_container_operation(
            '/1.0/operation/1234', 200, -1)]
        self.assertEqual(calls, self.ml.method_calls)

    @stubs.annotated_data(
        ('api_fail', lxd_exceptions.APIError('Fake', 500),
         exception.NovaException)
    )
    def test_container_stop_fail(self, tag, side_effect, expected):
        """
        contianer_stop stops a container on a given LXD host.
        Verifty that we raise an exception.NovaException when there is an
        APIError.
        """
        instance = stubs._fake_instance()
        self.ml.container_stop.side_effect = side_effect
        self.assertRaises(expected,
                          self.session.container_stop, instance.name,
                          instance)

    @stubs.annotated_data(
        ('1,', (200, fake_api.fake_operation_info_ok()))
    )
    def test_continer_reboot(self, tag, side_effect):
        """"
        container_reboot reboots a container on a given LXD host.
        Verify that the right pylxd calls are made to the LXD host.
        """
        instance = stubs._fake_instance()
        self.ml.container_reboot.return_value = side_effect
        self.assertEqual(None,
                         self.session.container_reboot(instance))
        calls = [mock.call.container_defined(instance.name),
                 mock.call.container_reboot(instance.name, -1),
                 mock.call.wait_container_operation(
                     '/1.0/operation/1234', 200, -1)]
        self.assertEqual(calls, self.ml.method_calls)

    @stubs.annotated_data(
        ('api_fail', lxd_exceptions.APIError('Fake', 500),
         exception.NovaException)
    )
    def test_container_reboot_fail(self, tag, side_effect, expected):
        """
        container_reboot reboots a container on a given LXD host.
        Check that an exception.NovaException is raised when
        there is an LXD API error.
        """
        instance = stubs._fake_instance()
        self.ml.container_reboot.side_effect = side_effect
        self.assertRaises(expected,
                          self.session.container_reboot, instance)

    @stubs.annotated_data(
        ('exists', True, (200, fake_api.fake_operation_info_ok())),
        ('missing', False, (200, fake_api.fake_operation_info_ok()))
    )
    def test_container_destroy(self, tag, container_defined, side_effect):
        """
        container_destroy delete a container from the LXD Host. Check
        that the approiate pylxd calls are made.
        """
        instance = stubs._fake_instance()
        if container_defined:
            self.ml.container_defined.return_value = container_defined
            self.ml.container_stop.return_value = side_effect
            self.ml.container_destroy.return_value = side_effect
            self.assertEqual(None,
                             self.session.container_destroy(instance.name,
                                                            instance))
            calls = [mock.call.container_defined(instance.name),
                     mock.call.container_defined(instance.name),
                     mock.call.container_stop(instance.name, -1),
                     mock.call.wait_container_operation(
                '/1.0/operation/1234', 200, -1),
                mock.call.container_destroy(instance.name),
                mock.call.wait_container_operation(
                '/1.0/operation/1234', 200, -1)]
            self.assertEqual(calls, self.ml.method_calls)
        if not container_defined:
            self.ml.container_defined.return_value = container_defined
            self.assertEqual(None,
                             self.session.container_destroy(instance.name,
                                                            instance))
            calls = [mock.call.container_defined(instance.name)]
            self.assertEqual(calls, self.ml.method_calls)

    @stubs.annotated_data(
        ('fail_to_stop', True, 'fail_stop',
         lxd_exceptions.APIError('Fake', '500'), exception.NovaException),
        ('fail_to_destroy', True, 'fail_destroy',
         lxd_exceptions.APIError('Fake', '500'), exception.NovaException)
    )
    def test_container_destroy_fail(self, tag, container_defined,
                                    test_type, side_effect, expected):
        """
        container_destroy deletes a container on the LXD host.
        Check whether an exeption.NovaException is raised when
        there is an APIError or when the container fails to stop.
        """
        instance = stubs._fake_instance()
        self.ml.cotnainer_defined.return_value = container_defined
        if test_type == 'fail_stop':
            self.ml.container_stop.side_effect = side_effect
            self.assertRaises(expected,
                              self.session.container_destroy, instance.name,
                              instance)
        if test_type == 'fail_destroy':
            self.ml.container_defined.return_value = container_defined
            self.ml.container_stop.return_value = \
                (200, fake_api.fake_operation_info_ok())
            self.ml.container_destroy.side_effect = side_effect
            self.assertRaises(expected,
                              self.session.container_destroy, instance.name,
                              instance)

    @stubs.annotated_data(
        ('1', (200, fake_api.fake_operation_info_ok()))
    )
    def fake_container_pause(self, tag, side_effect):
        """
        container_pause pauses a container on a given LXD host.
        Verify that the appropiate pylxd API calls are made.
        """
        instance = stubs._fake_instance()
        self.ml.container_suspend.return_value = side_effect
        self.assertEqual(None,
                         self.session.container_pause(instance.name,
                                                      instance))
        calls = [
            mock.call.container_susepnd(instance.name, -1),
            mock.call.wait_container_operation(
                '/1.0/operation/1234', 200, -1)]
        self.assertEqual(calls, self.ml.method_calls)

    @stubs.annotated_data(
        ('api_fail', lxd_exceptions.APIError(500, 'Fake'),
         exception.NovaException)
    )
    def test_container_pause_fail(self, tag, side_effect, expected):
        """
        container_pause pauses a contianer on a LXD host. Verify
        that an exception.NovaException is raised when there
        is an APIError.
        """
        instance = stubs._fake_instance()
        instance = stubs._fake_instance()
        self.ml.container_suspend.side_effect = side_effect
        self.assertRaises(expected,
                          self.session.container_pause,
                          instance.name, instance)

    @stubs.annotated_data(
        ('1', (200, fake_api.fake_operation_info_ok()))
    )
    def test_container_unpause(self, tag, side_effect):
        """
        container_unpase unpauses a continer on a LXD host.
        Check that the right pylxd calls are being sent
        to the LXD API server.
        """
        instance = stubs._fake_instance()
        self.ml.container_resume.return_value = side_effect
        self.assertEqual(None,
                         self.session.container_unpause(instance.name,
                                                        instance))
        calls = [
            mock.call.container_defined(instance.name),
            mock.call.container_resume(instance.name, -1),
            mock.call.wait_container_operation(
                '/1.0/operation/1234', 200, -1)]
        self.assertEqual(calls, self.ml.method_calls)

    @stubs.annotated_data(
        ('api_fail', lxd_exceptions.APIError(500, 'Fake'),
         exception.NovaException)
    )
    def test_container_unpause_fail(self, tag, side_effect, expected):
        """
        container_unpause resumes a previously suespended container.
        Validate that an exception.NovaException is raised when a
        APIError is sent by the API.
        """
        instance = stubs._fake_instance()
        self.ml.container_resume.side_effect = side_effect
        self.assertRaises(expected,
                          self.session.container_unpause,
                          instance.name, instance)

    @stubs.annotated_data(
        ('1', (200, fake_api.fake_operation_info_ok()))
    )
    def test_container_init(self, tag, side_effect):
        """
        conatainer_init creates a container based on given config
        for a container. Check to see if we are returning the right
        pylxd calls for the LXD API.
        """
        config = mock.Mock()
        instance = stubs._fake_instance()
        self.ml.container_init.return_value = side_effect
        self.ml.operation_info.return_value = \
            (200, fake_api.fake_container_state(200))
        self.assertEqual(None,
                         self.session.container_init(config, instance))
        calls = [mock.call.container_init(config),
                 mock.call.wait_container_operation(
                     '/1.0/operation/1234', 200, -1),
                 mock.call.operation_info('/1.0/operation/1234')]
        self.assertEqual(calls, self.ml.method_calls)

    @stubs.annotated_data(
        ('api_fail', lxd_exceptions.APIError(500, 'Fake'),
         exception.NovaException),
    )
    def test_container_init_fail(self, tag, side_effect, expected):
        """
        continer_init create as container on a given LXD host. Make
        sure that we reaise an exception.NovaException if there is
        an APIError from the LXD API.
        """
        config = mock.Mock()
        instance = stubs._fake_instance()
        self.ml.container_init.side_effect = side_effect
        self.assertRaises(expected,
                          self.session.container_init, config,
                          instance)
コード例 #15
0
class LXDAPIImageTestObject(LXDAPITestBase):

    list_data = (
        ("list", (), ()),
        ("search", ({
            "foo": "bar"
        }, ), ("foo=bar", )),
    )

    @annotated_data(*list_data)
    def test_list_images(self, method, args, call_args, ms):
        ms.return_value = ("200", fake_api.fake_image_list())
        self.assertEqual(["trusty"],
                         getattr(self.lxd, "image_" + method)(*args))
        ms.assert_called_once_with("GET", "/1.0/images", *call_args)

    @annotated_data(*list_data)
    def test_list_images_fail(self, method, args, call_args, ms):
        ms.side_effect = exceptions.PyLXDException
        self.assertRaises(exceptions.PyLXDException,
                          getattr(self.lxd, "image_" + method), *args)
        ms.assert_called_once_with("GET", "/1.0/images", *call_args)

    @annotated_data(
        (True, (("200", fake_api.fake_image_info()), )),
        (False, exceptions.APIError("404", 404)),
    )
    def test_image_defined(self, expected, side_effect, ms):
        ms.side_effect = side_effect
        self.assertEqual(expected, self.lxd.image_defined("test-image"))
        ms.assert_called_once_with("GET", "/1.0/images/test-image")

    @annotated_data(
        ("APIError", exceptions.APIError("500", 500), exceptions.APIError),
        ("PyLXDException", exceptions.PyLXDException,
         exceptions.PyLXDException),
    )
    def test_image_defined_fail(self, tag, side_effect, expected, ms):
        ms.side_effect = side_effect
        self.assertRaises(expected, self.lxd.image_defined, ("test-image", ))
        ms.assert_called_once_with("GET", "/1.0/images/test-image")

    def test_image_info(self, ms):
        self.assertEqual(
            {
                "image_upload_date": (datetime.datetime.fromtimestamp(
                    1435669853).strftime("%Y-%m-%d %H:%M:%S")),
                "image_created_date":
                "Unknown",
                "image_expires_date":
                "Unknown",
                "image_public":
                False,
                "image_size":
                "63MB",
                "image_fingerprint":
                "04aac4257341478b49c25d22cea8a6ce"
                "0489dc6c42d835367945e7596368a37f",
                "image_architecture":
                "x86_64",
            },
            self.lxd.image_info("test-image"),
        )
        ms.assert_called_once_with("GET", "/1.0/images/test-image")

    def test_image_info_fail(self, ms):
        ms.side_effect = exceptions.PyLXDException
        self.assertRaises(exceptions.PyLXDException, self.lxd.image_info,
                          ("test-image", ))
        ms.assert_called_once_with("GET", "/1.0/images/test-image")

    dates_data = (
        (
            "upload",
            (datetime.datetime.fromtimestamp(1435669853).strftime(
                "%Y-%m-%d %H:%M:%S")),
        ),
        ("create", "Unknown"),
        ("expire", "Unknown"),
    )

    @annotated_data(*dates_data)
    def test_image_date(self, method, expected, ms):
        self.assertEqual(
            expected,
            getattr(self.lxd, "image_{}_date".format(method))("test-image",
                                                              data=None),
        )
        ms.assert_called_once_with("GET", "/1.0/images/test-image")

    @annotated_data(*dates_data)
    def test_image_date_fail(self, method, expected, ms):
        ms.side_effect = exceptions.PyLXDException
        self.assertRaises(
            exceptions.PyLXDException,
            getattr(self.lxd, "image_{}_date".format(method)),
            "test-image",
            data=None,
        )
        ms.assert_called_once_with("GET", "/1.0/images/test-image")