[lxc-devel] [nova-lxd/master] Bugfixes and resource updates

zulcss on Github lxc-bot at linuxcontainers.org
Fri Apr 8 17:24:39 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1245 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160408/a4161ce2/attachment.bin>
-------------- next part --------------
From ae67b81047e8d1faec858eba29112d3fbfeb943d Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Fri, 8 Apr 2016 10:28:58 -0400
Subject: [PATCH 1/6] Fix launching instance with configdrive

When launching an instance with configdrive, LXD expects a
string rather than an boolean value. Otherwise the instance
wont boot.

This needs better unit tests in the future.

Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
 nova_lxd/nova/virt/lxd/config.py | 2 +-
 nova_lxd/tests/test_config.py    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/nova_lxd/nova/virt/lxd/config.py b/nova_lxd/nova/virt/lxd/config.py
index ca214ac..68f9214 100644
--- a/nova_lxd/nova/virt/lxd/config.py
+++ b/nova_lxd/nova/virt/lxd/config.py
@@ -303,7 +303,7 @@ def configure_disk_path(self, src_path, dest_path, vfs_type, instance):
             config[vfs_type] = {'path': dest_path,
                                 'source': src_path,
                                 'type': 'disk',
-                                'optional': True}
+                                'optional': 'True'}
             return config
         except Exception as ex:
             with excutils.save_and_reraise_exception():
diff --git a/nova_lxd/tests/test_config.py b/nova_lxd/tests/test_config.py
index 08f524c..478fb37 100644
--- a/nova_lxd/tests/test_config.py
+++ b/nova_lxd/tests/test_config.py
@@ -79,7 +79,7 @@ def test_create_disk_path(self):
         self.assertEqual({'fake_disk': {'path': '/fake/dest_path',
                                         'source': '/fake/src_path',
                                         'type': 'disk',
-                                        'optional': True}}, config)
+                                        'optional': 'True'}}, config)
 
     def test_config_instance_options(self):
         instance = stubs._fake_instance()

From 4573a2fb13b457cbc4c2c6114492c701a0196ca2 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Fri, 8 Apr 2016 10:48:21 -0400
Subject: [PATCH 2/6] Remove old LXD console configuration

Previous versions of LXD required the console
cgroup permissions to be configured so that we can
use nova console-log. This is no longer the case
so remove the old configuration parameters.

Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
 nova_lxd/nova/virt/lxd/config.py | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/nova_lxd/nova/virt/lxd/config.py b/nova_lxd/nova/virt/lxd/config.py
index 68f9214..8470754 100644
--- a/nova_lxd/nova/virt/lxd/config.py
+++ b/nova_lxd/nova/virt/lxd/config.py
@@ -143,9 +143,7 @@ def create_config(self, instance_name, instance):
                 config['limits.cpu'] = str(vcpus)
 
             # Configure the console for the instance
-            config['raw.lxc'] = 'lxc.console=\n' \
-                                'lxc.cgroup.devices.deny=c 5:1 rwm\n' \
-                                'lxc.console.logfile=%s\n' \
+            config['raw.lxc'] = 'lxc.console.logfile=%s\n' \
                 % self.container_dir.get_console_path(instance_name)
 
             return config

From 24b650eb1df84b08a6d34ec183c42019d5b1b346 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Fri, 8 Apr 2016 11:01:49 -0400
Subject: [PATCH 3/6] Fix spelling typos

s/instnace/instance/g

Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
 nova_lxd/nova/virt/lxd/migrate.py | 2 +-
 nova_lxd/nova/virt/lxd/session.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
index 84db028..86f2eff 100644
--- a/nova_lxd/nova/virt/lxd/migrate.py
+++ b/nova_lxd/nova/virt/lxd/migrate.py
@@ -89,7 +89,7 @@ def confirm_migration(self, migration, instance, network_info):
 
         if not self.session.container_defined(instance.name, instance):
             msg = _('Failed to find container %(instance)s') % \
-                {'instnace': instance.name}
+                {'instance': instance.name}
             raise exception.NovaException(msg)
 
         try:
diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index 9052ac0..2560c06 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
@@ -731,7 +731,7 @@ def profile_create(self, config, instance):
         try:
             if self.profile_defined(instance.name, instance):
                 msg = _('Profile already exists %(instnce)s') % \
-                    {'instnace': instance.name}
+                    {'instance': instance.name}
                 raise exception.NovaException(msg)
 
             client = self.get_session()

From 3eaf1076fdabdcc1a338b00e66719a3b7e2a5c1b Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Fri, 8 Apr 2016 11:06:22 -0400
Subject: [PATCH 4/6] Fix migration with configdrive

Migration fails with configdrive if there is a configdrive attached
to the instance.

After the container is created on the new host via init API call
the LXD daemon expects the directory that is originated to be on
the host to be present on the new host. Otherwise the container
will not start.

This is not tested by tempest and it should probably be included.

Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
 nova_lxd/nova/virt/lxd/migrate.py | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
index 86f2eff..d780ce7 100644
--- a/nova_lxd/nova/virt/lxd/migrate.py
+++ b/nova_lxd/nova/virt/lxd/migrate.py
@@ -18,6 +18,7 @@
 from nova import exception
 from nova import i18n
 from nova import utils
+from nova.virt import configdrive
 
 from oslo_config import cfg
 from oslo_log import log as logging
@@ -118,6 +119,12 @@ def finish_migration(self, context, migration, instance, disk_info,
             if not os.path.exists(instance_dir):
                 fileutils.ensure_tree(instance_dir)
 
+            if configdrive.required_by(instance):
+                configdrive_dir = \
+                    self.container_dir.get_container_configdrive(
+                        instance.name)
+                fileutils.ensure_tree(configdrive_dir)
+
             # Step 1 - Setup the profile on the dest host
             container_profile = self.config.create_profile(instance,
                                                            network_info)

From 09a3f2a05391ec2d70eff6b8698ed58298e39e36 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Fri, 8 Apr 2016 11:13:41 -0400
Subject: [PATCH 5/6] Fix issue #20

Fix traceback in get_host_cpu_stats.

Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
 nova_lxd/nova/virt/lxd/host.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/nova_lxd/nova/virt/lxd/host.py b/nova_lxd/nova/virt/lxd/host.py
index 5106966..587539c 100644
--- a/nova_lxd/nova/virt/lxd/host.py
+++ b/nova_lxd/nova/virt/lxd/host.py
@@ -180,12 +180,13 @@ def _get_hypersivor_version(self):
         return '.'.join(str(v) for v in version)
 
     def get_host_cpu_stats(self):
+        cpuinfo = self._get_cpu_info()
         return {
             'kernel': int(psutil.cpu_times()[2]),
             'idle': int(psutil.cpu_times()[3]),
             'user': int(psutil.cpu_times()[0]),
             'iowait': int(psutil.cpu_times()[4]),
-            'frequency': self.host_cpu_info['hz_advertised']
+            'frequency': cpuinfo.get('cpu mhz', 0)
         }
 
     def init_host(self, host):

From d6b447504e279c4ec98aa1c989ff5b32a419e2f9 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Fri, 8 Apr 2016 11:44:06 -0400
Subject: [PATCH 6/6] Query the LXD API for memory usage

In the past, we dont supply resource usage because the LXD
API did not provide them. Now that this is possible, provide
real data to the user when its required.

Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
 nova_lxd/nova/virt/lxd/operations.py     | 12 ++++++++----
 nova_lxd/nova/virt/lxd/session.py        | 12 ++++++++++--
 nova_lxd/tests/session/test_container.py | 17 ++++-------------
 nova_lxd/tests/test_driver_api.py        | 15 ++++++++++-----
 4 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/nova_lxd/nova/virt/lxd/operations.py b/nova_lxd/nova/virt/lxd/operations.py
index 7151e6b..9b3f144 100644
--- a/nova_lxd/nova/virt/lxd/operations.py
+++ b/nova_lxd/nova/virt/lxd/operations.py
@@ -31,6 +31,7 @@
 from nova import exception
 from nova import i18n
 from nova import utils
+from nova.compute import power_state
 
 from nova_lxd.nova.virt.lxd import config as container_config
 from nova_lxd.nova.virt.lxd import container_firewall
@@ -568,11 +569,14 @@ def get_info(self, instance):
         """
         LOG.debug('get_info called for instance', instance=instance)
         try:
+            if not self.session.container_defined(instance.name, instance):
+                return hardware.InstanceInfo(state=power_state.NOSTATE)
+
             container_state = self.session.container_state(instance)
-            return hardware.InstanceInfo(state=container_state,
-                                         max_mem_kb=0,
-                                         mem_kb=0,
-                                         num_cpu=2,
+            return hardware.InstanceInfo(state=container_state['state'],
+                                         max_mem_kb=container_state['max_mem'],
+                                         mem_kb=container_state['mem'],
+                                         num_cpu=instance.flavor.vcpus,
                                          cpu_time_ns=0)
         except Exception as ex:
             with excutils.save_and_reraise_exception():
diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index 2560c06..46738c9 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
@@ -178,12 +178,20 @@ def container_state(self, instance):
         """
         LOG.debug('container_state called for instance', instance=instance)
         try:
+            mem = 0
+            max_mem = 0
+
             client = self.get_session()
             if not self.container_defined(instance.name, instance):
-                return power_state.NOSTATE
+                return
 
             (state, data) = client.container_state(instance.name)
             state = constants.LXD_POWER_STATES[data['metadata']['status_code']]
+
+            container_state = self.container_info(instance)
+            mem = int(container_state['memory']['usage']) >> 10
+            max_mem = int(container_state['memory']['usage_peak']) >> 10
+
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.name,
@@ -197,7 +205,7 @@ def container_state(self, instance):
                           {'instance': instance.name, 'reason': e},
                           instance=instance)
                 state = power_state.NOSTATE
