[lxc-devel] [nova-lxd/master] Bugfixes
zulcss on Github
lxc-bot at linuxcontainers.org
Thu Apr 7 18:29:31 UTC 2016
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 349 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160407/bc4b23a6/attachment.bin>
-------------- next part --------------
From 175d667aff80a6e66d64272f8efb2f0458fdea7f Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Tue, 5 Apr 2016 20:15:31 -0400
Subject: [PATCH 01/14] fix configdrive
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
nova_lxd/nova/virt/lxd/config.py | 2 +-
test-requirements.txt | 2 --
2 files changed, 1 insertion(+), 3 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/test-requirements.txt b/test-requirements.txt
index 78996ac..c411121 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -16,5 +16,3 @@ testscenarios>=0.4 # Apache-2.0/BSD
testtools>=1.4.0 # MIT
os-testr>=0.4.1 # Apache-2.0
nosexcover # BSD
--e git+https://github.com/lxc/pylxd#egg=pylxd
--e git+https://github.com/openstack/nova#egg=nova
From d74717ff0321b4d8ad65ca39287e76eb300dd6d5 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Tue, 5 Apr 2016 21:08:52 -0400
Subject: [PATCH 02/14] Use real data from the LXD API
In the past we have sent bogus information because
we could not determine the memory usage for a container
now we can.
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
nova_lxd/nova/virt/lxd/operations.py | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/nova_lxd/nova/virt/lxd/operations.py b/nova_lxd/nova/virt/lxd/operations.py
index 7151e6b..9241155 100644
--- a/nova_lxd/nova/virt/lxd/operations.py
+++ b/nova_lxd/nova/virt/lxd/operations.py
@@ -568,11 +568,15 @@ def get_info(self, instance):
"""
LOG.debug('get_info called for instance', instance=instance)
try:
+ container_info = self.session.container_info(instance)
+ mem = int(container_info['memory']['usage']) >> 10
+ max_mem = int(container_info['memory']['usage_peak']) >> 10
+
container_state = self.session.container_state(instance)
return hardware.InstanceInfo(state=container_state,
- max_mem_kb=0,
- mem_kb=0,
- num_cpu=2,
+ max_mem_kb=max_mem,
+ mem_kb=mem,
+ num_cpu=instance.flavor.vcpus,
cpu_time_ns=0)
except Exception as ex:
with excutils.save_and_reraise_exception():
From a4cd790fc6bc22aa58a8dbb18ea62d52c94902b3 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Tue, 5 Apr 2016 21:11:31 -0400
Subject: [PATCH 03/14] Remove cgroup permissions for console
Remove cgroup permissions for console log, no longer needed.
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..2c64639 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 1b8fda705e84b20746f3a745bf13ecbde0ab0f6a Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Tue, 5 Apr 2016 21:38:14 -0400
Subject: [PATCH 04/14] Unplug vif if exception
Unplug vif if there is an exception
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
nova_lxd/nova/virt/lxd/host.py | 3 ++-
nova_lxd/nova/virt/lxd/operations.py | 1 +
2 files changed, 3 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):
diff --git a/nova_lxd/nova/virt/lxd/operations.py b/nova_lxd/nova/virt/lxd/operations.py
index 9241155..60b8b04 100644
--- a/nova_lxd/nova/virt/lxd/operations.py
+++ b/nova_lxd/nova/virt/lxd/operations.py
@@ -173,6 +173,7 @@ def _setup_network(self, instance_name, instance, network_info):
self.plug_vifs(instance, network_info)
except Exception as ex:
with excutils.save_and_reraise_exception():
+ self.unplug_vif(instance, network_info)
LOG.error(_LE('Failed to create container network for '
'%(instance)s: %(ex)s'),
{'instance': instance_name, 'ex': ex},
From 59ee1bf208455409b2682aa414c21c8caad3f796 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Wed, 6 Apr 2016 09:07:59 -0400
Subject: [PATCH 05/14] Make LOG.* messages more consistent
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
nova_lxd/nova/virt/lxd/session.py | 63 +++++++++++++++++++++++++--------------
1 file changed, 41 insertions(+), 22 deletions(-)
diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index 9052ac0..c3e5989 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
@@ -333,7 +333,8 @@ def container_stop(self, instance_name, instance):
LOG.info(_LI('Stopping instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
- 'image': instance.image_ref})
+ 'image': instance.image_ref},
+ instance=instance)
# Stop the container
client = self.get_session()
(state, data) = client.container_stop(instance_name,
@@ -342,7 +343,8 @@ def container_stop(self, instance_name, instance):
LOG.info(_LI('Successfully stopped instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
- 'image': instance.image_ref})
+ 'image': instance.image_ref},
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
@@ -353,7 +355,8 @@ def container_stop(self, instance_name, instance):
LOG.error(
_LE('Failed to stop container %(instance)s: '
'%(reason)s'), {'instance': instance_name,
- 'reason': ex})
+ 'reason': ex},
+ instance=instance)
def container_reboot(self, instance):
"""Reboot a LXD container
@@ -369,7 +372,8 @@ def container_reboot(self, instance):
LOG.info(_LI('Rebooting instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
- 'image': instance.image_ref})
+ 'image': instance.image_ref},
+ instance=instance)
# Container reboot
client = self.get_session()
@@ -379,7 +383,8 @@ def container_reboot(self, instance):
LOG.info(_LI('Successfully rebooted instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
- 'image': instance.image_ref})
+ 'image': instance.image_ref},
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
@@ -417,7 +422,8 @@ def container_destroy(self, instance_name, instance):
LOG.info(_LI('Successfully destroyed instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
- 'image': instance.image_ref})
+ 'image': instance.image_ref},
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
@@ -427,7 +433,8 @@ def container_destroy(self, instance_name, instance):
with excutils.save_and_reraise_exception():
LOG.error(_LE('Failed to destroy container %(instance)s: '
'%(reason)s'), {'instance': instance_name,
- 'reason': ex})
+ 'reason': ex},
+ instance=instance)
def container_pause(self, instance_name, instance):
"""Pause a LXD container
@@ -444,7 +451,8 @@ def container_pause(self, instance_name, instance):
LOG.info(_LI('Pausing instance %(instance)s with'
' %(image)s'), {'instance': instance_name,
- 'image': instance.image_ref})
+ 'image': instance.image_ref},
+ instance=instance)
client = self.get_session()
(state, data) = client.container_suspend(instance_name,
@@ -453,7 +461,8 @@ def container_pause(self, instance_name, instance):
LOG.info(_LI('Successfully paused instance %(instance)s with'
' %(image)s'), {'instance': instance_name,
- 'image': instance.image_ref})
+ 'image': instance.image_ref},
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance_name,
@@ -482,7 +491,8 @@ def container_unpause(self, instance_name, instance):
LOG.info(_LI('Unpausing instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
- 'image': instance.image_ref})
+ 'image': instance.image_ref},
+ instance=instance)
client = self.get_session()
(state, data) = client.container_resume(instance_name,
@@ -491,7 +501,8 @@ def container_unpause(self, instance_name, instance):
LOG.info(_LI('Successfully unpaused instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
- 'image': instance.image_ref})
+ 'image': instance.image_ref},
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
@@ -502,7 +513,8 @@ def container_unpause(self, instance_name, instance):
LOG.error(
_LE('Failed to unpause container %(instance)s: '
'%(reason)s'), {'instance': instance_name,
- 'reason': ex})
+ 'reason': ex},
+ instance=instance)
def container_init(self, config, instance):
"""Create a LXD container
@@ -515,7 +527,8 @@ def container_init(self, config, instance):
try:
LOG.info(_LI('Creating container %(instance)s with'
' %(image)s'), {'instance': instance.name,
- 'image': instance.image_ref})
+ 'image': instance.image_ref},
+ instance=instance)
client = self.get_session()
(state, data) = client.container_init(config)
@@ -528,7 +541,8 @@ def container_init(self, config, instance):
LOG.info(_LI('Successfully created container %(instance)s with'
' %(image)s'), {'instance': instance.name,
- 'image': instance.image_ref})
+ 'image': instance.image_ref},
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
@@ -718,7 +732,8 @@ def profile_defined(self, instance_name, instance):
LOG.error(
_LE('Failed to determine profile %(instance)s:'
' %(reason)s'),
- {'instance': instance.name, 'reason': ex})
+ {'instance': instance.name, 'reason': ex},
+ instance=instance)
def profile_create(self, config, instance):
"""Create an LXD container profile
@@ -745,7 +760,8 @@ def profile_create(self, config, instance):
with excutils.save_and_reraise_exception():
LOG.error(
_LE('Failed to create profile %(instance)s: %(reason)s'),
- {'instance': instance.name, 'reason': ex})
+ {'instance': instance.name, 'reason': ex},
+ instance=instance)
def profile_update(self, config, instance):
"""Update an LXD container profile
@@ -772,7 +788,8 @@ def profile_update(self, config, instance):
LOG.error(
_LE('Failed to update profile %(instance)s: '
'%(reason)s'),
- {'instance': instance.name, 'reason': ex})
+ {'instance': instance.name, 'reason': ex},
+ instance=instance)
def profile_delete(self, instance):
"""Delete a LXD container profile.
@@ -795,7 +812,8 @@ def profile_delete(self, instance):
with excutils.save_and_reraise_exception():
LOG.error(
_LE('Failed to delete profile %(instance)s: %(reason)s'),
- {'instance': instance.name, 'reason': ex})
+ {'instance': instance.name, 'reason': ex},
+ instance=instance)
#
# Host Methods
@@ -817,10 +835,11 @@ def get_host_config(self, instance):
client = self.get_session()
return client.host_config()['environment']
except lxd_exceptions.APIError as ex:
- msg = _('Failed to communicate with LXD %(instance)s:'
- ' %(reason)s') % {'instance': instance.name,
- 'ex': ex}
- LOG.error(msg)
+ with excutils.save_and_reraise_exception():
+ msg = _('Failed to communicate with LXD %(instance)s:'
+ ' %(reason)s') % {'instance': instance.name,
+ 'ex': ex}
+ LOG.error(msg)
#
# Migrate methods
From 855f90db64b18c98da80bc7576271c71417f05f1 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Wed, 6 Apr 2016 09:09:07 -0400
Subject: [PATCH 06/14] Fix typos
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
nova_lxd/nova/virt/lxd/migrate.py | 2 +-
nova_lxd/nova/virt/lxd/operations.py | 2 +-
nova_lxd/nova/virt/lxd/session.py | 2 +-
3 files changed, 3 insertions(+), 3 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/operations.py b/nova_lxd/nova/virt/lxd/operations.py
index 60b8b04..67e044a 100644
--- a/nova_lxd/nova/virt/lxd/operations.py
+++ b/nova_lxd/nova/virt/lxd/operations.py
@@ -173,7 +173,7 @@ def _setup_network(self, instance_name, instance, network_info):
self.plug_vifs(instance, network_info)
except Exception as ex:
with excutils.save_and_reraise_exception():
- self.unplug_vif(instance, network_info)
+ self.unplug_vifs(instance, network_info)
LOG.error(_LE('Failed to create container network for '
'%(instance)s: %(ex)s'),
{'instance': instance_name, 'ex': ex},
diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index c3e5989..792bd7e 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
@@ -746,7 +746,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 06cf4f1ca26358090a52ab67c994be3b09f5c1d6 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Wed, 6 Apr 2016 09:14:06 -0400
Subject: [PATCH 07/14] Remove profile if exception
Remove the profile if an exception is raised.
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
nova_lxd/nova/virt/lxd/operations.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/nova_lxd/nova/virt/lxd/operations.py b/nova_lxd/nova/virt/lxd/operations.py
index 67e044a..eb7e54d 100644
--- a/nova_lxd/nova/virt/lxd/operations.py
+++ b/nova_lxd/nova/virt/lxd/operations.py
@@ -194,6 +194,7 @@ def _setup_profile(self, instance_name, instance, network_info):
network_info)
self.session.profile_create(container_profile, instance)
except Exception as ex:
+ self.session.profile_delete(instance)
with excutils.save_and_reraise_exception():
LOG.error(_LE('Failed to create a profile for'
' %(instance)s: %(ex)s'),
From 6261b8194197c9fc911c0201b7977359b7af19f8 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Wed, 6 Apr 2016 09:17:51 -0400
Subject: [PATCH 08/14] Remove image if there is an exception
Delete the image from the local image store if there
is an exception.
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
nova_lxd/nova/virt/lxd/image.py | 1 +
nova_lxd/nova/virt/lxd/session.py | 22 ++++++++++++++++++++++
2 files changed, 23 insertions(+)
diff --git a/nova_lxd/nova/virt/lxd/image.py b/nova_lxd/nova/virt/lxd/image.py
index 2f29fcd..e3f4603 100644
--- a/nova_lxd/nova/virt/lxd/image.py
+++ b/nova_lxd/nova/virt/lxd/image.py
@@ -102,6 +102,7 @@ def setup_image(self, context, instance, image_meta):
self._cleanup_image(instance)
except Exception as ex:
+ self.client.image_delete(instance)
with excutils.save_and_reraise_exception():
LOG.error(_LE('Failed to upload %(image)s to LXD: '
'%(reason)s'),
diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index 792bd7e..ddeb48e 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
@@ -641,6 +641,28 @@ def image_upload(self, data, headers, instance):
{'instance': instance.image_ref, 'reason': e},
instance=instance)
+ def image_delete(self, instance):
+ """Delete the image from the image store
+
+ :param instance: instance object
+ """
+ LOG.debug('image_delete called for instnace', instance=instance)
+ try:
+ client = self.get_session()
+ return client.image-delete(instance.image_ref)
+ except lxd_exceptions.APIError as ex:
+ msg = _('Failed to communicate with LXD API %(instance)s:'
+ ' %(reason)s') % {'instance': instance.image_ref,
+ 'reason': ex}
+ LOG.error(msg)
+ raise exception.NovaException(msg)
+ except Exception as e:
+ with excutils.save_and_reraise_exception():
+ LOG.error(_LE('Error from LXD during create alias'
+ '%(instance)s: %(reason)s'),
+ {'instance': instance.image_ref, 'reason': e},
+ instance=instance)
+
#
# Operation methods
#
From 8e34a00d0ae951ff399f5a76a89352774514e39e Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Wed, 6 Apr 2016 09:34:01 -0400
Subject: [PATCH 09/14] Ensure configdrive
Make sure that the config drive has been created on the
new host if it is required.
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 cc4576b350643ea33c525b14e66250b1945bab44 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Thu, 7 Apr 2016 10:23:37 -0400
Subject: [PATCH 10/14] Re-add test dependencies
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
test-requirements.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/test-requirements.txt b/test-requirements.txt
index c411121..78996ac 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -16,3 +16,5 @@ testscenarios>=0.4 # Apache-2.0/BSD
testtools>=1.4.0 # MIT
os-testr>=0.4.1 # Apache-2.0
nosexcover # BSD
+-e git+https://github.com/lxc/pylxd#egg=pylxd
+-e git+https://github.com/openstack/nova#egg=nova
From 1d4d353828a8d1ee809fb913aa82a68c730a90d7 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Thu, 7 Apr 2016 13:46:26 -0400
Subject: [PATCH 11/14] Add leading slash.
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
nova_lxd/nova/virt/lxd/config.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nova_lxd/nova/virt/lxd/config.py b/nova_lxd/nova/virt/lxd/config.py
index 2c64639..475688a 100644
--- a/nova_lxd/nova/virt/lxd/config.py
+++ b/nova_lxd/nova/virt/lxd/config.py
@@ -72,7 +72,7 @@ def create_container(self, instance):
self.container_dir.get_container_configdrive(
instance.name)
config = self.configure_disk_path(configdrive_dir,
- 'var/lib/cloud/data',
+ '/var/lib/cloud/data',
'configdrive', instance)
container_config['devices'].update(config)
From e5309228eb406b2564a1aadff86c20b27fc17772 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Thu, 7 Apr 2016 13:47:22 -0400
Subject: [PATCH 12/14] Consoidate container state
Consolidate container state and memroy into one place.
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
nova_lxd/nova/virt/lxd/operations.py | 5 +++++
nova_lxd/nova/virt/lxd/session.py | 11 +++++++++--
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/nova_lxd/nova/virt/lxd/operations.py b/nova_lxd/nova/virt/lxd/operations.py
index eb7e54d..a0f762c 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
@@ -570,6 +571,10 @@ def get_info(self, instance):
"""
LOG.debug('get_info called for instance', instance=instance)
try:
+ if self.session.container_defined(instance.name, instance):
+ return hardware.InstanceInfo(
+ state=power_state.NOSTATE)
+
container_info = self.session.container_info(instance)
mem = int(container_info['memory']['usage']) >> 10
max_mem = int(container_info['memory']['usage_peak']) >> 10
diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index ddeb48e..d3404e3 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
@@ -178,12 +178,18 @@ 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']]
+
+ mem = int(self.container_info['memory']['usage']) >> 10
+ max_mem = int(container_info['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 +203,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
@@ -278,6 +284,7 @@ def container_defined(self, instance_name, instance):
{'instance': instance.name, 'reason': e},
instance=instance)
+
def container_start(self, instance_name, instance):
"""Start an LXD container
From e1879f461df9e6cee08333f36f626a457be135c5 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Thu, 7 Apr 2016 14:08:30 -0400
Subject: [PATCH 13/14] Fix unit tests
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
nova_lxd/tests/session/test_container.py | 18 +++++-------------
nova_lxd/tests/test_config.py | 2 +-
nova_lxd/tests/test_driver_api.py | 11 ++++++-----
3 files changed, 12 insertions(+), 19 deletions(-)
diff --git a/nova_lxd/tests/session/test_container.py b/nova_lxd/tests/session/test_container.py
index e9a3c43..de1aadc 100644
--- a/nova_lxd/tests/session/test_container.py
+++ b/nova_lxd/tests/session/test_container.py
@@ -142,13 +142,7 @@ 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
@@ -156,14 +150,12 @@ def test_container_state(self, tag, side_effect, expected):
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)
+ ('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):
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()
diff --git a/nova_lxd/tests/test_driver_api.py b/nova_lxd/tests/test_driver_api.py
index f769924..bcf037f 100644
--- a/nova_lxd/tests/test_driver_api.py
+++ b/nova_lxd/tests/test_driver_api.py
@@ -102,11 +102,12 @@ 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', 102, power_state.SHUTDOWN),
+ #('crashed', 108, power_state.CRASHED),
+ #('suspend', 109, power_state.SUSPENDED),
+ #('no_state', 401, power_state.NOSTATE),
)
def test_get_info(self, tag, side_effect, expected):
instance = stubs._fake_instance()
From d619f863eef981223c393dfeebd26e8c3a757dab Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short at canonical.com>
Date: Thu, 7 Apr 2016 14:28:10 -0400
Subject: [PATCH 14/14] Fix pep8 errors
Signed-off-by: Chuck Short <chuck.short at canonical.com>
---
nova_lxd/nova/virt/lxd/config.py | 2 +-
nova_lxd/nova/virt/lxd/operations.py | 3 +--
nova_lxd/nova/virt/lxd/session.py | 35 ++++++++++++++++----------------
nova_lxd/tests/session/test_container.py | 7 +++----
nova_lxd/tests/test_driver_api.py | 14 ++++++++-----
5 files changed, 31 insertions(+), 30 deletions(-)
diff --git a/nova_lxd/nova/virt/lxd/config.py b/nova_lxd/nova/virt/lxd/config.py
index 475688a..6006a11 100644
--- a/nova_lxd/nova/virt/lxd/config.py
+++ b/nova_lxd/nova/virt/lxd/config.py
@@ -143,7 +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.logfile=%s\n' \
+ config['raw.lxc'] = 'lxc.console.logfile=%s\n' \
% self.container_dir.get_console_path(instance_name)
return config
diff --git a/nova_lxd/nova/virt/lxd/operations.py b/nova_lxd/nova/virt/lxd/operations.py
index a0f762c..4b4f860 100644
--- a/nova_lxd/nova/virt/lxd/operations.py
+++ b/nova_lxd/nova/virt/lxd/operations.py
@@ -572,8 +572,7 @@ def get_info(self, instance):
LOG.debug('get_info called for instance', instance=instance)
try:
if self.session.container_defined(instance.name, instance):
- return hardware.InstanceInfo(
- state=power_state.NOSTATE)
+ return hardware.InstanceInfo(state=power_state.NOSTATE)
container_info = self.session.container_info(instance)
mem = int(container_info['memory']['usage']) >> 10
diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index d3404e3..4e78b86 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
@@ -188,7 +188,7 @@ def container_state(self, instance):
state = constants.LXD_POWER_STATES[data['metadata']['status_code']]
mem = int(self.container_info['memory']['usage']) >> 10
- max_mem = int(container_info['memory']['usage_peak']) >> 10
+ max_mem = int(self.container_info['memory']['usage_peak']) >> 10
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
@@ -284,7 +284,6 @@ def container_defined(self, instance_name, instance):
{'instance': instance.name, 'reason': e},
instance=instance)
-
def container_start(self, instance_name, instance):
"""Start an LXD container
@@ -341,7 +340,7 @@ def container_stop(self, instance_name, instance):
LOG.info(_LI('Stopping instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref},
- instance=instance)
+ instance=instance)
# Stop the container
client = self.get_session()
(state, data) = client.container_stop(instance_name,
@@ -351,7 +350,7 @@ def container_stop(self, instance_name, instance):
LOG.info(_LI('Successfully stopped instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref},
- instance=instance)
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
@@ -363,7 +362,7 @@ def container_stop(self, instance_name, instance):
_LE('Failed to stop container %(instance)s: '
'%(reason)s'), {'instance': instance_name,
'reason': ex},
- instance=instance)
+ instance=instance)
def container_reboot(self, instance):
"""Reboot a LXD container
@@ -380,7 +379,7 @@ def container_reboot(self, instance):
LOG.info(_LI('Rebooting instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref},
- instance=instance)
+ instance=instance)
# Container reboot
client = self.get_session()
@@ -391,7 +390,7 @@ def container_reboot(self, instance):
LOG.info(_LI('Successfully rebooted instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref},
- instance=instance)
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
@@ -430,7 +429,7 @@ def container_destroy(self, instance_name, instance):
LOG.info(_LI('Successfully destroyed instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref},
- instance=instance)
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
@@ -441,7 +440,7 @@ def container_destroy(self, instance_name, instance):
LOG.error(_LE('Failed to destroy container %(instance)s: '
'%(reason)s'), {'instance': instance_name,
'reason': ex},
- instance=instance)
+ instance=instance)
def container_pause(self, instance_name, instance):
"""Pause a LXD container
@@ -459,7 +458,7 @@ def container_pause(self, instance_name, instance):
LOG.info(_LI('Pausing instance %(instance)s with'
' %(image)s'), {'instance': instance_name,
'image': instance.image_ref},
- instance=instance)
+ instance=instance)
client = self.get_session()
(state, data) = client.container_suspend(instance_name,
@@ -469,7 +468,7 @@ def container_pause(self, instance_name, instance):
LOG.info(_LI('Successfully paused instance %(instance)s with'
' %(image)s'), {'instance': instance_name,
'image': instance.image_ref},
- instance=instance)
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance_name,
@@ -499,7 +498,7 @@ def container_unpause(self, instance_name, instance):
LOG.info(_LI('Unpausing instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref},
- instance=instance)
+ instance=instance)
client = self.get_session()
(state, data) = client.container_resume(instance_name,
@@ -509,7 +508,7 @@ def container_unpause(self, instance_name, instance):
LOG.info(_LI('Successfully unpaused instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref},
- instance=instance)
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
@@ -521,7 +520,7 @@ def container_unpause(self, instance_name, instance):
_LE('Failed to unpause container %(instance)s: '
'%(reason)s'), {'instance': instance_name,
'reason': ex},
- instance=instance)
+ instance=instance)
def container_init(self, config, instance):
"""Create a LXD container
@@ -535,7 +534,7 @@ def container_init(self, config, instance):
LOG.info(_LI('Creating container %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref},
- instance=instance)
+ instance=instance)
client = self.get_session()
(state, data) = client.container_init(config)
@@ -549,7 +548,7 @@ def container_init(self, config, instance):
LOG.info(_LI('Successfully created container %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref},
- instance=instance)
+ instance=instance)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
@@ -656,7 +655,7 @@ def image_delete(self, instance):
LOG.debug('image_delete called for instnace', instance=instance)
try:
client = self.get_session()
- return client.image-delete(instance.image_ref)
+ return client.image_delete(instance.image_ref)
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.image_ref,
@@ -790,7 +789,7 @@ def profile_create(self, config, instance):
LOG.error(
_LE('Failed to create profile %(instance)s: %(reason)s'),
{'instance': instance.name, 'reason': ex},
- instance=instance)
+ instance=instance)
def profile_update(self, config, instance):
"""Update an LXD container profile
diff --git a/nova_lxd/tests/session/test_container.py b/nova_lxd/tests/session/test_container.py
index de1aadc..69690f7 100644
--- a/nova_lxd/tests/session/test_container.py
+++ b/nova_lxd/tests/session/test_container.py
@@ -149,13 +149,12 @@ def test_container_state(self):
a power_state.RUNNING and a 108 sends a
power_state.CRASHED.
"""
- instance = stubs._fake_instance()
- calls =[]
+ 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})
+ ('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):
diff --git a/nova_lxd/tests/test_driver_api.py b/nova_lxd/tests/test_driver_api.py
index bcf037f..4159e8c 100644
--- a/nova_lxd/tests/test_driver_api.py
+++ b/nova_lxd/tests/test_driver_api.py
@@ -103,11 +103,15 @@ def test_init_host_fail(self, tag, config):
@stubs.annotated_data(
('running', {'state': 200, 'mem': 0, 'max_mem': 0},
- power_state.RUNNING),
- #('shutdown', 102, power_state.SHUTDOWN),
- #('crashed', 108, power_state.CRASHED),
- #('suspend', 109, power_state.SUSPENDED),
- #('no_state', 401, power_state.NOSTATE),
+ 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