-        return state
+        return {'state': state, 'mem': mem, 'max_mem': max_mem}
 
     def container_config(self, instance):
         """Fetches the configuration of a given LXD container
diff --git a/nova_lxd/tests/session/test_container.py b/nova_lxd/tests/session/test_container.py
index e9a3c43..69690f7 100644
--- a/nova_lxd/tests/session/test_container.py
+++ b/nova_lxd/tests/session/test_container.py
@@ -142,28 +142,19 @@ def test_container_running(self, tag, side_effect):
                 self.session.container_running, instance
             )
 
-    @stubs.annotated_data(
-        ('running', (200, fake_api.fake_container_state(200)),
-         power_state.RUNNING),
-        ('crashed', (200, fake_api.fake_container_state(108)),
-         power_state.CRASHED),
-    )
-    def test_container_state(self, tag, side_effect, expected):
+    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.
         """
-        instance = stubs._fake_instance()
-        self.ml.container_state.return_value = side_effect
-        self.assertEqual(expected,
-                         self.session.container_state(instance))
+        calls = []
+        self.assertEqual(calls, self.ml.method_calls)
 
     @stubs.annotated_data(
         ('api_fail', True, lxd_exceptions.APIError('Fake', 500),
-         power_state.NOSTATE),
-        ('missing', False, None, power_state.NOSTATE)
+         {'state': power_state.NOSTATE, 'mem': 0, 'max_mem': 0})
     )
     def test_container_state_fail(self, tag, container_defined, side_effect,
                                   expected):
diff --git a/nova_lxd/tests/test_driver_api.py b/nova_lxd/tests/test_driver_api.py
index f769924..4159e8c 100644
--- a/nova_lxd/tests/test_driver_api.py
+++ b/nova_lxd/tests/test_driver_api.py
@@ -102,11 +102,16 @@ def test_init_host_fail(self, tag, config):
         )
 
     @stubs.annotated_data(
-        ('running', 200, power_state.RUNNING),
-        ('shutdown', 102, power_state.SHUTDOWN),
-        ('crashed', 108, power_state.CRASHED),
-        ('suspend', 109, power_state.SUSPENDED),
-        ('no_state', 401, power_state.NOSTATE),
+        ('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()


More information about the lxc-devel mailing list