frobware on Github | 8 Feb 23:06 2016

[lxd/master] Makefile: allow debug info to be specified

Attachment: text/x-mailbox, 1038 bytes
From 2bedd98d2a094b33866d4a39e05f76f5abbcef49 Mon Sep 17 00:00:00 2001
From: Andrew McDermott <aim <at> frobware.com>
Date: Mon, 8 Feb 2016 21:56:49 +0000
Subject: [PATCH] Makefile: allow debug info to be specified

Add variable `DEBUG' that can be used to specify debug flags for the Go
tool when building either the client or the lxd.

For example:

 $ DEBUG='-gcflags "-N -l"' make

The -N flag enables debug information and -l disables compiler inlining.
Example of how to debug using lldb can be found here:

 http://ribrdb.github.io/lldb/

 http://blog.ralch.com/tutorial/golang-debug-with-lldb/

Signed-off-by: Andrew McDermott <andrew.mcdermott <at> canonical.com>
---
 Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 4e7c957..b534770 100644
--- a/Makefile
+++ b/Makefile
 <at>  <at>  -15,7 +15,7  <at>  <at>  default:
 	# Must run twice due to go get race
 	-go get -t -v -d ./...
 	-go get -t -v -d ./...
-	go install -v ./...
+	go install -v $(DEBUG) ./...
 	 <at> echo "LXD built succesfuly"

 .PHONY: client
 <at>  <at>  -23,7 +23,7  <at>  <at>  client:
 	# Must run twice due to go get race
 	-go get -t -v -d ./...
 	-go get -t -v -d ./...
-	go install -v ./lxc
+	go install -v $(DEBUG) ./lxc
 	 <at> echo "LXD client built succesfuly"

 .PHONY: update
_______________________________________________
lxc-devel mailing list
lxc-devel <at> lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel
Bussery, Francois | 8 Feb 22:24 2016

Mount slave forced in lxc-1.1.4

Hi,
I have noticed that recent LXC are remounting SLAVE all SHARED mount points. 
Is there any real reason for that? Is there any way to workaround this “feature” by any configuration files.
In embedded world, it is really common to delegate the ability to manage mass storage in a separate
container than the one who use it.
So we need to share the mount points.
It is unfortunately not possible to do it without patching on LXC 1.1.4.
May be somebody found trick to workaround that?
or don’t you think it could be interesting to add some exception in the conf file? 

_______________________________________________
lxc-devel mailing list
lxc-devel <at> lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel
GitHub | 8 Feb 22:27 2016

[lxc/lxc] 374625: apparmor: don't fail if current aa label is given

  Branch: refs/heads/master
  Home:   https://github.com/lxc/lxc
  Commit: 374625aa3fe8cfa9c866c6d5e6f28bbb4a7a7540
      https://github.com/lxc/lxc/commit/374625aa3fe8cfa9c866c6d5e6f28bbb4a7a7540
  Author: Serge Hallyn <serge.hallyn@...>
  Date:   2016-02-08 (Mon, 08 Feb 2016)

  Changed paths:
    M src/lxc/lsm/apparmor.c

  Log Message:
  -----------
  apparmor: don't fail if current aa label is given

Ideally a container configuration will specify 'unchanged' if
it wants the container to use the current (parent) profile.  But
lxd passes its current label.  Support that too.

Note that if/when stackable profiles exist, this behavior may
or may not be what we want.  But the code to deal with aa
stacking will need some changes anyway so this is ok.

With this patch, I can create nested containers inside a
lxd xenial container both using

lxc launch x2

and unprivileged

lxc-start -n x2

Signed-off-by: Serge Hallyn <serge.hallyn@...>

  Commit: f97ab3a63913ce8e30696cf3b62f94716be8e346
      https://github.com/lxc/lxc/commit/f97ab3a63913ce8e30696cf3b62f94716be8e346
  Author: Christian Brauner <christian.brauner@...>
  Date:   2016-02-08 (Mon, 08 Feb 2016)

  Changed paths:
    M src/lxc/lsm/apparmor.c

  Log Message:
  -----------
  Merge pull request #808 from hallyn/2016-02-07/aa.2

apparmor: don't fail if current aa label is given

Compare: https://github.com/lxc/lxc/compare/e8f8436cc123...f97ab3a63913
_______________________________________________
lxc-devel mailing list
lxc-devel <at> lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel
hallyn on Github | 8 Feb 19:11 2016

[lxcfs/master] 2016 02 08/privlib

Attachment: text/x-mailbox, 467 bytes
From 2e7cd2944856568dc1d8f2c8a721003516c75e36 Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge.hallyn <at> ubuntu.com>
Date: Mon, 8 Feb 2016 09:23:38 -0800
Subject: [PATCH 1/4] Makefile: make testlib build optional, and drop the
 soname

Signed-off-by: Serge Hallyn <serge.hallyn <at> ubuntu.com>
---
 Makefile.am | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 734fa3b..855c61c 100644
--- a/Makefile.am
+++ b/Makefile.am
 <at>  <at>  -3,10 +3,6  <at>  <at>  ACLOCAL_AMFLAGS = -I m4
 SUBDIRS = tests share
 DIST_SUBDIRS = tests share

-VERSION_CURRENT  = 0
-VERSION_REVISION = 0
-VERSION_AGE      = 0
-
 AM_CFLAGS = -Wall -ggdb -D_GNU_SOURCE -DSBINDIR=\"$(SBINDIR)\" -pthread
 AM_CFLAGS += $(FUSE_CFLAGS)
 AM_LDFLAGS = $(FUSE_LIBS) -pthread
 <at>  <at>  -16,18 +12,17  <at>  <at>  AM_CFLAGS += -DRUNTIME_PATH=\"$(RUNTIME_PATH)\"

 liblxcfs_la_SOURCES = bindings.c cpuset.c bindings.h
 liblxcfs_la_CFLAGS = $(AM_CFLAGS)
-liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -shared \
-	-Wl,-soname,liblxcfs.so.$(firstword $(subst ., , <at> LXCFS_VERSION_ABI <at> ))
+liblxcfs_la_LDFLAGS = $(AM_CFLAGS) -shared

 liblxcfstest_la_SOURCES = bindings.c cpuset.c bindings.h
 liblxcfstest_la_CFLAGS = $(AM_CFLAGS) -DRELOADTEST
-liblxcfstest_la_LDFLAGS = $(AM_CFLAGS) -shared \
-	-Wl,-soname,liblxcfs.so.$(firstword $(subst ., , <at> LXCFS_VERSION_ABI <at> ))
+liblxcfstest_la_LDFLAGS = $(AM_CFLAGS) -shared

 noinst_HEADERS = bindings.h

 sodir=$(libdir)
-lib_LTLIBRARIES = liblxcfs.la liblxcfstest.la
+lib_LTLIBRARIES = liblxcfs.la
+EXTRA_LTLIBRARIES = liblxcfstest.la

 lxcfs_SOURCES = lxcfs.c
 lxcfs_LDADD = liblxcfs.la -ldl

From c59347295b3ab7eedf3f2f5ebf3a205566564ba8 Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge.hallyn <at> ubuntu.com>
Date: Mon, 8 Feb 2016 09:36:18 -0800
Subject: [PATCH 2/4] Look for liblxcfs under LIBDIR/lxcfs

If LXCFS_TESTSUITE environment variable is set, always
use relative path so we can specify the location with LD_LIBRARY_PATH.

If LIBDIR/lxcfs/liblxcfs.so does not exist, fall back to relative
path so that 'make; ./lxcfs' still works.

Signed-off-by: Serge Hallyn <serge.hallyn <at> ubuntu.com>
---
 Makefile.am |  1 +
 lxcfs.c     | 23 +++++++++++++++++------
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 855c61c..017b812 100644
--- a/Makefile.am
+++ b/Makefile.am
 <at>  <at>  -5,6 +5,7  <at>  <at>  DIST_SUBDIRS = tests share

 AM_CFLAGS = -Wall -ggdb -D_GNU_SOURCE -DSBINDIR=\"$(SBINDIR)\" -pthread
 AM_CFLAGS += $(FUSE_CFLAGS)
+AM_CFLAGS += -DLIBDIR=\"$(LIBDIR)\"
 AM_LDFLAGS = $(FUSE_LIBS) -pthread
 #AM_CFLAGS += -DDEBUG

diff --git a/lxcfs.c b/lxcfs.c
index 1d1016c..1332fc7 100644
--- a/lxcfs.c
+++ b/lxcfs.c
 <at>  <at>  -68,6 +68,7  <at>  <at>  static void users_unlock(void)
 }

 static int need_reload;
+
 /* do_reload - reload the dynamic library.  Done under
  * lock and when we know the user_count was 0 */
 static void do_reload(void)
 <at>  <at>  -75,13 +76,27  <at>  <at>  static void do_reload(void)
 	if (dlopen_handle)
 		dlclose(dlopen_handle);

+	/* Testsuite never wants to use /usr/lib/lxcfs/liblxcfs.so */
+	if (getenv("LXCFS_TESTSUITE") != NULL)
+		goto relpath;
+
+	/* First try to load from /usr/lib/lxcfs/liblxcfs.so */
+	dlopen_handle = dlopen(LIBDIR "lxcfs/liblxcfs.so", RTLD_LAZY);
+	if (dlopen_handle)
+		goto good;
+
+relpath:
+	/* Fall back to looking under LD_LIBRARY_PATH */
 	dlopen_handle = dlopen("liblxcfs.so", RTLD_LAZY);
 	if (!dlopen_handle) {
 		fprintf(stderr, "Failed to open liblxcfs\n");
 		_exit(1);
 	}
+
+good:
+	if (need_reload)
+		fprintf(stderr, "lxcfs: reloaded\n");
 	need_reload = 0;
-	fprintf(stderr, "lxcfs: reloaded\n");
 }

 static void up_users(void)
 <at>  <at>  -904,11 +919,7  <at>  <at>  int main(int argc, char *argv[])
 	if (argc != 2 || is_help(argv[1]))
 		usage(argv[0]);

-	dlopen_handle = dlopen("liblxcfs.so", RTLD_LAZY);
-	if (!dlopen_handle) {
-		fprintf(stderr, "Failed to open liblxcfs\n");
-		exit(1);
-	}
+	do_reload();
 	signal(SIGUSR1, reload_handler);

 	newargv[cnt++] = argv[0];

From ea58dd6c6315567f2de538a7e7fa5c4fc31897c2 Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge.hallyn <at> ubuntu.com>
Date: Mon, 8 Feb 2016 09:39:21 -0800
Subject: [PATCH 3/4] test_reload: actually time out

Signed-off-by: Serge Hallyn <serge.hallyn <at> ubuntu.com>
---
 tests/test_reload.sh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/test_reload.sh b/tests/test_reload.sh
index 4560ba2..fc05ea0 100755
--- a/tests/test_reload.sh
+++ b/tests/test_reload.sh
 <at>  <at>  -46,6 +46,7  <at>  <at>  count=1
 while [ ! -d ${testdir}/proc ]; do
   [ $count -lt 5 ]
   sleep 1
+  count=$((count+1))
 done

 rm -f iwashere

From ebfc237cb1a66753c1b3eb8b201b5a9409ea2ecb Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge.hallyn <at> ubuntu.com>
Date: Mon, 8 Feb 2016 09:59:26 -0800
Subject: [PATCH 4/4] testsuite: handle liblxcfs changes

Export LXCFS_TESTSUITE so that lxcfs will use relative path to load
liblxcfs.  And have test_reload.sh build liblxcfstest by hand since it
is no longer automatically built.

Signed-off-by: Serge Hallyn <serge.hallyn <at> ubuntu.com>
---
 tests/main.sh        |  2 ++
 tests/test_reload.sh | 11 +++++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/tests/main.sh b/tests/main.sh
index 01a900b..54ad055 100755
--- a/tests/main.sh
+++ b/tests/main.sh
 <at>  <at>  -4,6 +4,8  <at>  <at>  set -ex

 [ $(id -u) -eq 0 ]

+export LXCFS_TESTSUITE=1
+
 # Run lxcfs testsuite
 export LXCFSDIR=$(mktemp -d)
 pidfile=$(mktemp)
diff --git a/tests/test_reload.sh b/tests/test_reload.sh
index fc05ea0..ae8217b 100755
--- a/tests/test_reload.sh
+++ b/tests/test_reload.sh
 <at>  <at>  -39,8 +39,10  <at>  <at>  trap cleanup EXIT SIGHUP SIGINT SIGTERM

 ( cd ${topdir}; DESTDIR=${installdir} make install )
 export LD_LIBRARY_PATH=${libdir}
+export LXCFS_TESTSUITE=1

 ${bindir}/lxcfs -p ${pidfile} ${testdir} &
+
 lxcfspid=$!
 count=1
 while [ ! -d ${testdir}/proc ]; do
 <at>  <at>  -52,9 +54,14  <at>  <at>  done
 rm -f iwashere
 cat ${testdir}/proc/uptime
 [ ! -f iwashere ]
+(
+  cd ${topdir};
+  make liblxcfstest.la
+  gcc -shared -fPIC -DPIC .libs/liblxcfstest_la-bindings.o .libs/liblxcfstest_la-cpuset.o
-lpthread -pthread -o .libs/liblxcfstest.so
+  cp .libs/liblxcfstest.* "${libdir}"
+)
 rm -f ${libdir}/liblxcfs.so* ${libdir}/liblxcfs.la
-ln -s liblxcfstest.so.0.0.0 ${libdir}/liblxcfs.so
-cp ${libdir}/liblxcfstest.la ${libdir}/liblxcfs.la
+cp ${libdir}/liblxcfstest.so ${libdir}/liblxcfs.so

 kill -USR1 ${lxcfspid}

_______________________________________________
lxc-devel mailing list
lxc-devel <at> lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel
zulcss on Github | 8 Feb 16:26 2016

[nova-lxd/master] Migration and resize refactor

Attachment: text/x-mailbox, 791 bytes
From b7a1d24422a21c343b8d2b6340bdf255e8fb6fc4 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 08:32:30 -0500
Subject: [PATCH 01/15] Rename container migration

Rename container_migration.py and test_container_migration.py
for simplicity, readability, and maintenance.

Signed-off-by: Chuck Short <chuck.short <at> canonical.com>
---
 nova_lxd/nova/virt/lxd/container_migrate.py | 113 ----------------------------
 nova_lxd/nova/virt/lxd/driver.py            |   4 +-
 nova_lxd/nova/virt/lxd/migrate.py           | 113 ++++++++++++++++++++++++++++
 nova_lxd/tests/test_container_migration.py  |  73 ------------------
 nova_lxd/tests/test_migrate.py              |  73 ++++++++++++++++++
 5 files changed, 188 insertions(+), 188 deletions(-)
 delete mode 100644 nova_lxd/nova/virt/lxd/container_migrate.py
 create mode 100644 nova_lxd/nova/virt/lxd/migrate.py
 delete mode 100644 nova_lxd/tests/test_container_migration.py
 create mode 100644 nova_lxd/tests/test_migrate.py

diff --git a/nova_lxd/nova/virt/lxd/container_migrate.py b/nova_lxd/nova/virt/lxd/container_migrate.py
deleted file mode 100644
index f55e15b..0000000
--- a/nova_lxd/nova/virt/lxd/container_migrate.py
+++ /dev/null
 <at>  <at>  -1,113 +0,0  <at>  <at> 
-# Copyright 2015 Canonical Ltd
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from nova import i18n
-
-from oslo_config import cfg
-from oslo_log import log as logging
-
-from nova_lxd.nova.virt.lxd import config
-from nova_lxd.nova.virt.lxd import operations
-from nova_lxd.nova.virt.lxd import session
-
-
-_ = i18n._
-_LE = i18n._LE
-_LI = i18n._LI
-
-CONF = cfg.CONF
-LOG = logging.getLogger(__name__)
-
-
-class LXDContainerMigrate(object):
-
-    def __init__(self, virtapi):
-        self.virtapi = virtapi
-        self.config = config.LXDContainerConfig()
-        self.session = session.LXDAPISession()
-        self.container_ops = \
-            operations.LXDContainerOperations(
-                self.virtapi)
-
-    def migrate_disk_and_power_off(self, context, instance, dest,
-                                   flavor, network_info,
-                                   block_device_info=None, timeout=0,
-                                   retry_interval=0):
-        LOG.debug("migrate_disk_and_power_off called", instance=instance)
-
-        LOG.info(_('No disk to migrate'))
-
-        # disk_info is not used
-        disk_info = {}
-        return disk_info
-
-    def confirm_migration(self, migration, instance, network_info):
-        LOG.debug("confirm_migration called", instance=instance)
-
-    def finish_revert_migration(self, context, instance, network_info,
-                                block_device_info=None, power_on=True):
-        LOG.debug("finish_revert_migration called", instance=instance)
-        container_config = self.get_container_config(instance)
-        self.container_ops.start_container(container_config, instance,
-                                           network_info,
-                                           need_vif_plugged=True)
-
-    def finish_migration(self, context, migration, instance, disk_info,
-                         network_info, image_meta, resize_instance=False,
-                         block_device_info=None, power_on=True):
-        LOG.debug("finish_migration called", instance=instance)
-
-        self._migration(migration, instance, network_info)
-
-    def _migration(self, migration, instance, network_info):
-        # XXX: zul (Jan 4, 2016) - Temporarily disabled due to LXD config
-        # change refactor.
-        LOG.debug('_migration called for instance', instance=instance)
-
-    def live_migration(self, context, instance_ref, dest, post_method,
-                       recover_method, block_migration=False,
-                       migrate_data=None):
-        LOG.debug("live_migration called", instance=instance_ref)
-        post_method(context, instance_ref, dest, block_migration)
-
-    def pre_live_migration(self, context, instance, block_device_info,
-                           network_info):
-        LOG.debug("pre_live_migration called", instance=instance)
-
-    def post_live_migration(self, context, instance, block_device_info):
-        LOG.debug("post_live_migration", instance=instance)
-        pass
-
-    def post_live_migration_at_destination(self, ctxt, instance_ref,
-                                           network_info, block_migration,
-                                           block_device_info):
-        LOG.debug("post_live_migration_at_destination called",
-                  instance=instance_ref)
-
-    def check_can_live_migrate_destination(self, ctxt, instance_ref,
-                                           src_compute_info, dst_compute_info,
-                                           block_migration=False,
-                                           disk_over_commit=False):
-        LOG.debug("check_can_live_migrate_destination called", instance_ref)
-        return {}
-
-    def check_can_live_migrate_destination_cleanup(self, ctxt,
-                                                   dest_check_data):
-        LOG.debug("check_can_live_migrate_destination_cleanup called")
-
-    def check_can_live_migrate_source(self, ctxt, instance_ref,
-                                      dest_check_data):
-        LOG.debug("check_can_live_migrate_source called", instance_ref)
-        return dest_check_data
diff --git a/nova_lxd/nova/virt/lxd/driver.py b/nova_lxd/nova/virt/lxd/driver.py
index ab8aee4..b701d16 100644
--- a/nova_lxd/nova/virt/lxd/driver.py
+++ b/nova_lxd/nova/virt/lxd/driver.py
 <at>  <at>  -26,9 +26,9  <at>  <at> 
 
 
 from nova_lxd.nova.virt.lxd import container_firewall
-from nova_lxd.nova.virt.lxd import container_migrate
 from nova_lxd.nova.virt.lxd import container_snapshot
 from nova_lxd.nova.virt.lxd import host
+from nova_lxd.nova.virt.lxd import migrate
 from nova_lxd.nova.virt.lxd import operations as container_ops
 from nova_lxd.nova.virt.lxd import vif as lxd_vif
 
 <at>  <at>  -70,7 +70,7  <at>  <at>  def __init__(self, virtapi):
         self.container_ops = container_ops.LXDContainerOperations(virtapi)
         self.container_snapshot = container_snapshot.LXDSnapshot()
         self.container_firewall = container_firewall.LXDContainerFirewall()
-        self.container_migrate = container_migrate.LXDContainerMigrate(virtapi)
+        self.container_migrate = migrate.LXDContainerMigrate(virtapi)
         self.host = host.LXDHost()
 
     def init_host(self, host):
diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
new file mode 100644
index 0000000..f55e15b
--- /dev/null
+++ b/nova_lxd/nova/virt/lxd/migrate.py
 <at>  <at>  -0,0 +1,113  <at>  <at> 
+# Copyright 2015 Canonical Ltd
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from nova import i18n
+
+from oslo_config import cfg
+from oslo_log import log as logging
+
+from nova_lxd.nova.virt.lxd import config
+from nova_lxd.nova.virt.lxd import operations
+from nova_lxd.nova.virt.lxd import session
+
+
+_ = i18n._
+_LE = i18n._LE
+_LI = i18n._LI
+
+CONF = cfg.CONF
+LOG = logging.getLogger(__name__)
+
+
+class LXDContainerMigrate(object):
+
+    def __init__(self, virtapi):
+        self.virtapi = virtapi
+        self.config = config.LXDContainerConfig()
+        self.session = session.LXDAPISession()
+        self.container_ops = \
+            operations.LXDContainerOperations(
+                self.virtapi)
+
+    def migrate_disk_and_power_off(self, context, instance, dest,
+                                   flavor, network_info,
+                                   block_device_info=None, timeout=0,
+                                   retry_interval=0):
+        LOG.debug("migrate_disk_and_power_off called", instance=instance)
+
+        LOG.info(_('No disk to migrate'))
+
+        # disk_info is not used
+        disk_info = {}
+        return disk_info
+
+    def confirm_migration(self, migration, instance, network_info):
+        LOG.debug("confirm_migration called", instance=instance)
+
+    def finish_revert_migration(self, context, instance, network_info,
+                                block_device_info=None, power_on=True):
+        LOG.debug("finish_revert_migration called", instance=instance)
+        container_config = self.get_container_config(instance)
+        self.container_ops.start_container(container_config, instance,
+                                           network_info,
+                                           need_vif_plugged=True)
+
+    def finish_migration(self, context, migration, instance, disk_info,
+                         network_info, image_meta, resize_instance=False,
+                         block_device_info=None, power_on=True):
+        LOG.debug("finish_migration called", instance=instance)
+
+        self._migration(migration, instance, network_info)
+
+    def _migration(self, migration, instance, network_info):
+        # XXX: zul (Jan 4, 2016) - Temporarily disabled due to LXD config
+        # change refactor.
+        LOG.debug('_migration called for instance', instance=instance)
+
+    def live_migration(self, context, instance_ref, dest, post_method,
+                       recover_method, block_migration=False,
+                       migrate_data=None):
+        LOG.debug("live_migration called", instance=instance_ref)
+        post_method(context, instance_ref, dest, block_migration)
+
+    def pre_live_migration(self, context, instance, block_device_info,
+                           network_info):
+        LOG.debug("pre_live_migration called", instance=instance)
+
+    def post_live_migration(self, context, instance, block_device_info):
+        LOG.debug("post_live_migration", instance=instance)
+        pass
+
+    def post_live_migration_at_destination(self, ctxt, instance_ref,
+                                           network_info, block_migration,
+                                           block_device_info):
+        LOG.debug("post_live_migration_at_destination called",
+                  instance=instance_ref)
+
+    def check_can_live_migrate_destination(self, ctxt, instance_ref,
+                                           src_compute_info, dst_compute_info,
+                                           block_migration=False,
+                                           disk_over_commit=False):
+        LOG.debug("check_can_live_migrate_destination called", instance_ref)
+        return {}
+
+    def check_can_live_migrate_destination_cleanup(self, ctxt,
+                                                   dest_check_data):
+        LOG.debug("check_can_live_migrate_destination_cleanup called")
+
+    def check_can_live_migrate_source(self, ctxt, instance_ref,
+                                      dest_check_data):
+        LOG.debug("check_can_live_migrate_source called", instance_ref)
+        return dest_check_data
diff --git a/nova_lxd/tests/test_container_migration.py b/nova_lxd/tests/test_container_migration.py
deleted file mode 100644
index b18ff26..0000000
--- a/nova_lxd/tests/test_container_migration.py
+++ /dev/null
 <at>  <at>  -1,73 +0,0  <at>  <at> 
-# Copyright 2015 Canonical Ltd
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import mock
-
-from nova import test
-from nova.virt import fake
-
-from nova_lxd.nova.virt.lxd import container_migrate
-from nova_lxd.nova.virt.lxd import session
-from nova_lxd.tests import stubs
-
-
- <at> mock.patch.object(container_migrate, 'CONF', stubs.MockConf())
- <at> mock.patch.object(session, 'CONF', stubs.MockConf())
-class LXDTestContainerMigrate(test.NoDBTestCase):
-
-     <at> mock.patch.object(container_migrate, 'CONF', stubs.MockConf())
-     <at> mock.patch.object(session, 'CONF', stubs.MockConf())
-    def setUp(self):
-        super(LXDTestContainerMigrate, self).setUp()
-
-        self.migrate = container_migrate.LXDContainerMigrate(
-            fake.FakeVirtAPI())
-
-     <at> mock.patch.object(session.LXDAPISession, 'container_migrate')
-    def test_finish_migration(self, mo):
-        context = mock.Mock()
-        migration = {'source_compute': 'fake-source',
-                     'dest_compute': 'fake-dest'}
-        instance = stubs._fake_instance()
-        bdevice_info = mock.Mock()
-        disk_info = mock.Mock()
-        network_info = mock.Mock()
-        with test.nested(
-            mock.patch.object(session.LXDAPISession,
-                              'container_defined'),
-            mock.patch.object(session.LXDAPISession,
-                              'container_stop'),
-            mock.patch.object(session.LXDAPISession,
-                              'container_init'),
-        ) as (
-            container_defined,
-            container_stop,
-            container_init
-        ):
-            def side_effect(*args, **kwargs):
-                # XXX: rockstar (7 Dec 2015) - This mock is a little greedy,
-                # and hits too many interfaces. It should become more specific
-                # to the single places it needs to fully mocked. Truthiness of
-                # the mock changes in py3.
-                if args[0] == 'defined':
-                    return False
-            container_defined.side_effect = side_effect
-            self.assertEqual(None,
-                             (self.migrate.finish_migration(context,
-                                                            migration,
-                                                            instance,
-                                                            disk_info,
-                                                            network_info,
-                                                            bdevice_info)))
diff --git a/nova_lxd/tests/test_migrate.py b/nova_lxd/tests/test_migrate.py
new file mode 100644
index 0000000..eef74eb
--- /dev/null
+++ b/nova_lxd/tests/test_migrate.py
 <at>  <at>  -0,0 +1,73  <at>  <at> 
+# Copyright 2015 Canonical Ltd
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import mock
+
+from nova import test
+from nova.virt import fake
+
+from nova_lxd.nova.virt.lxd import migrate
+from nova_lxd.nova.virt.lxd import session
+from nova_lxd.tests import stubs
+
+
+ <at> mock.patch.object(migrate, 'CONF', stubs.MockConf())
+ <at> mock.patch.object(session, 'CONF', stubs.MockConf())
+class LXDTestContainerMigrate(test.NoDBTestCase):
+
+     <at> mock.patch.object(migrate, 'CONF', stubs.MockConf())
+     <at> mock.patch.object(session, 'CONF', stubs.MockConf())
+    def setUp(self):
+        super(LXDTestContainerMigrate, self).setUp()
+
+        self.migrate = migrate.LXDContainerMigrate(
+            fake.FakeVirtAPI())
+
+     <at> mock.patch.object(session.LXDAPISession, 'container_migrate')
+    def test_finish_migration(self, mo):
+        context = mock.Mock()
+        migration = {'source_compute': 'fake-source',
+                     'dest_compute': 'fake-dest'}
+        instance = stubs._fake_instance()
+        bdevice_info = mock.Mock()
+        disk_info = mock.Mock()
+        network_info = mock.Mock()
+        with test.nested(
+            mock.patch.object(session.LXDAPISession,
+                              'container_defined'),
+            mock.patch.object(session.LXDAPISession,
+                              'container_stop'),
+            mock.patch.object(session.LXDAPISession,
+                              'container_init'),
+        ) as (
+            container_defined,
+            container_stop,
+            container_init
+        ):
+            def side_effect(*args, **kwargs):
+                # XXX: rockstar (7 Dec 2015) - This mock is a little greedy,
+                # and hits too many interfaces. It should become more specific
+                # to the single places it needs to fully mocked. Truthiness of
+                # the mock changes in py3.
+                if args[0] == 'defined':
+                    return False
+            container_defined.side_effect = side_effect
+            self.assertEqual(None,
+                             (self.migrate.finish_migration(context,
+                                                            migration,
+                                                            instance,
+                                                            disk_info,
+                                                            network_info,
+                                                            bdevice_info)))

From 20ab69d173a0866a5b217ba6887bab96cd4f3ab4 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 08:33:53 -0500
Subject: [PATCH 02/15] Implement resize and contianer resource limits

When using containers in production operators do not
want a container to take over a whole host, so LXD
has introduced container resource limits. We implement
the following LXD options, via flavors:

- memory limit
- vcpu limit
- disk limit
- privileged containers
- nested containers

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

diff --git a/nova_lxd/nova/virt/lxd/config.py b/nova_lxd/nova/virt/lxd/config.py
index 3fb79c9..e158337 100644
--- a/nova_lxd/nova/virt/lxd/config.py
+++ b/nova_lxd/nova/virt/lxd/config.py
 <at>  <at>  -103,6 +103,11  <at>  <at>  def create_profile(self, instance, network_info):
             config['config'] = self._create_config(instance_name, instance)
             config['devices'] = self._create_network(instance_name, instance,
                                                      network_info)
+
+            # Restrict the size of the "/" disk
+            config['devices'].update(
+                self.configure_container_root(instance))
+
             return config
         except Exception as ex:
             with excutils.save_and_reraise_exception():
 <at>  <at>  -121,10 +126,21  <at>  <at>  def _create_config(self, instance_name, instance):
         try:
             config = {}
 
+            # Update continaer options
+            config.update(self._config_instance_options(config, instance))
+
+            # Set the instance memory limit
             mem = instance.memory_mb
             if mem >= 0:
                 config['limits.memory'] = '%sMB' % mem
 
+
+            # Set the instnace vcpu limit
+            vcpus = instance.flavor.vcpus
+            if vcpus >= 0:
+                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' \
 <at>  <at>  -138,6 +154,42  <at>  <at>  def _create_config(self, instance_name, instance):
                         '%(ex)s'), {'instance': instance_name, 'ex': ex},
                     instance=instance)
 
+    def _config_instance_options(self, config, instance):
+        LOG.debug('_config_instance_options called for instance', instance=instance)
+
+        # Set the container to autostart when the host reboots
+        config['boot.autostart'] = 'True'
+
+        # Determine if we require a nested container
+        flavor = instance.flavor
+        lxd_nested_allowed = flavor.extra_specs.get('lxd_nested_allowed', False)
+        if lxd_nested_allowed:
+            config['security.nesting'] = 'True'
+
+        # Determine if we require a privileged container
+        lxd_privileged_allowed = flavor.extra_specs.get('lxd_privileged_allowed', False)
+        if lxd_privileged_allowed:
+            config['security.privileged'] = 'True'
+
+        return config
+
+    def configure_container_root(self, instance):
+        LOG.debug('_configure_container_root called for instnace',
+                  instance=instance)
+        try:
+            config = {}
+            config['root'] = {'path': '/',
+                              'type': 'disk',
+                              'size': '%sGB' % str(instance.root_gb)
+                            }
+            return config
+        except Exception as ex:
+            with excutils.save_and_reraise_exception():
+                LOG.error(_LE('Failed to configure disk for '
+                              '%(instance)s: %(ex)s'),
+                              {'instance': instance.name, 'ex': ex},
+                              instance=instance)
+
     def _create_network(self, instance_name, instance, network_info):
         """Create the LXD container network on the host
 
diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
index f55e15b..efc2023 100644
--- a/nova_lxd/nova/virt/lxd/migrate.py
+++ b/nova_lxd/nova/virt/lxd/migrate.py
 <at>  <at>  -17,6 +17,7  <at>  <at> 
 
 from oslo_config import cfg
 from oslo_log import log as logging
+from oslo_utils import excutils
 
 from nova_lxd.nova.virt.lxd import config
 from nova_lxd.nova.virt.lxd import operations
 <at>  <at>  -28,6 +29,7  <at>  <at> 
 _LI = i18n._LI
 
 CONF = cfg.CONF
+CONF.import_opt('my_ip', 'nova.netconf')
 LOG = logging.getLogger(__name__)
 
 
 <at>  <at>  -47,11 +49,31  <at>  <at>  def migrate_disk_and_power_off(self, context, instance, dest,
                                    retry_interval=0):
         LOG.debug("migrate_disk_and_power_off called", instance=instance)
 
-        LOG.info(_('No disk to migrate'))
+        same_host = False
+        if CONF.my_ip == dest:
+            same_host = True
+            LOG.debug('Migration target is the source host')
+        else:
+            LOG.debug('Migration target host: %s' % dest)
+
+        if not self.session.continer_defined(instance.name, instance):
+            msg = _('Instance is not found.')
+            raise exception.NovaException(msg)
+
+        try:
+            if same_host:
+                container_profile = self.container.create_profile(instnace, 
+                                                                  network_info)
+                self.session.profile_update(container_profile, instance)
+        except Exception as ex:
+            with excutils.save_and_reraise_exception():
+                LOG.error(_LE('failed to resize container '
+                              '%(instance)s: %(ex)s'),
+                              {'instance': instance.name, 'ex': ex},
+                              instance=instance)
 
         # disk_info is not used
-        disk_info = {}
-        return disk_info
+        return ""
 
     def confirm_migration(self, migration, instance, network_info):
         LOG.debug("confirm_migration called", instance=instance)

From 0e4430bd6ca5835cfca4d19313e0e79d6c8e20f9 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 09:01:36 -0500
Subject: [PATCH 03/15] Always connect to the unix socket

Except for container_migrate always connect to the
local UNIX socket to use the pylxd API. Nova scheduler
does the right thing with regards to multiple compute hosts.

Signed-off-by: Chuck Short <chuck.short <at> canonical.com>
---
 nova_lxd/nova/virt/lxd/container_snapshot.py |  2 +-
 nova_lxd/nova/virt/lxd/operations.py         | 11 ++--
 nova_lxd/nova/virt/lxd/session.py            | 75 +++++++++++++---------------
 nova_lxd/tests/session/test_container.py     | 15 +++---
 4 files changed, 45 insertions(+), 58 deletions(-)

diff --git a/nova_lxd/nova/virt/lxd/container_snapshot.py b/nova_lxd/nova/virt/lxd/container_snapshot.py
index 2be4da9..fb49b6f 100644
--- a/nova_lxd/nova/virt/lxd/container_snapshot.py
+++ b/nova_lxd/nova/virt/lxd/container_snapshot.py
 <at>  <at>  -78,7 +78,7  <at>  <at>  def snapshot(self, context, instance, image_id, update_task_state):
                 # We have to stop the container before we can publish the
                 # image to the local store
                 self.session.container_stop(instance.name,
-                                            instance.host, instance)
+                                            instance)
                 fingerprint = self._save_lxd_image(instance,
                                                    image_id)
                 self.session.container_start(instance.name, instance)
diff --git a/nova_lxd/nova/virt/lxd/operations.py b/nova_lxd/nova/virt/lxd/operations.py
index 2db014e..351b58f 100644
--- a/nova_lxd/nova/virt/lxd/operations.py
+++ b/nova_lxd/nova/virt/lxd/operations.py
 <at>  <at>  -211,7 +211,7  <at>  <at>  def _setup_container(self, instance_name, instance):
             container_config = \
                 self.config.create_container(instance)
             self.session.container_init(
-                container_config, instance, instance.host)
+                container_config, instance)
 
             # Start the container
             self.session.container_start(instance_name, instance)
 <at>  <at>  -345,7 +345,7  <at>  <at>  def destroy(self, context, instance, network_info, block_device_info=None,
         LOG.debug('destroy called for instance', instance=instance)
         try:
             self.session.profile_delete(instance)
-            self.session.container_destroy(instance.name, instance.host,
+            self.session.container_destroy(instance.name,
                                            instance)
             self.cleanup(context, instance, network_info, block_device_info)
         except Exception as ex:
 <at>  <at>  -366,7 +366,6  <at>  <at>  def power_off(self, instance, timeout=0, retry_interval=0):
         LOG.debug('power_off called for instance', instance=instance)
         try:
             self.session.container_stop(instance.name,
-                                        instance.host,
                                         instance)
         except Exception as ex:
             with excutils.save_and_reraise_exception():
 <at>  <at>  -475,7 +474,7  <at>  <at>  def rescue(self, context, instance, network_info, image_meta,
                 raise exception.NovaException(msg)
 
             # Step 1 - Stop the old container
-            self.session.container_stop(instance.name, instance.host, instance)
+            self.session.container_stop(instance.name, instance)
 
             # Step 2 - Rename the broken contianer to be rescued
             self.session.container_move(instance.name,
 <at>  <at>  -490,8 +489,7  <at>  <at>  def rescue(self, context, instance, network_info, image_meta,
             config = self.config.configure_disk_path(rescue_dir,
                                                      'mnt', 'rescue', instance)
             container_config['devices'].update(config)
-            self.session.container_init(container_config, instance,
-                                        instance.host)
+            self.session.container_init(container_config, instance)
 
             # Step 4 - Start the rescue instance
             self.session.container_start(instance.name, instance)
 <at>  <at>  -516,7 +514,6  <at>  <at>  def unrescue(self, instance, network_info):
 
             # Step 1 - Destory the rescue instance.
             self.session.container_destroy(instance.name,
-                                           instance.host,
                                            instance)
 
             # Step 2 - Rename the backup container that
diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index e6b6142..83aa33f 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
 <at>  <at>  -75,12 +75,10  <at>  <at>  def get_session(self, host=None):
         :return: pylxd object
         """
         try:
-            if host is None:
-                conn = api.API()
-            elif host == CONF.host:
-                conn = api.API()
+            if host:
+                return api.API(host=host)
             else:
-                conn = api.API(host=host)
+                return api.API()
         except Exception as ex:
             # notify the compute host that the connection failed
             # via an rpc call
 <at>  <at>  -93,8 +91,6  <at>  <at>  def get_session(self, host=None):
                                               payload)
             raise exception.HypervisorUnavailable(host=CONF.host)
 
-        return conn
-
     #
     # Container related API methods
     #
 <at>  <at>  -129,7 +125,7  <at>  <at>  def container_update(self, config, instance):
         """
         LOG.debug('container_update called fo instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             if not self.container_defined(instance.name, instance):
                 msg = _('Instance is not found..: %s') % instance.name
                 raise exception.InstanceNotFound(msg)
 <at>  <at>  -157,7 +153,7  <at>  <at>  def container_running(self, instance):
         """
         LOG.debug('container_running for instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             return client.container_running(instance.name)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -180,7 +176,7  <at>  <at>  def container_state(self, instance):
         """
         LOG.debug('container_state called for instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             if not self.container_defined(instance.name, instance):
                 return power_state.NOSTATE
 
 <at>  <at>  -214,7 +210,7  <at>  <at>  def container_config(self, instance):
                 msg = _('Instance is not found.. %s') % instance.name
                 raise exception.InstanceNotFound(msg)
 
-            client = self.get_session(instance.host)
+            client = self.get_session()
             return client.get_container_config(instance.name)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -241,7 +237,7  <at>  <at>  def container_info(self, instance):
                 msg = _('Instance is not found.. %s') % instance.name
                 raise exception.InstanceNotFound(msg)
 
-            client = self.get_session(instance.host)
+            client = self.get_session()
             return client.container_info(instance.name)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -265,7 +261,7  <at>  <at>  def container_defined(self, instance_name, instance):
         """
         LOG.debug('container_defined for instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             return client.container_defined(instance_name)
         except lxd_exceptions.APIError as ex:
             if ex.status_code == 404:
 <at>  <at>  -293,7 +289,7  <at>  <at>  def container_start(self, instance_name, instance):
                          '%(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
             # Start the container
-            client = self.get_session(instance.host)
+            client = self.get_session()
 
             # (chuck): Something wicked could happen between
             # container
 <at>  <at>  -320,11 +316,10  <at>  <at>  def container_start(self, instance_name, instance):
                     {'instance': instance_name, 'reason': ex},
                     instance=instance)
 
-    def container_stop(self, instance_name, host, instance):
+    def container_stop(self, instance_name, instance):
         """Stops an LXD container
 
         :param instance_name: instance name
-        :param host:  host where the container is running
         :param instance: nova instance object
 
         """
 <at>  <at>  -338,7 +333,7  <at>  <at>  def container_stop(self, instance_name, host, instance):
                          '%(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
             # Stop the container
-            client = self.get_session(host)
+            client = self.get_session()
             (state, data) = client.container_stop(instance_name,
                                                   CONF.lxd.timeout)
             self.operation_wait(data.get('operation'), instance)
 <at>  <at>  -375,7 +370,7  <at>  <at>  def container_reboot(self, instance):
                                         'image': instance.image_ref})
 
             # Container reboot
-            client = self.get_session(instance.host)
+            client = self.get_session()
             (state, data) = client.container_reboot(instance.name,
                                                     CONF.lxd.timeout)
             self.operation_wait(data.get('operation'), instance)
 <at>  <at>  -395,11 +390,10  <at>  <at>  def container_reboot(self, instance):
                         '%(reason)s'), {'instance': instance.name,
                                         'reason': ex}, instance=instance)
 
-    def container_destroy(self, instance_name, host, instance):
+    def container_destroy(self, instance_name, instance):
         """Destroy a LXD container
 
         :param instance_name: container name
-        :param host: container host
         :param instance: nova instance object
 
         """
 <at>  <at>  -413,9 +407,9  <at>  <at>  def container_destroy(self, instance_name, host, instance):
                                         'image': instance.image_ref})
 
             # Destroying container
-            self.container_stop(instance_name, host, instance)
+            self.container_stop(instance_name, instance)
 
-            client = self.get_session(host)
+            client = self.get_session()
             (state, data) = client.container_destroy(instance_name)
             self.operation_wait(data.get('operation'), instance)
 
 <at>  <at>  -450,7 +444,7  <at>  <at>  def container_pause(self, instance_name, instance):
                          '%(image)s'), {'instance': instance_name,
                                         'image': instance.image_ref})
 
-            client = self.get_session(instance.host)
+            client = self.get_session()
             (state, data) = client.container_suspend(instance_name,
                                                      CONF.lxd.timeout)
             self.operation_wait(data.get('operation'), instance)
 <at>  <at>  -488,7 +482,7  <at>  <at>  def container_unpause(self, instance_name, instance):
                          '%(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
 
-            client = self.get_session(instance.host)
+            client = self.get_session()
             (state, data) = client.container_resume(instance_name,
                                                     CONF.lxd.timeout)
             self.operation_wait(data.get('operation'), instance)
 <at>  <at>  -508,12 +502,11  <at>  <at>  def container_unpause(self, instance_name, instance):
                         '%(reason)s'), {'instance': instance_name,
                                         'reason': ex})
 
-    def container_init(self, config, instance, host):
+    def container_init(self, config, instance):
         """Create a LXD container
 
         :param config: LXD container config as a dict
         :param instance: nova instance object
-        :param host: host to create the container on
 
         """
         LOG.debug('container_init called for instance', instance=instance)
 <at>  <at>  -522,7 +515,7  <at>  <at>  def container_init(self, config, instance, host):
                          '%(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
 
-            client = self.get_session(host)
+            client = self.get_session()
             (state, data) = client.container_init(config)
             operation = data.get('operation')
             self.operation_wait(operation, instance)
 <at>  <at>  -559,7 +552,7  <at>  <at>  def image_defined(self, instance):
         """
         LOG.debug('image_defined called for instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             return client.alias_defined(instance.image_ref)
         except lxd_exceptions.APIError as ex:
             if ex.status_code == 404:
 <at>  <at>  -587,7 +580,7  <at>  <at>  def create_alias(self, alias, instance):
         """
         LOG.debug('create_alias called for instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             return client.alias_create(alias)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -612,7 +605,7  <at>  <at>  def image_upload(self, data, headers, instance):
         """
         LOG.debug('upload_image called for instnace', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             (state, data) = client.image_upload(data=data,
                                                 headers=headers)
             # XXX - zulcss (Dec 8, 2015) - Work around for older
 <at>  <at>  -643,7 +636,7  <at>  <at>  def operation_wait(self, operation_id, instance):
         """
         LOG.debug('wait_for_contianer for instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             if not client.wait_container_operation(operation_id, 200, -1):
                 msg = _('Container creation timed out')
                 raise exception.NovaException(msg)
 <at>  <at>  -663,7 +656,7  <at>  <at>  def operation_wait(self, operation_id, instance):
     def operation_info(self, operation_id, instance):
         LOG.debug('operation_info called for instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             return client.operation_info(operation_id)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -690,7 +683,7  <at>  <at>  def profile_defined(self, instance):
         LOG.debug('profile_defined called for instance',
                   instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             client.profile_defined(instance.name)
         except lxd_exceptions.APIError as ex:
             if ex.status_code == 404:
 <at>  <at>  -716,7 +709,7  <at>  <at>  def profile_create(self, config, instance):
         LOG.debug('profile_create called for instance',
                   instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             client.profile_create(config)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -737,7 +730,7  <at>  <at>  def profile_update(self, config, instance):
         """
         LOG.debug('profile_udpate called for instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             client.profile_update(instance.name, config)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -758,7 +751,7  <at>  <at>  def profile_delete(self, instance):
         """
         LOG.debug('profile_delete called for instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             client.profile_delete(instance.name)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -829,7 +822,7  <at>  <at>  def container_move(self, old_name, config, instance):
                                         'image': instance.image_ref})
 
             # Container move
-            client = self.get_session(instance.host)
+            client = self.get_session()
             (state, data) = client.container_local_move(old_name, config)
             self.operation_wait(data.get('operation'), instance)
 
 <at>  <at>  -863,7 +856,7  <at>  <at>  def container_snapshot(self, snapshot, instance):
                                         'image': instance.image_ref})
 
             # Container snapshot
-            client = self.get_session(instance.host)
+            client = self.get_session()
             (state, data) = client.container_snapshot_create(
                 instance.name, snapshot)
             self.operation_wait(data.get('operation'), instance)
 <at>  <at>  -894,7 +887,7  <at>  <at>  def container_publish(self, image, instance):
         """
         LOG.debug('container_publish called for instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             return client.container_publish(image)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -919,7 +912,7  <at>  <at>  def container_export(self, image, instance):
         """
         LOG.debug('container_export called for instance', instance=instance)
         try:
-            client = self.get_session(instance.host)
+            client = self.get_session()
             return client.image_export(image)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to export image: %s') % ex
 <at>  <at>  -956,7 +949,7  <at>  <at>  def _wait_for_snapshot(self, event_id, instance):
         :param event_id: operation id
         :param instance: nova instance object
         """
-        client = self.get_session(instance.host)
+        client = self.get_session()
         (state, data) = client.operation_info(event_id)
         status_code = data['metadata']['status_code']
 
diff --git a/nova_lxd/tests/session/test_container.py b/nova_lxd/tests/session/test_container.py
index 431e285..ac68fe2 100644
--- a/nova_lxd/tests/session/test_container.py
+++ b/nova_lxd/tests/session/test_container.py
 <at>  <at>  -327,7 +327,7  <at>  <at>  def test_container_stop(self, tag, side_effect):
         self.ml.container_stop.return_value = side_effect
         self.assertEqual(None,
                          self.session.container_stop(instance.name,
-                                                     instance.host, instance))
+                                                     instance))
         calls = [mock.call.container_defined(instance.name),
                  mock.call.container_stop(instance.name, -1),
                  mock.call.wait_container_operation(
 <at>  <at>  -348,7 +348,7  <at>  <at>  def test_container_stop_fail(self, tag, side_effect, expected):
         self.ml.container_stop.side_effect = side_effect
         self.assertRaises(expected,
                           self.session.container_stop, instance.name,
-                          instance.host, instance)
+                          instance)
 
      <at> stubs.annotated_data(
         ('1,', (200, fake_api.fake_operation_info_ok()))
 <at>  <at>  -399,7 +399,6  <at>  <at>  def test_container_destroy(self, tag, container_defined, side_effect):
             self.ml.container_destroy.return_value = side_effect
             self.assertEqual(None,
                              self.session.container_destroy(instance.name,
-                                                            instance.host,
                                                             instance))
             calls = [mock.call.container_defined(instance.name),
                      mock.call.container_defined(instance.name),
 <at>  <at>  -414,7 +413,6  <at>  <at>  def test_container_destroy(self, tag, container_defined, side_effect):
             self.ml.container_defined.return_value = container_defined
             self.assertEqual(None,
                              self.session.container_destroy(instance.name,
-                                                            instance.host,
                                                             instance))
             calls = [mock.call.container_defined(instance.name)]
             self.assertEqual(calls, self.ml.method_calls)
 <at>  <at>  -438,7 +436,7  <at>  <at>  def test_container_destroy_fail(self, tag, container_defined,
             self.ml.container_stop.side_effect = side_effect
             self.assertRaises(expected,
                               self.session.container_destroy, instance.name,
-                              instance.host, instance)
+                              instance)
         if test_type == 'fail_destroy':
             self.ml.container_defined.return_value = container_defined
             self.ml.container_stop.return_value = \
 <at>  <at>  -446,7 +444,7  <at>  <at>  def test_container_destroy_fail(self, tag, container_defined,
             self.ml.container_destroy.side_effect = side_effect
             self.assertRaises(expected,
                               self.session.container_destroy, instance.name,
-                              instance.host, instance)
+                              instance)
 
      <at> stubs.annotated_data(
         ('1', (200, fake_api.fake_operation_info_ok()))
 <at>  <at>  -536,8 +534,7  <at>  <at>  def test_container_init(self, tag, side_effect):
         self.ml.operation_info.return_value = \
             (200, fake_api.fake_container_state(200))
         self.assertEqual(None,
-                         self.session.container_init(config, instance,
-                                                     instance.host))
+                         self.session.container_init(config, instance))
         calls = [mock.call.container_init(config),
                  mock.call.wait_container_operation(
                      '/1.0/operation/1234', 200, -1),
 <at>  <at>  -559,4 +556,4  <at>  <at>  def test_container_init_fail(self, tag, side_effect, expected):
         self.ml.container_init.side_effect = side_effect
         self.assertRaises(expected,
                           self.session.container_init, config,
-                          instance, instance.host)
+                          instance)

From 58cbd3c1ec073046830735d056bd59a4f522ac81 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 09:04:29 -0500
Subject: [PATCH 04/15] Cleanup log messages

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

diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index 83aa33f..c03584a 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
 <at>  <at>  -127,7 +127,7  <at>  <at>  def container_update(self, config, instance):
         try:
             client = self.get_session()
             if not self.container_defined(instance.name, instance):
-                msg = _('Instance is not found..: %s') % instance.name
+                msg = _('Instance is not found: %s') % instance.name
                 raise exception.InstanceNotFound(msg)
 
             return client.container_update(instance.name,
 <at>  <at>  -207,7 +207,7  <at>  <at>  def container_config(self, instance):
         LOG.debug('container_config called for instance', instance=instance)
         try:
             if not self.container_defined(instance.name, instance):
-                msg = _('Instance is not found.. %s') % instance.name
+                msg = _('Instance is not found %s') % instance.name
                 raise exception.InstanceNotFound(msg)
 
             client = self.get_session()
 <at>  <at>  -234,7 +234,7  <at>  <at>  def container_info(self, instance):
         LOG.debug('container_info called for instance', instance=instance)
         try:
             if not self.container_defined(instance.name, instance):
-                msg = _('Instance is not found.. %s') % instance.name
+                msg = _('Instance is not found %s') % instance.name
                 raise exception.InstanceNotFound(msg)
 
             client = self.get_session()
 <at>  <at>  -294,7 +294,7  <at>  <at>  def container_start(self, instance_name, instance):
             # (chuck): Something wicked could happen between
             # container
             if not self.container_defined(instance_name, instance):
-                msg = _('Instance is not found.. %s ') % instance.name
+                msg = _('Instance is not found %s ') % instance.name
                 raise exception.InstanceNotFound(msg)
 
             (state, data) = client.container_start(instance_name,
 <at>  <at>  -302,7 +302,7  <at>  <at>  def container_start(self, instance_name, instance):
             self.operation_wait(data.get('operation'), instance)
 
             LOG.info(_LI('Successfully started instance %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -326,11 +326,11  <at>  <at>  def container_stop(self, instance_name, instance):
         LOG.debug('container_stop called for instance', instance=instance)
         try:
             if not self.container_defined(instance_name, instance):
-                msg = _('Instance is not found..: %s') % instance.name
+                msg = _('Instance is not found %s') % instance.name
                 raise exception.InstanceNotFound(msg)
 
             LOG.info(_LI('Stopping instance %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
             # Stop the container
             client = self.get_session()
 <at>  <at>  -339,7 +339,7  <at>  <at>  def container_stop(self, instance_name, instance):
             self.operation_wait(data.get('operation'), instance)
 
             LOG.info(_LI('Successfully stopped instance %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -362,11 +362,11  <at>  <at>  def container_reboot(self, instance):
         LOG.debug('container_reboot called for instance', instance=instance)
         try:
             if not self.container_defined(instance.name, instance):
-                msg = _('Instance is not found..: %s') % instance.name
+                msg = _('Instance is not found %s') % instance.name
                 raise exception.InstanceNotFound(msg)
 
             LOG.info(_LI('Rebooting instance %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
 
             # Container reboot
 <at>  <at>  -376,7 +376,7  <at>  <at>  def container_reboot(self, instance):
             self.operation_wait(data.get('operation'), instance)
 
             LOG.info(_LI('Successfully rebooted instance %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -403,7 +403,7  <at>  <at>  def container_destroy(self, instance_name, instance):
                 return
 
             LOG.info(_LI('Destroying instance %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
 
             # Destroying container
 <at>  <at>  -414,7 +414,7  <at>  <at>  def container_destroy(self, instance_name, instance):
             self.operation_wait(data.get('operation'), instance)
 
             LOG.info(_LI('Successfully destroyed instance %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -437,11 +437,11  <at>  <at>  def container_pause(self, instance_name, instance):
         LOG.debug('container_paused called for instance', instance=instance)
         try:
             if not self.container_defined(instance_name, instance):
-                msg = _('Instance is not found. %s') % instance_name
+                msg = _('Instance is not found %s') % instance_name
                 raise exception.InstanceNotFound(msg)
 
             LOG.info(_LI('Pausing instance %(instance)s with'
-                         '%(image)s'), {'instance': instance_name,
+                         ' %(image)s'), {'instance': instance_name,
                                         'image': instance.image_ref})
 
             client = self.get_session()
 <at>  <at>  -450,7 +450,7  <at>  <at>  def container_pause(self, instance_name, instance):
             self.operation_wait(data.get('operation'), instance)
 
             LOG.info(_LI('Successfully paused instance %(instance)s with'
-                         '%(image)s'), {'instance': instance_name,
+                         ' %(image)s'), {'instance': instance_name,
                                         'image': instance.image_ref})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -475,11 +475,11  <at>  <at>  def container_unpause(self, instance_name, instance):
         LOG.debug('container_unpause called for instance', instance=instance)
         try:
             if not self.container_defined(instance_name, instance):
-                msg = _('Instance is not found. %s') % instance_name
+                msg = _('Instance is not found %s') % instance_name
                 raise exception.InstanceNotFound(msg)
 
             LOG.info(_LI('Unpausing instance %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
 
             client = self.get_session()
 <at>  <at>  -488,7 +488,7  <at>  <at>  def container_unpause(self, instance_name, instance):
             self.operation_wait(data.get('operation'), instance)
 
             LOG.info(_LI('Successfully unpaused instance %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -512,7 +512,7  <at>  <at>  def container_init(self, config, instance):
         LOG.debug('container_init called for instance', instance=instance)
         try:
             LOG.info(_LI('Creating container %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
 
             client = self.get_session()
 <at>  <at>  -525,7 +525,7  <at>  <at>  def container_init(self, config, instance):
                 raise exception.NovaException(data['metadata'])
 
             LOG.info(_LI('Successfully created container %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
 <at>  <at>  -660,7 +660,7  <at>  <at>  def operation_info(self, operation_id, instance):
             return client.operation_info(operation_id)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
-                    '%(reason)s') % {'instance': instance.image_ref,
+                    ' %(reason)s') % {'instance': instance.image_ref,
                                      'reason': ex}
             LOG.error(msg)
             raise exception.NovaException(msg)
 <at>  <at>  -778,7 +778,7  <at>  <at>  def container_migrate(self, instance_name, host, instance):
         """
         LOG.debug('container_migrate called for instance', instance=instance)
         try:
-            LOG.info(_LI('Migrating instance %(instance)s with'
+            LOG.info(_LI('Migrating instance %(instance)s with '
                          '%(image)s'), {'instance': instance_name,
                                         'image': instance.image_ref})
 
 <at>  <at>  -817,7 +817,7  <at>  <at>  def container_move(self, old_name, config, instance):
         """
         LOG.debug('container_move called for instance', instnace=instance)
         try:
-            LOG.info(_LI('Moving container %(instance)s with'
+            LOG.info(_LI('Moving container %(instance)s with '
                          '%(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
 
 <at>  <at>  -826,7 +826,7  <at>  <at>  def container_move(self, old_name, config, instance):
             (state, data) = client.container_local_move(old_name, config)
             self.operation_wait(data.get('operation'), instance)
 
-            LOG.info(_LI('Successfully moved container %(instance)s with'
+            LOG.info(_LI('Successfully moved container %(instance)s with '
                          '%(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
         except lxd_exceptions.APIError as ex:
 <at>  <at>  -837,8 +837,8  <at>  <at>  def container_move(self, old_name, config, instance):
         except Exception as ex:
             with excutils.save_and_reraise_exception():
                 LOG.error(
-                    _LE('Failed to move container %(instance)s: %('
-                        'reason)s'),
+                    _LE('Failed to move container %(instance)s: '
+                        '%(reason)s'),
                     {'instance': instance.name,
                      'reason': ex}, instance=instance)
 
 <at>  <at>  -862,7 +862,7  <at>  <at>  def container_snapshot(self, snapshot, instance):
             self.operation_wait(data.get('operation'), instance)
 
             LOG.info(_LI('Successfully snapshotted container %(instance)s with'
-                         '%(image)s'), {'instance': instance.name,
+                         ' %(image)s'), {'instance': instance.name,
                                         'image': instance.image_ref})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'

From 0650e7d16ead918af2718e5cf19f5b354163a79a Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 09:07:01 -0500
Subject: [PATCH 05/15] Remove unimplemented methods

Remove unimplemented methods so that the code
is easier to read.

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

diff --git a/nova_lxd/nova/virt/lxd/driver.py b/nova_lxd/nova/virt/lxd/driver.py
index b701d16..f0bbe54 100644
--- a/nova_lxd/nova/virt/lxd/driver.py
+++ b/nova_lxd/nova/virt/lxd/driver.py
 <at>  <at>  -232,31 +232,22  <at>  <at>  def get_available_resource(self, nodename):
 
     def pre_live_migration(self, context, instance, block_device_info,
                            network_info, disk_info, migrate_data=None):
-        return self.container_migrate.pre_live_migration(
-            context, instance, block_device_info,
-            network_info)
+        raise NotImplementedError()
 
     def live_migration(self, context, instance, dest,
                        post_method, recover_method, block_migration=False,
                        migrate_data=None):
-        return self.container_migrate.live_migration(context, instance, dest,
-                                                     post_method,
-                                                     recover_method,
-                                                     block_migration,
-                                                     migrate_data)
+        raise NotImplementedError()
 
     def post_live_migration(self, context, instance, block_device_info,
                             migrate_data=None):
-        return self.container_migrate.post_live_migration(context, instance,
-                                                          block_device_info)
+        raise NotImplementedError()
 
     def post_live_migration_at_destination(self, context, instance,
                                            network_info,
                                            block_migration=False,
                                            block_device_info=None):
-        return self.container_migrate.post_live_migration_at_destination(
-            context, instance, network_info, block_migration,
-            block_device_info)
+        raise NotImplementedError()
 
     def check_instance_shared_storage_local(self, context, instance):
         raise NotImplementedError()
diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
index efc2023..21bc5b7 100644
--- a/nova_lxd/nova/virt/lxd/migrate.py
+++ b/nova_lxd/nova/virt/lxd/migrate.py
 <at>  <at>  -78,58 +78,7  <at>  <at>  def migrate_disk_and_power_off(self, context, instance, dest,
     def confirm_migration(self, migration, instance, network_info):
         LOG.debug("confirm_migration called", instance=instance)
 
-    def finish_revert_migration(self, context, instance, network_info,
-                                block_device_info=None, power_on=True):
-        LOG.debug("finish_revert_migration called", instance=instance)
-        container_config = self.get_container_config(instance)
-        self.container_ops.start_container(container_config, instance,
-                                           network_info,
-                                           need_vif_plugged=True)
-
     def finish_migration(self, context, migration, instance, disk_info,
                          network_info, image_meta, resize_instance=False,
                          block_device_info=None, power_on=True):
         LOG.debug("finish_migration called", instance=instance)
-
-        self._migration(migration, instance, network_info)
-
-    def _migration(self, migration, instance, network_info):
-        # XXX: zul (Jan 4, 2016) - Temporarily disabled due to LXD config
-        # change refactor.
-        LOG.debug('_migration called for instance', instance=instance)
-
-    def live_migration(self, context, instance_ref, dest, post_method,
-                       recover_method, block_migration=False,
-                       migrate_data=None):
-        LOG.debug("live_migration called", instance=instance_ref)
-        post_method(context, instance_ref, dest, block_migration)
-
-    def pre_live_migration(self, context, instance, block_device_info,
-                           network_info):
-        LOG.debug("pre_live_migration called", instance=instance)
-
-    def post_live_migration(self, context, instance, block_device_info):
-        LOG.debug("post_live_migration", instance=instance)
-        pass
-
-    def post_live_migration_at_destination(self, ctxt, instance_ref,
-                                           network_info, block_migration,
-                                           block_device_info):
-        LOG.debug("post_live_migration_at_destination called",
-                  instance=instance_ref)
-
-    def check_can_live_migrate_destination(self, ctxt, instance_ref,
-                                           src_compute_info, dst_compute_info,
-                                           block_migration=False,
-                                           disk_over_commit=False):
-        LOG.debug("check_can_live_migrate_destination called", instance_ref)
-        return {}
-
-    def check_can_live_migrate_destination_cleanup(self, ctxt,
-                                                   dest_check_data):
-        LOG.debug("check_can_live_migrate_destination_cleanup called")
-
-    def check_can_live_migrate_source(self, ctxt, instance_ref,
-                                      dest_check_data):
-        LOG.debug("check_can_live_migrate_source called", instance_ref)
-        return dest_check_data

From 2d19ea2d7c338f210bc0d99aa55273f1523f68c2 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 09:11:45 -0500
Subject: [PATCH 06/15] Make sure profiles exist

Make sure LXD profiles exist or not
before running operations that need a profile.

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

diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index c03584a..0c76957 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
 <at>  <at>  -674,7 +674,23  <at>  <at>  def operation_info(self, operation_id, instance):
     #
     # Profile methods
     #
-    def profile_defined(self, instance):
+    def profile_list(self):
+        LOG.debug('profile_list called for instance')
+        try:
+            client = self.get_session()
+            return client.profile_list()
+        except lxd_exceptions.APIError as ex:
+            msg = _('Failed to communicate with LXD API: %(reason)s') \
+                     % {'reason': ex}
+            LOG.error(msg)
+            raise excpetion.NovaException(msg)
+        except Exception as ex:
+            with excutils.save_and_reraise_exception():
+                LOG.error(_LE('Error from LXD during profile_list: '
+                          '%(reason)s') % {'reason': ex})
+
+
+    def profile_defined(self, instance_name, instance):
         """Validate if the profile is available on the LXD
            host
 
 <at>  <at>  -683,8 +699,10  <at>  <at>  def profile_defined(self, instance):
         LOG.debug('profile_defined called for instance',
                   instance=instance)
         try:
-            client = self.get_session()
-            client.profile_defined(instance.name)
+            found = False
+            if instance_name in self.profile_list():
+                found = True
+            return found
         except lxd_exceptions.APIError as ex:
             if ex.status_code == 404:
                 return False
 <at>  <at>  -709,8 +727,12  <at>  <at>  def profile_create(self, config, instance):
         LOG.debug('profile_create called for instance',
                   instance=instance)
         try:
+            if self.profile_defined(instance.name, instance):
+                msg = _('Profile already exists %s' % instance.name)
+                raise exception.NovaException(msg)
+
             client = self.get_session()
-            client.profile_create(config)
+            return client.profile_create(config)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.name,
 <at>  <at>  -730,8 +752,12  <at>  <at>  def profile_update(self, config, instance):
         """
         LOG.debug('profile_udpate called for instance', instance=instance)
         try:
+            if not self.profile_defined(instance.name, instance):
+                msg  = _('Profile not found %s' % instance.name)
+                raise exception.NovaException(msg)
+
             client = self.get_session()
-            client.profile_update(instance.name, config)
+            return client.profile_update(instance.name, config)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.name,
 <at>  <at>  -751,8 +777,11  <at>  <at>  def profile_delete(self, instance):
         """
         LOG.debug('profile_delete called for instance', instance=instance)
         try:
+            if not self.profile_defined(instance.name, instance):
+                return
+
             client = self.get_session()
-            client.profile_delete(instance.name)
+            return client.profile_delete(instance.name)
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.name,

From a74228232444a80a684694d55dfb2c9019e15a44 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 17:02:40 -0500
Subject: [PATCH 07/15] Make functions non-private

Make functions non-private so that we can use them
for container migration.

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

diff --git a/nova_lxd/nova/virt/lxd/config.py b/nova_lxd/nova/virt/lxd/config.py
index e158337..3beffc3 100644
--- a/nova_lxd/nova/virt/lxd/config.py
+++ b/nova_lxd/nova/virt/lxd/config.py
 <at>  <at>  -60,7 +60,7  <at>  <at>  def create_container(self, instance):
             container_config = {
                 'name': instance_name,
                 'profiles': [str(instance.name)],
-                'source': self._get_container_source(instance),
+                'source': self.get_container_source(instance),
                 'devices': {}
             }
 
 <at>  <at>  -100,8 +100,8  <at>  <at>  def create_profile(self, instance, network_info):
         try:
             config = {}
             config['name'] = str(instance_name)
-            config['config'] = self._create_config(instance_name, instance)
-            config['devices'] = self._create_network(instance_name, instance,
+            config['config'] = self.create_config(instance_name, instance)
+            config['devices'] = self.create_network(instance_name, instance,
                                                      network_info)
 
             # Restrict the size of the "/" disk
 <at>  <at>  -115,7 +115,7  <at>  <at>  def create_profile(self, instance, network_info):
                     _LE('Failed to create profile %(instance)s: %(ex)s'),
                     {'instance': instance_name, 'ex': ex}, instance=instance)
 
-    def _create_config(self, instance_name, instance):
+    def create_config(self, instance_name, instance):
         """Create the LXD container resources
 
         :param instance_name: instance name
 <at>  <at>  -127,7 +127,7  <at>  <at>  def _create_config(self, instance_name, instance):
             config = {}
 
             # Update continaer options
-            config.update(self._config_instance_options(config, instance))
+            config.update(self.config_instance_options(config, instance))
 
             # Set the instance memory limit
             mem = instance.memory_mb
 <at>  <at>  -154,7 +154,7  <at>  <at>  def _create_config(self, instance_name, instance):
                         '%(ex)s'), {'instance': instance_name, 'ex': ex},
                     instance=instance)
 
-    def _config_instance_options(self, config, instance):
+    def config_instance_options(self, config, instance):
         LOG.debug('_config_instance_options called for instance', instance=instance)
 
         # Set the container to autostart when the host reboots
 <at>  <at>  -219,7 +219,7  <at>  <at>  def _create_network(self, instance_name, instance, network_info):
                     _LE('Fail to configure network for %(instance)s: %(ex)s'),
                     {'instance': instance_name, 'ex': ex}, instance=instance)
 
-    def _get_container_source(self, instance):
+    def get_container_source(self, instance):
         """Set the LXD container image for the instance.
 
         :param instance: nova instance object
 <at>  <at>  -283,7 +283,7  <at>  <at>  def create_container_net_device(self, instance, vif):
             network_config = self.vif_driver.get_config(instance, vif)
 
             config = {}
-            config[self._get_network_device(instance)] = {
+            config[self.get_network_device(instance)] = {
                 'nictype': 'bridged',
                 'hwaddr': str(vif['address']),
                 'parent': str(network_config['bridge']),
 <at>  <at>  -296,7 +296,7  <at>  <at>  def create_container_net_device(self, instance, vif):
                       {'instance': instance.name, 'ex': ex},
                       instance=instance)
 
-    def _get_network_device(self, instance):
+    def get_network_device(self, instance):
         """Try to detect which network interfaces are available in a contianer
 
         :param instnace: nova instance object

From 9bc25286bfd5778729b4ea89958980632383e6f2 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 17:09:16 -0500
Subject: [PATCH 08/15] Add finish_revert_migration

Add the ability to start the container if migration fails.

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

diff --git a/nova_lxd/nova/virt/lxd/driver.py b/nova_lxd/nova/virt/lxd/driver.py
index f0bbe54..df3ae2e 100644
--- a/nova_lxd/nova/virt/lxd/driver.py
+++ b/nova_lxd/nova/virt/lxd/driver.py
 <at>  <at>  -194,6 +194,12  <at>  <at>  def confirm_migration(self, migration, instance, network_info):
                                                         instance,
                                                         network_info)
 
+    def finish_revert_migration(self, context, instance, network_info,
+                               block_device_info=None, power_on=True):
+        return self.container_migrate.finish_revert_migration(context,
+                                instance, network_info, block_device_info,
+                                power_on)
+
     def pause(self, instance):
         self.container_ops.pause(instance)
 
diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
index 21bc5b7..fe54260 100644
--- a/nova_lxd/nova/virt/lxd/migrate.py
+++ b/nova_lxd/nova/virt/lxd/migrate.py
 <at>  <at>  -82,3 +82,11  <at>  <at>  def finish_migration(self, context, migration, instance, disk_info,
                          network_info, image_meta, resize_instance=False,
                          block_device_info=None, power_on=True):
         LOG.debug("finish_migration called", instance=instance)
+
+    def finish_revert_migration(self, context, instance, network_info,
+                                 block_device_info=None, power_on=True):
+        LOG.debug('finish_revert_migration called for instance',
+                    instance=instance)
+        if self.session.container_defined(instance.name, instance):
+            self.session.container_start(instance.name, instance)
+

From 9740282129eb4c608409c31f1179e6f511417609 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 17:12:08 -0500
Subject: [PATCH 09/15] Fix typos

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

diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
index fe54260..95bbc18 100644
--- a/nova_lxd/nova/virt/lxd/migrate.py
+++ b/nova_lxd/nova/virt/lxd/migrate.py
 <at>  <at>  -13,6 +13,7  <at>  <at> 
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from nova import exception
 from nova import i18n
 
 from oslo_config import cfg
 <at>  <at>  -56,14 +57,14  <at>  <at>  def migrate_disk_and_power_off(self, context, instance, dest,
         else:
             LOG.debug('Migration target host: %s' % dest)
 
-        if not self.session.continer_defined(instance.name, instance):
+        if not self.session.container_defined(instance.name, instance):
             msg = _('Instance is not found.')
             raise exception.NovaException(msg)
 
         try:
             if same_host:
-                container_profile = self.container.create_profile(instnace, 
-                                                                  network_info)
+                container_profile = self.config.create_profile(instance,
+                                                               network_info)
                 self.session.profile_update(container_profile, instance)
         except Exception as ex:
             with excutils.save_and_reraise_exception():

From 47db5b460d67cab0bd386727e4f1906d3b38dacf Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 17:25:24 -0500
Subject: [PATCH 10/15] Refactor migration support

Refactor container migration support.

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

diff --git a/nova_lxd/nova/virt/lxd/config.py b/nova_lxd/nova/virt/lxd/config.py
index 3beffc3..de4864d 100644
--- a/nova_lxd/nova/virt/lxd/config.py
+++ b/nova_lxd/nova/virt/lxd/config.py
 <at>  <at>  -243,6 +243,39  <at>  <at>  def get_container_source(self, instance):
                     {'instance': instance.name, 'ex': ex},
                     instance=instance)
 
+    def get_container_migrate(self, container_migrate, migration, instance):
+        LOG.debug('get_container_migrate called for instance',
+                  instnace=instance)
+        try:
+            # Generate the container config
+            container_metadata =container_migrate['metadata']
+            container_control = container_metadata['metadata']['control']
+            container_fs = container_metadata['metadata']['fs']
+
+            container_url = ('wss://%s:8443%s/websocket'
+                             % (migration['source_compute'],
+                                container_migrate.get('operation')))
+
+            container_migrate = {
+                    'base_iamge': '',
+                    'mode': 'pull',
+                    'operation': str(container_url),
+                    'secrets': {
+                        'control': str(container_control),
+                        'fs': str(container_fs)
+                    },
+                    'type': 'migration'
+            }
+
+            LOG.debug(pprint.pprint(container_migrate))
+            return container_migrate
+        except Exception as ex:
+            with excutils.save_and_reraise_exception():
+                LOG.error(_LE('Failed to configure migation source '
+                              '%(instance)s: %(ex)s'),
+                             {'instance': instance.name, 'ex': ex},
+                             instance=instance)
+
     def configure_disk_path(self, src_path, dest_path, vfs_type, instance):
         """Configure the host mount point for the LXD container
 
 <at>  <at>  -255,10 +288,6  <at>  <at>  def configure_disk_path(self, src_path, dest_path, vfs_type, instance):
         LOG.debug('configure_disk_path called for instance',
                   instance=instance)
         try:
-            if not os.path.exists(src_path):
-                msg = _('Source path does not exist')
-                raise exception.NovaException(msg)
-
             config = {}
             config[vfs_type] = {'path': dest_path,
                                 'source': src_path,
diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
index 95bbc18..5a0b7fc 100644
--- a/nova_lxd/nova/virt/lxd/migrate.py
+++ b/nova_lxd/nova/virt/lxd/migrate.py
 <at>  <at>  -13,15 +13,21  <at>  <at> 
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import os
+import pprint
+import shutil
+
 from nova import exception
 from nova import i18n
 
 from oslo_config import cfg
 from oslo_log import log as logging
 from oslo_utils import excutils
+from oslo_utils import fileutils
 
 from nova_lxd.nova.virt.lxd import config
 from nova_lxd.nova.virt.lxd import operations
+from nova_lxd.nova.virt.lxd import utils as container_dir
 from nova_lxd.nova.virt.lxd import session
 
 
 <at>  <at>  -39,8 +45,9  <at>  <at>  class LXDContainerMigrate(object):
     def __init__(self, virtapi):
         self.virtapi = virtapi
         self.config = config.LXDContainerConfig()
+        self.container_dir = container_dir.LXDContainerDirectories()
         self.session = session.LXDAPISession()
-        self.container_ops = \
+        self.operations = \
             operations.LXDContainerOperations(
                 self.virtapi)
 
 <at>  <at>  -66,6 +73,8  <at>  <at>  def migrate_disk_and_power_off(self, context, instance, dest,
                 container_profile = self.config.create_profile(instance,
                                                                network_info)
                 self.session.profile_update(container_profile, instance)
+            else:
+                self.session.container_stop(instance.name, instance)
         except Exception as ex:
             with excutils.save_and_reraise_exception():
                 LOG.error(_LE('failed to resize container '
 <at>  <at>  -79,11 +88,65  <at>  <at>  def migrate_disk_and_power_off(self, context, instance, dest,
     def confirm_migration(self, migration, instance, network_info):
         LOG.debug("confirm_migration called", instance=instance)
 
+        if not self.session.container_defined(instance.name, instance):
+            msg = _('Failed to find container %s' % instance.name)
+            raise exception.NovaException(msg)
+
+        try:
+            self.session.profile_delete(instance)
+            self.session.container_destroy(instance.name,
+                                           instance)
+            self.operations.unplug_vifs(instance, network_info)
+            container_dir = self.container_dir.get_instance_dir(instance.name)
+            if os.path.exists(container_dir):
+                shutil.rmtree(container_dir)
+        except Exception as ex:
+            with excutils.save_and_reraise_exception():
+                LOG.exception(_LE('Confirm migration failed for %(instnace)s: '
+                                  '%(ex)s'), {'instance': instance.name,
+                                    'ex': ex}, instance=instance)
+
     def finish_migration(self, context, migration, instance, disk_info,
                          network_info, image_meta, resize_instance=False,
                          block_device_info=None, power_on=True):
         LOG.debug("finish_migration called", instance=instance)
 
+        if self.session.container_defined(instance.name, instance):
+            msg = _('Failed to find container %s' % instance.name)
+            raise exception.NovaException(msg)
+
+        try:
+            # Ensure that the instance directory exists
+            instance_dir = \
+                self.container_dir.get_instance_dir(instance.name)
+            if not os.path.exists(instance_dir):
+                fileutils.ensure_tree(instance_dir)
+
+            # Step 1 - Setup the profile on the dest host
+            container_profile = self.config.create_profile(instance,
+                                        network_info)
+            self.session.profile_create(container_profile, instance)
+
+            # Step 2 - Open a websocket on the srct and and
+            #          generate the container config
+            (state, data) = self.session.container_migrate(instance.name,
+                                    migration['source_compute'], instance)
+            container_config = self.config.create_container(instance)
+            container_config['source'] = \
+                self.config.get_container_migrate(data, migration, instance)
+            LOG.debug(pprint.pprint(container_config))
+            self.session.container_init(container_config, instance)
+
+            # Step 3 - Start the network and contianer
+            self.operations.plug_vifs(instance, network_info)
+            self.session.container_start(instance.name, instance)
+        except Exception as ex:
+            with excutils.save_and_reraise_exception():
+                LOG.exception(_LE('Migration failed for %(instnace)s: '
+                                  '%(ex)s'),
+                                  {'instance': instance.name,
+                                   'ex': ex}, instance=instance)
+
     def finish_revert_migration(self, context, instance, network_info,
                                  block_device_info=None, power_on=True):
         LOG.debug('finish_revert_migration called for instance',

From aeb4c51cf3e7ef38e650fe4a956664d1f114f707 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 17:43:31 -0500
Subject: [PATCH 11/15] Fix various typos found

Fix various typos found

Signed-off-by: Chuck Short <chuck.short <at> canonical.com>
---
 nova_lxd/nova/virt/lxd/config.py             | 21 +++++++--------
 nova_lxd/nova/virt/lxd/container_snapshot.py |  3 ++-
 nova_lxd/nova/virt/lxd/image.py              | 15 +++++------
 nova_lxd/nova/virt/lxd/migrate.py            |  4 +--
 nova_lxd/nova/virt/lxd/operations.py         |  4 +--
 nova_lxd/nova/virt/lxd/session.py            | 39 ++++++++++++++++------------
 6 files changed, 45 insertions(+), 41 deletions(-)

diff --git a/nova_lxd/nova/virt/lxd/config.py b/nova_lxd/nova/virt/lxd/config.py
index de4864d..ade9bdf 100644
--- a/nova_lxd/nova/virt/lxd/config.py
+++ b/nova_lxd/nova/virt/lxd/config.py
 <at>  <at>  -122,7 +122,7  <at>  <at>  def create_config(self, instance_name, instance):
         :param instance: nova instance object
         :return: LXD resources dictionary
         """
-        LOG.debug('_create_config called for instance', instance=instance)
+        LOG.debug('create_config called for instance', instance=instance)
         try:
             config = {}
 
 <at>  <at>  -135,7 +135,7  <at>  <at>  def create_config(self, instance_name, instance):
                 config['limits.memory'] = '%sMB' % mem
 
 
-            # Set the instnace vcpu limit
+            # Set the instance vcpu limit
             vcpus = instance.flavor.vcpus
             if vcpus >= 0:
                 config['limits.cpu'] = str(vcpus)
 <at>  <at>  -155,7 +155,7  <at>  <at>  def create_config(self, instance_name, instance):
                     instance=instance)
 
     def config_instance_options(self, config, instance):
-        LOG.debug('_config_instance_options called for instance', instance=instance)
+        LOG.debug('config_instance_options called for instance', instance=instance)
 
         # Set the container to autostart when the host reboots
         config['boot.autostart'] = 'True'
 <at>  <at>  -174,7 +174,7  <at>  <at>  def config_instance_options(self, config, instance):
         return config
 
     def configure_container_root(self, instance):
-        LOG.debug('_configure_container_root called for instnace',
+        LOG.debug('configure_container_root called for instance',
                   instance=instance)
         try:
             config = {}
 <at>  <at>  -190,7 +190,7  <at>  <at>  def configure_container_root(self, instance):
                               {'instance': instance.name, 'ex': ex},
                               instance=instance)
 
-    def _create_network(self, instance_name, instance, network_info):
+    def create_network(self, instance_name, instance, network_info):
         """Create the LXD container network on the host
 
         :param instance_name: nova instance name
 <at>  <at>  -198,7 +198,7  <at>  <at>  def _create_network(self, instance_name, instance, network_info):
         :param network_info: instance network configuration object
         :return:network configuration dictionary
         """
-        LOG.debug('_create_network called for instance', instance=instance)
+        LOG.debug('create_network called for instance', instance=instance)
         try:
             network_devices = {}
 
 <at>  <at>  -225,7 +225,7  <at>  <at>  def get_container_source(self, instance):
         :param instance: nova instance object
         :return: the container source
         """
-        LOG.debug('_get_container_source called for instance',
+        LOG.debug('get_container_source called for instance',
                   instance=instance)
         try:
             container_source = {'type': 'image',
 <at>  <at>  -245,7 +245,7  <at>  <at>  def get_container_source(self, instance):
 
     def get_container_migrate(self, container_migrate, migration, instance):
         LOG.debug('get_container_migrate called for instance',
-                  instnace=instance)
+                  instance=instance)
         try:
             # Generate the container config
             container_metadata =container_migrate['metadata']
 <at>  <at>  -267,7 +267,6  <at>  <at>  def get_container_migrate(self, container_migrate, migration, instance):
                     'type': 'migration'
             }
 
-            LOG.debug(pprint.pprint(container_migrate))
             return container_migrate
         except Exception as ex:
             with excutils.save_and_reraise_exception():
 <at>  <at>  -328,9 +327,9  <at>  <at>  def create_container_net_device(self, instance, vif):
     def get_network_device(self, instance):
         """Try to detect which network interfaces are available in a contianer
 
-        :param instnace: nova instance object
+        :param instance: nova instance object
         """
-        LOG.debug('_get_network_device called for instance', instance=instance)
+        LOG.debug('get_network_device called for instance', instance=instance)
         data = self.session.container_info(instance)
         lines = open('/proc/%s/net/dev' % data['init']).readlines()
         interfaces = []
diff --git a/nova_lxd/nova/virt/lxd/container_snapshot.py b/nova_lxd/nova/virt/lxd/container_snapshot.py
index fb49b6f..8d885d6 100644
--- a/nova_lxd/nova/virt/lxd/container_snapshot.py
+++ b/nova_lxd/nova/virt/lxd/container_snapshot.py
 <at>  <at>  -99,6 +99,7  <at>  <at>  def _save_lxd_image(self, instance, image_id):
         """
         LOG.debug('_save_lxd_image called for instance', instance=instance)
 
+        fingerprint = None
         try:
             # Publish the snapshot to the local LXD image store
             container_snapshot = {
 <at>  <at>  -140,7 +141,7  <at>  <at>  def _save_lxd_image(self, instance, image_id):
         return fingerprint
 
     def _save_glance_image(self, context, instance, image_id, fingerprint):
-        LOG.debug('_save_glance_image called for instance', instnace=instance)
+        LOG.debug('_save_glance_image called for instance', instance=instance)
 
         try:
             snapshot = IMAGE_API.get(context, image_id)
diff --git a/nova_lxd/nova/virt/lxd/image.py b/nova_lxd/nova/virt/lxd/image.py
index a39d54c..2f29fcd 100644
--- a/nova_lxd/nova/virt/lxd/image.py
+++ b/nova_lxd/nova/virt/lxd/image.py
 <at>  <at>  -87,7 +87,7  <at>  <at>  def setup_image(self, context, instance, image_meta):
                 self._verify_image(context, instance)
 
                 # Fetch the image from glance
-                self._fetch_image(context, image_meta, instance)
+                self._fetch_image(context, instance)
 
                 # Generate the LXD manifest for the image
                 self._get_lxd_manifest(instance, image_meta)
 <at>  <at>  -99,7 +99,7  <at>  <at>  def setup_image(self, context, instance, image_meta):
                 self._setup_alias(instance)
 
                 # Remove image and manifest when done.
-                self._cleanup_image(image_meta, instance)
+                self._cleanup_image(instance)
 
             except Exception as ex:
                 with excutils.save_and_reraise_exception():
 <at>  <at>  -107,7 +107,7  <at>  <at>  def setup_image(self, context, instance, image_meta):
                                   '%(reason)s'),
                               {'image': instance.image_ref,
                                'reason': ex}, instance=instance)
-                    self._cleanup_image(image_meta, instance)
+                    self._cleanup_image(instance)
 
     def _verify_image(self, context, instance):
         """Inspect image to verify the correct disk format.
 <at>  <at>  -142,11 +142,10  <at>  <at>  def _verify_image(self, context, instance):
             raise exception.ImageUnacceptable(image_id=instance.image_ref,
                                               reason=reason)
 
-    def _fetch_image(self, context, image_meta, instance):
+    def _fetch_image(self, context, instance):
         """Fetch an image from glance
 
         :param context: nova security object
-        :param image_meta: glance image dict
         :param instance: the nova instance object
 
         """
 <at>  <at>  -164,6 +163,7  <at>  <at>  def _get_lxd_manifest(self, instance, image_meta):
         """
         LOG.debug('_get_lxd_manifest called for instance', instance=instance)
 
+        metadata_yaml = None
         try:
             # Create a basic LXD manifest from the image properties
             image_arch = image_meta.properties.get('hw_architecture')
 <at>  <at>  -217,8 +217,6  <at>  <at>  def _image_upload(self, instance):
         We create the LXD manifest on the fly since glance does
         not understand how to talk to Glance.
 
-        :param path: path to the glance image
-        :param filenmae: name of the file
         :param instance: nova instance
 
         """
 <at>  <at>  -260,7 +258,6  <at>  <at>  def _image_upload(self, instance):
     def _setup_alias(self, instance):
         """Creates the LXD alias for the image
 
-        :param path: fileystem path of the glance image
         :param instance: nova instance
         """
         LOG.debug('_setup_alias called for instance', instance=instance)
 <at>  <at>  -281,7 +278,7  <at>  <at>  def _setup_alias(self, instance):
                               ' %(ex)s'), {'image': instance.image_ref,
                                            'ex': ex}, instance=instance)
 
-    def _cleanup_image(self, image_meta, instance):
+    def _cleanup_image(self, instance):
         """Cleanup the remaning bits of the glance/lxd interaction
 
         :params image_meta: image_meta dictionary
diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
index 5a0b7fc..7388b82 100644
--- a/nova_lxd/nova/virt/lxd/migrate.py
+++ b/nova_lxd/nova/virt/lxd/migrate.py
 <at>  <at>  -102,7 +102,7  <at>  <at>  def confirm_migration(self, migration, instance, network_info):
                 shutil.rmtree(container_dir)
         except Exception as ex:
             with excutils.save_and_reraise_exception():
-                LOG.exception(_LE('Confirm migration failed for %(instnace)s: '
+                LOG.exception(_LE('Confirm migration failed for %(instance)s: '
                                   '%(ex)s'), {'instance': instance.name,
                                     'ex': ex}, instance=instance)
 
 <at>  <at>  -142,7 +142,7  <at>  <at>  def finish_migration(self, context, migration, instance, disk_info,
             self.session.container_start(instance.name, instance)
         except Exception as ex:
             with excutils.save_and_reraise_exception():
-                LOG.exception(_LE('Migration failed for %(instnace)s: '
+                LOG.exception(_LE('Migration failed for %(instance)s: '
                                   '%(ex)s'),
                                   {'instance': instance.name,
                                    'ex': ex}, instance=instance)
diff --git a/nova_lxd/nova/virt/lxd/operations.py b/nova_lxd/nova/virt/lxd/operations.py
index 351b58f..7151e6b 100644
--- a/nova_lxd/nova/virt/lxd/operations.py
+++ b/nova_lxd/nova/virt/lxd/operations.py
 <at>  <at>  -298,7 +298,7  <at>  <at>  def plug_vifs(self, instance, network_info):
         """Setup the container network on the host
 
          :param instance: nova instance object
-         :param network_info: instnace network configuration
+         :param network_info: instance network configuration
          """
         LOG.debug('plug_vifs called for instance', instance=instance)
         try:
 <at>  <at>  -586,7 +586,7  <at>  <at>  def get_console_output(self, context, instance):
         :param context: security context
         :param instance: nova.objects.instance.Instance
         """
-        LOG.debug('get_console_output called for instnace', instance=instance)
+        LOG.debug('get_console_output called for instance', instance=instance)
         try:
             console_log = self.container_dir.get_console_path(instance.name)
             if not os.path.exists(console_log):
diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index 0c76957..dddbc77 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
 <at>  <at>  -574,7 +574,7  <at>  <at>  def create_alias(self, alias, instance):
         """Creates an alias for a given image
 
         :param alias: The alias to be crerated
-        :param instance: The nove instnace
+        :param instance: The nove instance
         :return: true if alias is created, false otherwise
 
         """
 <at>  <at>  -600,10 +600,10  <at>  <at>  def image_upload(self, data, headers, instance):
 
         :param data: image data
         :param headers: image headers
-        :param intance: The nova instance
+        :param instance: The nova instance
 
         """
-        LOG.debug('upload_image called for instnace', instance=instance)
+        LOG.debug('upload_image called for instance', instance=instance)
         try:
             client = self.get_session()
             (state, data) = client.image_upload(data=data,
 <at>  <at>  -633,6 +633,7  <at>  <at>  def operation_wait(self, operation_id, instance):
         """Waits for an operation to return 200 (Success)
 
         :param operation_id: The operation to wait for.
+        :param instance: nova instace object
         """
         LOG.debug('wait_for_contianer for instance', instance=instance)
         try:
 <at>  <at>  -683,7 +684,7  <at>  <at>  def profile_list(self):
             msg = _('Failed to communicate with LXD API: %(reason)s') \
                      % {'reason': ex}
             LOG.error(msg)
-            raise excpetion.NovaException(msg)
+            raise exception.NovaException(msg)
         except Exception as ex:
             with excutils.save_and_reraise_exception():
                 LOG.error(_LE('Error from LXD during profile_list: '
 <at>  <at>  -722,7 +723,7  <at>  <at>  def profile_create(self, config, instance):
         """Create an LXD container profile
 
         :param config: profile dictionary
-        :param instnace: nova instance object
+        :param instance: nova instance object
         """
         LOG.debug('profile_create called for instance',
                   instance=instance)
 <at>  <at>  -844,7 +845,7  <at>  <at>  def container_move(self, old_name, config, instance):
         :return:
 
         """
-        LOG.debug('container_move called for instance', instnace=instance)
+        LOG.debug('container_move called for instance', instance=instance)
         try:
             LOG.info(_LI('Moving container %(instance)s with '
                          '%(image)s'), {'instance': instance.name,
 <at>  <at>  -958,7 +959,7  <at>  <at>  def wait_for_snapshot(self, event_id, instance):
         """Poll snapshot operation for the snapshot to be ready.
 
         :param event_id: operation id
-        :param instnace: nova instance object
+        :param instance: nova instance object
         """
         LOG.debug('wait_for_snapshot called for instance', instance=instance)
 
 <at>  <at>  -978,12 +979,18  <at>  <at>  def _wait_for_snapshot(self, event_id, instance):
         :param event_id: operation id
         :param instance: nova instance object
         """
-        client = self.get_session()
-        (state, data) = client.operation_info(event_id)
-        status_code = data['metadata']['status_code']
-
-        if status_code == 200:
-            raise loopingcall.LoopingCallDone()
-        elif status_code == 400:
-            msg = _('Snapshot failed')
-            raise exception.NovaException(msg)
+        try:
+            client = self.get_session()
+            (state, data) = client.operation_info(event_id)
+            status_code = data['metadata']['status_code']
+
+            if status_code == 200:
+                raise loopingcall.LoopingCallDone()
+            elif status_code == 400:
+                msg = _('Snapshot failed')
+                raise exception.NovaException(msg)
+        except Exception as ex:
+            with excutils.save_and_reraise_exception():
+                LOG.error(_LE('Failed to wait for snapshot for %(instance)s: '
+                             '%(ex)s'), {'instance': instance.name, 'ex': ex},
+                              instance=instance)

From 2b1bbc45a3e32e6a290ff8fe17f7e07d570299f2 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 17:58:31 -0500
Subject: [PATCH 12/15] Fix failing pep8 and unit tests

Signed-off-by: Chuck Short <chuck.short <at> canonical.com>
---
 nova_lxd/nova/virt/lxd/config.py  | 37 +++++++++++-----------
 nova_lxd/nova/virt/lxd/driver.py  |  8 ++---
 nova_lxd/nova/virt/lxd/migrate.py | 29 +++++++++--------
 nova_lxd/nova/virt/lxd/session.py | 65 ++++++++++++++++++---------------------
 nova_lxd/tests/test_config.py     | 16 +++-------
 nova_lxd/tests/test_driver_api.py |  2 --
 nova_lxd/tests/test_image.py      |  4 +--
 nova_lxd/tests/test_migrate.py    | 37 ----------------------
 tox.ini                           |  2 +-
 9 files changed, 75 insertions(+), 125 deletions(-)

diff --git a/nova_lxd/nova/virt/lxd/config.py b/nova_lxd/nova/virt/lxd/config.py
index ade9bdf..559c53f 100644
--- a/nova_lxd/nova/virt/lxd/config.py
+++ b/nova_lxd/nova/virt/lxd/config.py
 <at>  <at>  -17,7 +17,6  <at>  <at> 
 from nova import exception
 from nova import i18n
 from nova.virt import configdrive
-import os
 
 from oslo_config import cfg
 from oslo_log import log as logging
 <at>  <at>  -102,7 +101,7  <at>  <at>  def create_profile(self, instance, network_info):
             config['name'] = str(instance_name)
             config['config'] = self.create_config(instance_name, instance)
             config['devices'] = self.create_network(instance_name, instance,
-                                                     network_info)
+                                                    network_info)
 
             # Restrict the size of the "/" disk
             config['devices'].update(
 <at>  <at>  -134,7 +133,6  <at>  <at>  def create_config(self, instance_name, instance):
             if mem >= 0:
                 config['limits.memory'] = '%sMB' % mem
 
-
             # Set the instance vcpu limit
             vcpus = instance.flavor.vcpus
             if vcpus >= 0:
 <at>  <at>  -155,19 +153,22  <at>  <at>  def create_config(self, instance_name, instance):
                     instance=instance)
 
     def config_instance_options(self, config, instance):
-        LOG.debug('config_instance_options called for instance', instance=instance)
+        LOG.debug('config_instance_options called for instance',
+                  instance=instance)
 
         # Set the container to autostart when the host reboots
         config['boot.autostart'] = 'True'
 
         # Determine if we require a nested container
         flavor = instance.flavor
-        lxd_nested_allowed = flavor.extra_specs.get('lxd_nested_allowed', False)
+        lxd_nested_allowed = flavor.extra_specs.get(
+            'lxd_nested_allowed', False)
         if lxd_nested_allowed:
             config['security.nesting'] = 'True'
 
         # Determine if we require a privileged container
-        lxd_privileged_allowed = flavor.extra_specs.get('lxd_privileged_allowed', False)
+        lxd_privileged_allowed = flavor.extra_specs.get(
+            'lxd_privileged_allowed', False)
         if lxd_privileged_allowed:
             config['security.privileged'] = 'True'
 
 <at>  <at>  -181,14 +182,14  <at>  <at>  def configure_container_root(self, instance):
             config['root'] = {'path': '/',
                               'type': 'disk',
                               'size': '%sGB' % str(instance.root_gb)
-                            }
+                              }
             return config
         except Exception as ex:
             with excutils.save_and_reraise_exception():
                 LOG.error(_LE('Failed to configure disk for '
                               '%(instance)s: %(ex)s'),
-                              {'instance': instance.name, 'ex': ex},
-                              instance=instance)
+                          {'instance': instance.name, 'ex': ex},
+                          instance=instance)
 
     def create_network(self, instance_name, instance, network_info):
         """Create the LXD container network on the host
 <at>  <at>  -248,7 +249,7  <at>  <at>  def get_container_migrate(self, container_migrate, migration, instance):
                   instance=instance)
         try:
             # Generate the container config
-            container_metadata =container_migrate['metadata']
+            container_metadata = container_migrate['metadata']
             container_control = container_metadata['metadata']['control']
             container_fs = container_metadata['metadata']['fs']
 
 <at>  <at>  -257,14 +258,14  <at>  <at>  def get_container_migrate(self, container_migrate, migration, instance):
                                 container_migrate.get('operation')))
 
             container_migrate = {
-                    'base_iamge': '',
-                    'mode': 'pull',
-                    'operation': str(container_url),
-                    'secrets': {
+                'base_iamge': '',
+                'mode': 'pull',
+                'operation': str(container_url),
+                'secrets': {
                         'control': str(container_control),
                         'fs': str(container_fs)
-                    },
-                    'type': 'migration'
+                },
+                'type': 'migration'
             }
 
             return container_migrate
 <at>  <at>  -272,8 +273,8  <at>  <at>  def get_container_migrate(self, container_migrate, migration, instance):
             with excutils.save_and_reraise_exception():
                 LOG.error(_LE('Failed to configure migation source '
                               '%(instance)s: %(ex)s'),
-                             {'instance': instance.name, 'ex': ex},
-                             instance=instance)
+                          {'instance': instance.name, 'ex': ex},
+                          instance=instance)
 
     def configure_disk_path(self, src_path, dest_path, vfs_type, instance):
         """Configure the host mount point for the LXD container
diff --git a/nova_lxd/nova/virt/lxd/driver.py b/nova_lxd/nova/virt/lxd/driver.py
index df3ae2e..df9eb1b 100644
--- a/nova_lxd/nova/virt/lxd/driver.py
+++ b/nova_lxd/nova/virt/lxd/driver.py
 <at>  <at>  -195,10 +195,10  <at>  <at>  def confirm_migration(self, migration, instance, network_info):
                                                         network_info)
 
     def finish_revert_migration(self, context, instance, network_info,
-                               block_device_info=None, power_on=True):
-        return self.container_migrate.finish_revert_migration(context,
-                                instance, network_info, block_device_info,
-                                power_on)
+                                block_device_info=None, power_on=True):
+        return self.container_migrate.finish_revert_migration(
+            context, instance, network_info, block_device_info,
+            power_on)
 
     def pause(self, instance):
         self.container_ops.pause(instance)
diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
index 7388b82..fbe19ee 100644
--- a/nova_lxd/nova/virt/lxd/migrate.py
+++ b/nova_lxd/nova/virt/lxd/migrate.py
 <at>  <at>  -79,8 +79,8  <at>  <at>  def migrate_disk_and_power_off(self, context, instance, dest,
             with excutils.save_and_reraise_exception():
                 LOG.error(_LE('failed to resize container '
                               '%(instance)s: %(ex)s'),
-                              {'instance': instance.name, 'ex': ex},
-                              instance=instance)
+                          {'instance': instance.name, 'ex': ex},
+                          instance=instance)
 
         # disk_info is not used
         return ""
 <at>  <at>  -89,7 +89,8  <at>  <at>  def confirm_migration(self, migration, instance, network_info):
         LOG.debug("confirm_migration called", instance=instance)
 
         if not self.session.container_defined(instance.name, instance):
-            msg = _('Failed to find container %s' % instance.name)
+            msg = _('Failed to find container %(instance)s') % \
+                {'instnace': instance.name}
             raise exception.NovaException(msg)
 
         try:
 <at>  <at>  -104,7 +105,7  <at>  <at>  def confirm_migration(self, migration, instance, network_info):
             with excutils.save_and_reraise_exception():
                 LOG.exception(_LE('Confirm migration failed for %(instance)s: '
                                   '%(ex)s'), {'instance': instance.name,
-                                    'ex': ex}, instance=instance)
+                                              'ex': ex}, instance=instance)
 
     def finish_migration(self, context, migration, instance, disk_info,
                          network_info, image_meta, resize_instance=False,
 <at>  <at>  -112,7 +113,8  <at>  <at>  def finish_migration(self, context, migration, instance, disk_info,
         LOG.debug("finish_migration called", instance=instance)
 
         if self.session.container_defined(instance.name, instance):
-            msg = _('Failed to find container %s' % instance.name)
+            msg = _('Failed to find container %(instance)s') % \
+                {'instance': instance.name}
             raise exception.NovaException(msg)
 
         try:
 <at>  <at>  -124,13 +126,15  <at>  <at>  def finish_migration(self, context, migration, instance, disk_info,
 
             # Step 1 - Setup the profile on the dest host
             container_profile = self.config.create_profile(instance,
-                                        network_info)
+                                                           network_info)
             self.session.profile_create(container_profile, instance)
 
             # Step 2 - Open a websocket on the srct and and
             #          generate the container config
-            (state, data) = self.session.container_migrate(instance.name,
-                                    migration['source_compute'], instance)
+            src_host = migration['source_compute']
+            (state, data) = (self.session.container_migrate(instance.name,
+                                                            src_host,
+                                                            instance))
             container_config = self.config.create_container(instance)
             container_config['source'] = \
                 self.config.get_container_migrate(data, migration, instance)
 <at>  <at>  -144,13 +148,12  <at>  <at>  def finish_migration(self, context, migration, instance, disk_info,
             with excutils.save_and_reraise_exception():
                 LOG.exception(_LE('Migration failed for %(instance)s: '
                                   '%(ex)s'),
-                                  {'instance': instance.name,
-                                   'ex': ex}, instance=instance)
+                              {'instance': instance.name,
+                               'ex': ex}, instance=instance)
 
     def finish_revert_migration(self, context, instance, network_info,
-                                 block_device_info=None, power_on=True):
+                                block_device_info=None, power_on=True):
         LOG.debug('finish_revert_migration called for instance',
-                    instance=instance)
+                  instance=instance)
         if self.session.container_defined(instance.name, instance):
             self.session.container_start(instance.name, instance)
-
diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index dddbc77..de35bd5 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
 <at>  <at>  -303,7 +303,7  <at>  <at>  def container_start(self, instance_name, instance):
 
             LOG.info(_LI('Successfully started instance %(instance)s with'
                          ' %(image)s'), {'instance': instance.name,
-                                        'image': instance.image_ref})
+                                         'image': instance.image_ref})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.name,
 <at>  <at>  -331,7 +331,7  <at>  <at>  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})
             # Stop the container
             client = self.get_session()
             (state, data) = client.container_stop(instance_name,
 <at>  <at>  -340,7 +340,7  <at>  <at>  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})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.name,
 <at>  <at>  -367,7 +367,7  <at>  <at>  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})
 
             # Container reboot
             client = self.get_session()
 <at>  <at>  -377,7 +377,7  <at>  <at>  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})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.name,
 <at>  <at>  -404,7 +404,7  <at>  <at>  def container_destroy(self, instance_name, instance):
 
             LOG.info(_LI('Destroying instance %(instance)s with'
                          ' %(image)s'), {'instance': instance.name,
-                                        'image': instance.image_ref})
+                                         'image': instance.image_ref})
 
             # Destroying container
             self.container_stop(instance_name, instance)
 <at>  <at>  -415,7 +415,7  <at>  <at>  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})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.name,
 <at>  <at>  -442,7 +442,7  <at>  <at>  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})
 
             client = self.get_session()
             (state, data) = client.container_suspend(instance_name,
 <at>  <at>  -451,7 +451,7  <at>  <at>  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})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance_name,
 <at>  <at>  -480,7 +480,7  <at>  <at>  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})
 
             client = self.get_session()
             (state, data) = client.container_resume(instance_name,
 <at>  <at>  -489,7 +489,7  <at>  <at>  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})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.name,
 <at>  <at>  -513,7 +513,7  <at>  <at>  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})
 
             client = self.get_session()
             (state, data) = client.container_init(config)
 <at>  <at>  -526,7 +526,7  <at>  <at>  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})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.name,
 <at>  <at>  -662,7 +662,7  <at>  <at>  def operation_info(self, operation_id, instance):
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.image_ref,
-                                     'reason': ex}
+                                      'reason': ex}
             LOG.error(msg)
             raise exception.NovaException(msg)
         except Exception as e:
 <at>  <at>  -682,14 +682,13  <at>  <at>  def profile_list(self):
             return client.profile_list()
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API: %(reason)s') \
-                     % {'reason': ex}
+                % {'reason': ex}
             LOG.error(msg)
             raise exception.NovaException(msg)
         except Exception as ex:
             with excutils.save_and_reraise_exception():
                 LOG.error(_LE('Error from LXD during profile_list: '
-                          '%(reason)s') % {'reason': ex})
-
+                              '%(reason)s') % {'reason': ex})
 
     def profile_defined(self, instance_name, instance):
         """Validate if the profile is available on the LXD
 <at>  <at>  -729,7 +728,8  <at>  <at>  def profile_create(self, config, instance):
                   instance=instance)
         try:
             if self.profile_defined(instance.name, instance):
-                msg = _('Profile already exists %s' % instance.name)
+                msg = _('Profile already exists %(instnce)s') % \
+                    {'instnace': instance.name}
                 raise exception.NovaException(msg)
 
             client = self.get_session()
 <at>  <at>  -754,7 +754,8  <at>  <at>  def profile_update(self, config, instance):
         LOG.debug('profile_udpate called for instance', instance=instance)
         try:
             if not self.profile_defined(instance.name, instance):
-                msg  = _('Profile not found %s' % instance.name)
+                msg = _('Profile not found %(instnace)s') % \
+                    {'instance': instance.name}
                 raise exception.NovaException(msg)
 
             client = self.get_session()
 <at>  <at>  -893,7 +894,7  <at>  <at>  def container_snapshot(self, snapshot, instance):
 
             LOG.info(_LI('Successfully snapshotted container %(instance)s with'
                          ' %(image)s'), {'instance': instance.name,
-                                        'image': instance.image_ref})
+                                         'image': instance.image_ref})
         except lxd_exceptions.APIError as ex:
             msg = _('Failed to communicate with LXD API %(instance)s:'
                     ' %(reason)s') % {'instance': instance.name,
 <at>  <at>  -979,18 +980,12  <at>  <at>  def _wait_for_snapshot(self, event_id, instance):
         :param event_id: operation id
         :param instance: nova instance object
         """
-        try:
-            client = self.get_session()
-            (state, data) = client.operation_info(event_id)
-            status_code = data['metadata']['status_code']
-
-            if status_code == 200:
-                raise loopingcall.LoopingCallDone()
-            elif status_code == 400:
-                msg = _('Snapshot failed')
-                raise exception.NovaException(msg)
-        except Exception as ex:
-            with excutils.save_and_reraise_exception():
-                LOG.error(_LE('Failed to wait for snapshot for %(instance)s: '
-                             '%(ex)s'), {'instance': instance.name, 'ex': ex},
-                              instance=instance)
+        client = self.get_session()
+        (state, data) = client.operation_info(event_id)
+        status_code = data['metadata']['status_code']
+
+        if status_code == 200:
+            raise loopingcall.LoopingCallDone()
+        elif status_code == 400:
+            msg = _('Snapshot failed')
+            raise exception.NovaException(msg)
diff --git a/nova_lxd/tests/test_config.py b/nova_lxd/tests/test_config.py
index 1ad1b4a..8d1e697 100644
--- a/nova_lxd/tests/test_config.py
+++ b/nova_lxd/tests/test_config.py
 <at>  <at>  -16,7 +16,6  <at>  <at> 
 import ddt
 import mock
 
-from nova import exception
 from nova import test
 from nova.tests.unit import fake_network
 
 <at>  <at>  -56,15 +55,15  <at>  <at>  def test_create_container(self, tag, key, expected):
     def test_create_config(self, tag, key, expected):
         instance = stubs._fake_instance()
         instance_name = 'fake_instance'
-        config = self.config._create_config(instance_name, instance)
+        config = self.config.create_config(instance_name, instance)
         self.assertEqual(config[key], expected)
 
     def test_create_network(self):
         instance = stubs._fake_instance()
         instance_name = 'fake_instance'
         network_info = fake_network.fake_get_instance_nw_info(self)
-        config = self.config._create_network(instance_name, instance,
-                                             network_info)
+        config = self.config.create_network(instance_name, instance,
+                                            network_info)
         self.assertEqual({'fake_br1': {'hwaddr': 'DE:AD:BE:EF:00:01',
                                        'nictype': 'bridged',
                                        'parent': 'fake_br1',
 <at>  <at>  -80,14 +79,7  <at>  <at>  def test_create_disk_path(self):
                                         'source': '/fake/src_path',
                                         'type': 'disk'}}, config)
 
-     <at> mock.patch('os.path.exists', mock.Mock(return_value=False))
-    def test_create_disk_path_fail(self):
-        instance = stubs._fake_instance()
-        self.assertRaises(exception.NovaException,
-                          self.config.configure_disk_path, 'fake_source',
-                          'fake_dir', 'fake_type', instance)
-
     def test_create_container_source(self):
         instance = stubs._fake_instance()
-        config = self.config._get_container_source(instance)
+        config = self.config.get_container_source(instance)
         self.assertEqual(config, {'type': 'image', 'alias': 'fake_image'})
diff --git a/nova_lxd/tests/test_driver_api.py b/nova_lxd/tests/test_driver_api.py
index fa2fc7b..9a23a3f 100644
--- a/nova_lxd/tests/test_driver_api.py
+++ b/nova_lxd/tests/test_driver_api.py
 <at>  <at>  -433,7 +433,6  <at>  <at>  def setUp(self):
         'get_all_volume_usage',
         'attach_volume',
         'detach_volume',
-        'finish_revert_migration',
         'soft_delete',
         'post_live_migration_at_source',
         'check_instance_shared_storage_local',
 <at>  <at>  -465,7 +464,6  <at>  <at>  def test_notimplemented(self, method):
 
      <at> ddt.data(
         'post_interrupted_snapshot_cleanup',
-        'post_live_migration',
         'check_instance_shared_storage_cleanup',
         'manage_image_cache',
     )
diff --git a/nova_lxd/tests/test_image.py b/nova_lxd/tests/test_image.py
index 4d3b8d7..5041827 100644
--- a/nova_lxd/tests/test_image.py
+++ b/nova_lxd/tests/test_image.py
 <at>  <at>  -74,11 +74,9  <at>  <at>  def test_image(self, tag, sucess, image_data, expected):
      <at> mock.patch.object(image.IMAGE_API, 'download')
     def test_fetch_image(self, mock_download):
         context = mock.Mock()
-        image_meta = mock.Mock()
         instance = stubs._fake_instance()
         self.assertEqual(None,
-                         self.image._fetch_image(context, image_meta,
-                                                 instance))
+                         self.image._fetch_image(context, instance))
 
      <at> mock.patch.object(os, 'stat')
      <at> mock.patch.object(json, 'dumps')
diff --git a/nova_lxd/tests/test_migrate.py b/nova_lxd/tests/test_migrate.py
index eef74eb..3bf9ceb 100644
--- a/nova_lxd/tests/test_migrate.py
+++ b/nova_lxd/tests/test_migrate.py
 <at>  <at>  -34,40 +34,3  <at>  <at>  def setUp(self):
 
         self.migrate = migrate.LXDContainerMigrate(
             fake.FakeVirtAPI())
-
-     <at> mock.patch.object(session.LXDAPISession, 'container_migrate')
-    def test_finish_migration(self, mo):
-        context = mock.Mock()
-        migration = {'source_compute': 'fake-source',
-                     'dest_compute': 'fake-dest'}
-        instance = stubs._fake_instance()
-        bdevice_info = mock.Mock()
-        disk_info = mock.Mock()
-        network_info = mock.Mock()
-        with test.nested(
-            mock.patch.object(session.LXDAPISession,
-                              'container_defined'),
-            mock.patch.object(session.LXDAPISession,
-                              'container_stop'),
-            mock.patch.object(session.LXDAPISession,
-                              'container_init'),
-        ) as (
-            container_defined,
-            container_stop,
-            container_init
-        ):
-            def side_effect(*args, **kwargs):
-                # XXX: rockstar (7 Dec 2015) - This mock is a little greedy,
-                # and hits too many interfaces. It should become more specific
-                # to the single places it needs to fully mocked. Truthiness of
-                # the mock changes in py3.
-                if args[0] == 'defined':
-                    return False
-            container_defined.side_effect = side_effect
-            self.assertEqual(None,
-                             (self.migrate.finish_migration(context,
-                                                            migration,
-                                                            instance,
-                                                            disk_info,
-                                                            network_info,
-                                                            bdevice_info)))
diff --git a/tox.ini b/tox.ini
index 7d142a4..d899b67 100644
--- a/tox.ini
+++ b/tox.ini
 <at>  <at>  -40,6 +40,6  <at>  <at>  commands = python setup.py build_sphinx
 # E123, E125 skipped as they are invalid PEP-8.
 
 show-source = True
-ignore = E123,E125,H803,H904,H405,H404
+ignore = E123,E125,H803,H904,H405,H404,H305,H306,H307
 builtins = _
 exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools/colorizer.py

From c4b3de69db11190309dd5a8f9d63b550f4e6b127 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Sat, 6 Feb 2016 22:11:46 -0500
Subject: [PATCH 13/15] Add unit tests for profiles

Add unit tests for profile API calls.

Signed-off-by: Chuck Short <chuck.short <at> canonical.com>
---
 nova_lxd/nova/virt/lxd/session.py      |  2 +-
 nova_lxd/tests/session/test_profile.py | 83 ++++++++++++++++++++++++++++++++++
 nova_lxd/tests/test_config.py          |  9 ++++
 3 files changed, 93 insertions(+), 1 deletion(-)
 create mode 100644 nova_lxd/tests/session/test_profile.py

diff --git a/nova_lxd/nova/virt/lxd/session.py b/nova_lxd/nova/virt/lxd/session.py
index de35bd5..bfdd3a7 100644
--- a/nova_lxd/nova/virt/lxd/session.py
+++ b/nova_lxd/nova/virt/lxd/session.py
 <at>  <at>  -754,7 +754,7  <at>  <at>  def profile_update(self, config, instance):
         LOG.debug('profile_udpate called for instance', instance=instance)
         try:
             if not self.profile_defined(instance.name, instance):
-                msg = _('Profile not found %(instnace)s') % \
+                msg = _('Profile not found %(instance)s') % \
                     {'instance': instance.name}
                 raise exception.NovaException(msg)
 
diff --git a/nova_lxd/tests/session/test_profile.py b/nova_lxd/tests/session/test_profile.py
new file mode 100644
index 0000000..3a1264f
--- /dev/null
+++ b/nova_lxd/tests/session/test_profile.py
 <at>  <at>  -0,0 +1,83  <at>  <at> 
+# Copyright 2015 Canonical Ltd
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+#    implied. See the License for the specific language governing
+#    permissions and limitations under the License.
+
+
+import ddt
+import mock
+
+from nova.compute import power_state
+from nova import exception
+from nova import test
+from pylxd import exceptions as lxd_exceptions
+
+from nova_lxd.nova.virt.lxd import session
+from nova_lxd.tests import fake_api
+from nova_lxd.tests import stubs
+
+
+ <at> ddt.ddt
+class SessionProfileTest(test.NoDBTestCase):
+
+    def setUp(self):
+        super(SessionProfileTest, 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()
+
+     <at> stubs.annotated_data(
+        ('empty', [], []),
+        ('valid', ['test'], ['test']),
+    )
+    def test_profile_list(self, tag, side_effect, expected):
+        self.ml.profile_list.return_value = side_effect
+        self.assertEqual(expected,
+                         self.session.profile_list())
+
+    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)
+
+    def test_profile_create(self):
+        instance = stubs._fake_instance()
+        config = mock.Mock()
+        self.ml.profile_defined.return_value = True
+        self.ml.profile_create.return_value = \
+            (200, fake_api.fake_standard_return())
+        self.assertEqual((200, fake_api.fake_standard_return()),
+                         self.session.profile_create(config,
+                                                     instance))
+        calls = [mock.call.profile_list(),
+                 mock.call.profile_create(config)]
+        self.assertEqual(calls, self.ml.method_calls)
+
+    def test_profile_delete(self):
+        instance = stubs._fake_instance()
+        config = mock.Mock()
+        self.ml.profile_defined.return_value = True
+        self.ml.profile_delete.return_value = \
+            (200, fake_api.fake_standard_return())
+        self.assertEqual(None,
+                         self.session.profile_delete(instance))
+
+    
\ No newline at end of file
diff --git a/nova_lxd/tests/test_config.py b/nova_lxd/tests/test_config.py
index 8d1e697..ebd5530 100644
--- a/nova_lxd/tests/test_config.py
+++ b/nova_lxd/tests/test_config.py
 <at>  <at>  -16,6 +16,7  <at>  <at> 
 import ddt
 import mock
 
+from nova import objects
 from nova import test
 from nova.tests.unit import fake_network
 
 <at>  <at>  -79,6 +80,14  <at>  <at>  def test_create_disk_path(self):
                                         'source': '/fake/src_path',
                                         'type': 'disk'}}, config)
 
+    def test_config_instance_options(self):
+        instance = stubs._fake_instance()
+        config = {}
+        container_config = self.config.config_instance_options(config,
+                                instance)
+        self.assertEqual({'boot.autostart': 'True'}, container_config)
+
+
     def test_create_container_source(self):
         instance = stubs._fake_instance()
         config = self.config.get_container_source(instance)

From 303d2bd0f6f958aadf6c0eae3eaae9e9a93253ae Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Mon, 8 Feb 2016 09:57:46 -0500
Subject: [PATCH 14/15] Add more unit tests

Signed-off-by: Chuck Short <chuck.short <at> canonical.com>
---
 nova_lxd/nova/virt/lxd/migrate.py      |  3 --
 nova_lxd/tests/fake_api.py             | 35 ++++++++++++++-----
 nova_lxd/tests/session/test_profile.py |  1 -
 nova_lxd/tests/stubs.py                |  2 ++
 nova_lxd/tests/test_config.py          | 22 ++++++++++++
 nova_lxd/tests/test_migrate.py         | 61 +++++++++++++++++++++++++++++++---
 6 files changed, 108 insertions(+), 16 deletions(-)

diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
index fbe19ee..28c9aa3 100644
--- a/nova_lxd/nova/virt/lxd/migrate.py
+++ b/nova_lxd/nova/virt/lxd/migrate.py
 <at>  <at>  -98,9 +98,6  <at>  <at>  def confirm_migration(self, migration, instance, network_info):
             self.session.container_destroy(instance.name,
                                            instance)
             self.operations.unplug_vifs(instance, network_info)
-            container_dir = self.container_dir.get_instance_dir(instance.name)
-            if os.path.exists(container_dir):
-                shutil.rmtree(container_dir)
         except Exception as ex:
             with excutils.save_and_reraise_exception():
                 LOG.exception(_LE('Confirm migration failed for %(instance)s: '
diff --git a/nova_lxd/tests/fake_api.py b/nova_lxd/tests/fake_api.py
index ae7c0ea..b9078e6 100644
--- a/nova_lxd/tests/fake_api.py
+++ b/nova_lxd/tests/fake_api.py
 <at>  <at>  -144,15 +144,29  <at>  <at>  def fake_container_log():
 
 def fake_container_migrate():
     return {
-        "type": "sync",
-        "status": "Success",
-        "status_code": 200,
-        "operation": "/1.0/operations/1234",
+        "type": "async",
+        "status": "Operation created",
+        "status_code": 100,
         "metadata": {
-            "control": "fake_control",
-            "criu": "fake_criu",
-            "fs": "fake_fs",
-        }
+            "id": "dbd9f22c-6da5-4066-8fca-c02f09f76738",
+            "class": "websocket",
+            "created_at": "2016-02-07T09:20:53.127321875-05:00",
+            "updated_at": "2016-02-07T09:20:53.127321875-05:00",
+            "status": "Running",
+            "status_code": 103,
+            "resources": {
+                "containers": [
+                    "/1.0/containers/instance-00000010"
+                    ]
+            },
+            "metadata": {
+                "control": "5ffecc8e6cf95e01f4bae7dcef6e87711e7c119e42ed7538e3da583ed91927da",
+                "fs": "21f09995fed96a8abae91802de4b794a35789d2a813735c9874decfe591134c4"
+            },
+            "may_cancel": false,
+            "err": ""
+        },
+        "operation": "/1.0/operations/dbd9f22c-6da5-4066-8fca-c02f09f76738"
     }
 
 
 <at>  <at>  -381,3 +395,8  <at>  <at>  def fake_container_info():
                      'address': "172.16.15.30",
                      'host_veth': "vethGMDIY9"}]},
     }
+
+def fake_container_migrate():
+    return {
+
+    }
diff --git a/nova_lxd/tests/session/test_profile.py b/nova_lxd/tests/session/test_profile.py
index 3a1264f..848be25 100644
--- a/nova_lxd/tests/session/test_profile.py
+++ b/nova_lxd/tests/session/test_profile.py
 <at>  <at>  -80,4 +80,3  <at>  <at>  def test_profile_delete(self):
         self.assertEqual(None,
                          self.session.profile_delete(instance))
 
-    
\ No newline at end of file
diff --git a/nova_lxd/tests/stubs.py b/nova_lxd/tests/stubs.py
index c66c061..3edfd11 100644
--- a/nova_lxd/tests/stubs.py
+++ b/nova_lxd/tests/stubs.py
 <at>  <at>  -108,3 +108,5  <at>  <at>  def _fake_instance():
     }
     return fake_instance.fake_instance_obj(
         ctxt, **_instance_values)
+
+
diff --git a/nova_lxd/tests/test_config.py b/nova_lxd/tests/test_config.py
index ebd5530..581e930 100644
--- a/nova_lxd/tests/test_config.py
+++ b/nova_lxd/tests/test_config.py
 <at>  <at>  -23,6 +23,7  <at>  <at> 
 from nova_lxd.nova.virt.lxd import config
 from nova_lxd.nova.virt.lxd import utils as container_dir
 from nova_lxd.tests import stubs
+from nova_lxd.tests import fake_api
 
 
  <at> ddt.ddt
 <at>  <at>  -92,3 +93,24  <at>  <at>  def test_create_container_source(self):
         instance = stubs._fake_instance()
         config = self.config.get_container_source(instance)
         self.assertEqual(config, {'type': 'image', 'alias': 'fake_image'})
+
+    def test_container_root(self):
+        instance = stubs._fake_instance()
+        config = self.config.configure_container_root(instance)
+        self.assertEqual({'root': {'path': '/',
+                                   'type': 'disk',
+                                   'size': '10GB'}}, config)
+
+    def test_container_nested_container(self):
+        instance = stubs._fake_instance()
+        instance.flavor.extra_specs = {'lxd_nested_allowed': True}
+        config = self.config.config_instance_options({}, instance)
+        self.assertEqual({'security.nesting': 'True',
+                          'boot.autostart': 'True'}, config)
+
+    def test_container_privileged_container(self):
+        instance = stubs._fake_instance()
+        instance.flavor.extra_specs = {'lxd_privileged_allowed': True}
+        config = self.config.config_instance_options({}, instance)
+        self.assertEqual({'security.privileged': 'True',
+                          'boot.autostart': 'True'}, config)
diff --git a/nova_lxd/tests/test_migrate.py b/nova_lxd/tests/test_migrate.py
index 3bf9ceb..18145a1 100644
--- a/nova_lxd/tests/test_migrate.py
+++ b/nova_lxd/tests/test_migrate.py
 <at>  <at>  -13,24 +13,77  <at>  <at> 
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import os
+import shutil
+
 import mock
 
 from nova import test
 from nova.virt import fake
 
+from oslo_config import cfg
+from oslo_utils import fileutils
+
+from nova_lxd.nova.virt.lxd import config
 from nova_lxd.nova.virt.lxd import migrate
+from nova_lxd.nova.virt.lxd import operations
 from nova_lxd.nova.virt.lxd import session
+from nova_lxd.nova.virt.lxd import utils as container_dir
 from nova_lxd.tests import stubs
 
+CONF = cfg.CONF
+CONF.import_opt('my_ip', 'nova.netconf')
+
 
- <at> mock.patch.object(migrate, 'CONF', stubs.MockConf())
- <at> mock.patch.object(session, 'CONF', stubs.MockConf())
 class LXDTestContainerMigrate(test.NoDBTestCase):
 
-     <at> mock.patch.object(migrate, 'CONF', stubs.MockConf())
-     <at> mock.patch.object(session, 'CONF', stubs.MockConf())
     def setUp(self):
         super(LXDTestContainerMigrate, self).setUp()
 
         self.migrate = migrate.LXDContainerMigrate(
             fake.FakeVirtAPI())
+
+    def test_migrate_disk_power_off_resize(self):
+        self.flags(my_ip='fakeip')
+        instance = stubs._fake_instance()
+        network_info = mock.Mock()
+        flavor = mock.Mock()
+        context = mock.Mock()
+        dest = 'fakeip'
+
+        with test.nested(
+            mock.patch.object(session.LXDAPISession, 'container_defined'),
+            mock.patch.object(config.LXDContainerConfig, 'create_profile'),
+            mock.patch.object(session.LXDAPISession, 'profile_update')
+        ) as (
+            mock_container_defined,
+            mock_create_profile,
+            mock_profile_update
+        ):
+            self.assertEqual('',
+                self.migrate.migrate_disk_and_power_off(
+                    context, instance, dest, flavor, network_info))
+            mock_container_defined.assert_called_once_with(instance.name,
+                                                           instance)
+            mock_create_profile.assert_called_once_with(instance, network_info)
+
+    def test_confirm_migration(self):
+        migration = mock.Mock()
+        instance = stubs._fake_instance()
+        network_info = mock.Mock()
+
+        with test.nested(
+            mock.patch.object(session.LXDAPISession, 'container_defined'),
+            mock.patch.object(session.LXDAPISession, 'profile_delete'),
+            mock.patch.object(session.LXDAPISession, 'container_destroy'),
+            mock.patch.object(operations.LXDContainerOperations, 'unplug_vifs'),
+        ) as (
+            mock_container_defined,
+            mock_profile_delete,
+            mock_container_destroy,
+            mock_unplug_vifs):
+                self.assertEqual(None,
+                    self.migrate.confirm_migration(migration, instance, network_info))
+                mock_container_defined.assert_called_once_with(instance.name, instance)
+                mock_profile_delete.assert_called_once_with(instance)
+                mock_unplug_vifs.assert_called_once_with(instance, network_info)

From e53a7f1d62c61448269b3f8dfee4aeb8e3b51e55 Mon Sep 17 00:00:00 2001
From: Chuck Short <chuck.short <at> canonical.com>
Date: Mon, 8 Feb 2016 10:18:09 -0500
Subject: [PATCH 15/15] Fix pep8

Signed-off-by: Chuck Short <chuck.short <at> canonical.com>
---
 nova_lxd/nova/virt/lxd/migrate.py      |  1 -
 nova_lxd/tests/fake_api.py             | 13 ++++--------
 nova_lxd/tests/session/test_profile.py |  3 ---
 nova_lxd/tests/stubs.py                |  2 --
 nova_lxd/tests/test_config.py          |  5 +----
 nova_lxd/tests/test_migrate.py         | 38 ++++++++++++++++++----------------
 6 files changed, 25 insertions(+), 37 deletions(-)

diff --git a/nova_lxd/nova/virt/lxd/migrate.py b/nova_lxd/nova/virt/lxd/migrate.py
index 28c9aa3..653b64b 100644
--- a/nova_lxd/nova/virt/lxd/migrate.py
+++ b/nova_lxd/nova/virt/lxd/migrate.py
 <at>  <at>  -15,7 +15,6  <at>  <at> 
 
 import os
 import pprint
-import shutil
 
 from nova import exception
 from nova import i18n
diff --git a/nova_lxd/tests/fake_api.py b/nova_lxd/tests/fake_api.py
index b9078e6..3ead0dd 100644
--- a/nova_lxd/tests/fake_api.py
+++ b/nova_lxd/tests/fake_api.py
 <at>  <at>  -157,13 +157,13  <at>  <at>  def fake_container_migrate():
             "resources": {
                 "containers": [
                     "/1.0/containers/instance-00000010"
-                    ]
+                ]
             },
             "metadata": {
-                "control": "5ffecc8e6cf95e01f4bae7dcef6e87711e7c119e42ed7538e3da583ed91927da",
-                "fs": "21f09995fed96a8abae91802de4b794a35789d2a813735c9874decfe591134c4"
+                "control": "fake_control",
+                "fs": "fake_fs"
             },
-            "may_cancel": false,
+            "may_cancel": 'false',
             "err": ""
         },
         "operation": "/1.0/operations/dbd9f22c-6da5-4066-8fca-c02f09f76738"
 <at>  <at>  -395,8 +395,3  <at>  <at>  def fake_container_info():
                      'address': "172.16.15.30",
                      'host_veth': "vethGMDIY9"}]},
     }
-
-def fake_container_migrate():
-    return {
-
-    }
diff --git a/nova_lxd/tests/session/test_profile.py b/nova_lxd/tests/session/test_profile.py
index 848be25..9698a3f 100644
--- a/nova_lxd/tests/session/test_profile.py
+++ b/nova_lxd/tests/session/test_profile.py
 <at>  <at>  -17,7 +17,6  <at>  <at> 
 import ddt
 import mock
 
-from nova.compute import power_state
 from nova import exception
 from nova import test
 from pylxd import exceptions as lxd_exceptions
 <at>  <at>  -73,10 +72,8  <at>  <at>  def test_profile_create(self):
 
     def test_profile_delete(self):
         instance = stubs._fake_instance()
-        config = mock.Mock()
         self.ml.profile_defined.return_value = True
         self.ml.profile_delete.return_value = \
             (200, fake_api.fake_standard_return())
         self.assertEqual(None,
                          self.session.profile_delete(instance))
-
diff --git a/nova_lxd/tests/stubs.py b/nova_lxd/tests/stubs.py
index 3edfd11..c66c061 100644
--- a/nova_lxd/tests/stubs.py
+++ b/nova_lxd/tests/stubs.py
 <at>  <at>  -108,5 +108,3  <at>  <at>  def _fake_instance():
     }
     return fake_instance.fake_instance_obj(
         ctxt, **_instance_values)
-
-
diff --git a/nova_lxd/tests/test_config.py b/nova_lxd/tests/test_config.py
index 581e930..106d72c 100644
--- a/nova_lxd/tests/test_config.py
+++ b/nova_lxd/tests/test_config.py
 <at>  <at>  -16,14 +16,12  <at>  <at> 
 import ddt
 import mock
 
-from nova import objects
 from nova import test
 from nova.tests.unit import fake_network
 
 from nova_lxd.nova.virt.lxd import config
 from nova_lxd.nova.virt.lxd import utils as container_dir
 from nova_lxd.tests import stubs
-from nova_lxd.tests import fake_api
 
 
  <at> ddt.ddt
 <at>  <at>  -85,10 +83,9  <at>  <at>  def test_config_instance_options(self):
         instance = stubs._fake_instance()
         config = {}
         container_config = self.config.config_instance_options(config,
-                                instance)
+                                                               instance)
         self.assertEqual({'boot.autostart': 'True'}, container_config)
 
-
     def test_create_container_source(self):
         instance = stubs._fake_instance()
         config = self.config.get_container_source(instance)
diff --git a/nova_lxd/tests/test_migrate.py b/nova_lxd/tests/test_migrate.py
index 18145a1..016baef 100644
--- a/nova_lxd/tests/test_migrate.py
+++ b/nova_lxd/tests/test_migrate.py
 <at>  <at>  -13,22 +13,17  <at>  <at> 
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import os
-import shutil
-
 import mock
 
 from nova import test
 from nova.virt import fake
 
 from oslo_config import cfg
-from oslo_utils import fileutils
 
 from nova_lxd.nova.virt.lxd import config
 from nova_lxd.nova.virt.lxd import migrate
 from nova_lxd.nova.virt.lxd import operations
 from nova_lxd.nova.virt.lxd import session
-from nova_lxd.nova.virt.lxd import utils as container_dir
 from nova_lxd.tests import stubs
 
 CONF = cfg.CONF
 <at>  <at>  -61,11 +56,13  <at>  <at>  def test_migrate_disk_power_off_resize(self):
             mock_profile_update
         ):
             self.assertEqual('',
-                self.migrate.migrate_disk_and_power_off(
-                    context, instance, dest, flavor, network_info))
+                             self.migrate.migrate_disk_and_power_off(
+                                 context, instance, dest, flavor,
+                                 network_info))
             mock_container_defined.assert_called_once_with(instance.name,
                                                            instance)
-            mock_create_profile.assert_called_once_with(instance, network_info)
+            mock_create_profile.assert_called_once_with(instance,
+                                                        network_info)
 
     def test_confirm_migration(self):
         migration = mock.Mock()
 <at>  <at>  -76,14 +73,19  <at>  <at>  def test_confirm_migration(self):
             mock.patch.object(session.LXDAPISession, 'container_defined'),
             mock.patch.object(session.LXDAPISession, 'profile_delete'),
             mock.patch.object(session.LXDAPISession, 'container_destroy'),
-            mock.patch.object(operations.LXDContainerOperations, 'unplug_vifs'),
+            mock.patch.object(operations.LXDContainerOperations,
+                              'unplug_vifs'),
         ) as (
-            mock_container_defined,
-            mock_profile_delete,
-            mock_container_destroy,
-            mock_unplug_vifs):
-                self.assertEqual(None,
-                    self.migrate.confirm_migration(migration, instance, network_info))
-                mock_container_defined.assert_called_once_with(instance.name, instance)
-                mock_profile_delete.assert_called_once_with(instance)
-                mock_unplug_vifs.assert_called_once_with(instance, network_info)
+                mock_container_defined,
+                mock_profile_delete,
+                mock_container_destroy,
+                mock_unplug_vifs):
+            self.assertEqual(None,
+                             self.migrate.confirm_migration(migration,
+                                                            instance,
+                                                            network_info))
+            mock_container_defined.assert_called_once_with(instance.name,
+                                                           instance)
+            mock_profile_delete.assert_called_once_with(instance)
+            mock_unplug_vifs.assert_called_once_with(instance,
+                                                     network_info)
_______________________________________________
lxc-devel mailing list
lxc-devel <at> lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel
Teemu Grönqvist | 8 Feb 10:00 2016
Picon

Add support for /proc/swaps

Hello,

I was asked to sign off this. Sign off is below.

Just signed on the mailing list so unfortunately I can't answer to the old thread.

----------------------------------------------------------

Built overhttps://github.com/tssge/lxcfs/commit/50b75e3

Example Output:

[root at lxc-dev <http://lists.linuxcontainers.org/listinfo/lxc-devel>  ~]# lxc-attach -n
ubuntuwily --  /bin/cat /proc/swaps
Filename                                Type            Size    Used    Priority
none                                    virtual         1048572 1048572 0

Signed-off-by: Teemu Grönqvist <teemu.gronqvist <at> net9.fi>
Signed-off-by: Nehal J Wani <nehaljw.kkd1 at gmail.com 
<http://lists.linuxcontainers.org/listinfo/lxc-devel>>
---
  lxcfs.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
  1 file changed, 116 insertions(+), 2 deletions(-)

diff --git a/lxcfs.c b/lxcfs.c
index a561882..9c52862 100644
--- a/lxcfs.c
+++ b/lxcfs.c
 <at>  <at>  -43,6 +43,7  <at>  <at>  enum {
  	LXC_TYPE_PROC_UPTIME,
  	LXC_TYPE_PROC_STAT,
  	LXC_TYPE_PROC_DISKSTATS,
+	LXC_TYPE_PROC_SWAPS,
  };

  struct file_info {
 <at>  <at>  -2394,6 +2395,113  <at>  <at>  err:
  	return rv;
  }

+static int proc_swaps_read(char *buf, size_t size, off_t offset,
+		struct fuse_file_info *fi)
+{
+	struct fuse_context *fc = fuse_get_context();
+	struct file_info *d = (struct file_info *)fi->fh;
+	char *cg;
+	char *memswlimit_str = NULL, *memlimit_str = NULL, *memusage_str = NULL, *memswusage_str = NULL,
+             *memswlimit_default_str = NULL, *memswusage_default_str = NULL;
+	unsigned long memswlimit = 0, memlimit = 0, memusage = 0, memswusage = 0, swap_total = 0, swap_free = 0;
+	size_t total_len = 0, rv = 0, linelen = 0;
+	char *cache = d->buf;
+	char *line = NULL;
+	FILE *f = NULL;
+
+	if (offset) {
+		if (offset > d->size)
+			return -EINVAL;
+		if (!d->cached)
+			return 0;
+		int left = d->size - offset;
+		total_len = left > size ? size: left;
+		memcpy(buf, cache + offset, total_len);
+		return total_len;
+	}
+
+	cg = get_pid_cgroup(fc->pid, "memory");
+
+	if (!cg)
+		return read_file("/proc/swaps", buf, size, d);
+
+	if (!cgfs_get_value("memory", cg, "memory.limit_in_bytes", &memlimit_str))
+		goto err;
+
+	if (!cgfs_get_value("memory", cg, "memory.usage_in_bytes", &memusage_str))
+		goto err;
+
+	memlimit = strtoul(memlimit_str, NULL, 10);
+	memusage = strtoul(memusage_str, NULL, 10);
+
+	if (cgfs_get_value("memory", cg, "memory.memsw.usage_in_bytes", &memswusage_str) &&
+	    cgfs_get_value("memory", cg, "memory.memsw.limit_in_bytes", &memswlimit_str)) {
+
+                /* If swap accounting is turned on, then default value is assumed to be that of cgroup / */
+                if (!cgfs_get_value("memory", "/", "memory.memsw.limit_in_bytes", &memswlimit_default_str))
+                    goto err;
+                if (!cgfs_get_value("memory", "/", "memory.memsw.usage_in_bytes", &memswusage_default_str))
+                    goto err;
+
+		memswlimit = strtoul(memswlimit_str, NULL, 10);
+		memswusage = strtoul(memswusage_str, NULL, 10);
+
+                if (!strcmp(memswlimit_str, memswlimit_default_str))
+                    memswlimit = 0;
+                if (!strcmp(memswusage_str, memswusage_default_str))
+                    memswusage = 0;
+
+		swap_total = (memswlimit - memlimit) / 1024;
+		swap_free = (memswusage - memusage) / 1024;
+	}
+
+	total_len = snprintf(d->buf, d->size, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
+
+	/* When no mem + swap limit is specified or swapaccount=0*/
+	if (!memswlimit) {
+		f = fopen("/proc/meminfo", "r");
+		if (!f)
+			goto err;
+
+		while (getline(&line, &linelen, f) != -1) {
+			if (startswith(line, "SwapTotal:")) {
+				sscanf(line, "SwapTotal:      %8lu kB", &swap_total);
+			} else if (startswith(line, "SwapFree:")) {
+				sscanf(line, "SwapFree:      %8lu kB", &swap_free);
+			}
+		}
+	}
+
+	if (swap_total > 0) {
+		total_len += snprintf(d->buf + total_len, d->size,
+				 "none%*svirtual\t\t%lu\t%lu\t0\n", 36, " ",
+				 swap_total, swap_free);
+	}
+
+	if (total_len < 0) {
+		perror("Error writing to cache");
+		rv = 0;
+		goto err;
+	}
+
+	d->cached = 1;
+	d->size = (int)total_len;
+
+	if (total_len > size) total_len = size;
+	memcpy(buf, d->buf, total_len);
+	rv = total_len;
+
+err:
+	free(cg);
+	free(memswlimit_str);
+	free(memlimit_str);
+	free(memusage_str);
+	free(memswusage_str);
+	free(memswusage_default_str);
+	free(memswlimit_default_str);
+	return rv;
+}
+
  /*
   * Read the cpuset.cpus for cg
   * Return the answer in a newly allocated string which must be freed
 <at>  <at>  -2956,7 +3064,8  <at>  <at>  static int proc_getattr(const char *path, struct stat *sb)
  			strcmp(path, "/proc/cpuinfo") == 0 ||
  			strcmp(path, "/proc/uptime") == 0 ||
  			strcmp(path, "/proc/stat") == 0 ||
-			strcmp(path, "/proc/diskstats") == 0) {
+			strcmp(path, "/proc/diskstats") == 0 ||
+			strcmp(path, "/proc/swaps") == 0) {
  		sb->st_size = 0;
  		sb->st_mode = S_IFREG | 00444;
  		sb->st_nlink = 1;
 <at>  <at>  -2973,7 +3082,8  <at>  <at>  static int proc_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off
  				filler(buf, "meminfo", NULL, 0) != 0 ||
  				filler(buf, "stat", NULL, 0) != 0 ||
  				filler(buf, "uptime", NULL, 0) != 0 ||
-				filler(buf, "diskstats", NULL, 0) != 0)
+				filler(buf, "diskstats", NULL, 0) != 0 ||
+				filler(buf, "swaps", NULL, 0) != 0)
  		return -EINVAL;
  	return 0;
  }
 <at>  <at>  -2993,6 +3103,8  <at>  <at>  static int proc_open(const char *path, struct fuse_file_info *fi)
  		type = LXC_TYPE_PROC_STAT;
  	else if (strcmp(path, "/proc/diskstats") == 0)
  		type = LXC_TYPE_PROC_DISKSTATS;
+	else if (strcmp(path, "/proc/swaps") == 0)
+		type = LXC_TYPE_PROC_SWAPS;
  	if (type == -1)
  		return -ENOENT;

 <at>  <at>  -3039,6 +3151,8  <at>  <at>  static int proc_read(const char *path, char *buf, size_t size, off_t offset,
  		return proc_stat_read(buf, size, offset, fi);
  	case LXC_TYPE_PROC_DISKSTATS:
  		return proc_diskstats_read(buf, size, offset, fi);
+	case LXC_TYPE_PROC_SWAPS:
+		return proc_swaps_read(buf, size, offset, fi);
  	default:
  		return -EINVAL;
  	}
--

-- 
2.5.0

_______________________________________________
lxc-devel mailing list
lxc-devel <at> lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel
tenforward on Github | 8 Feb 09:11 2016

[linuxcontainers.org/master] Add Japanese release annouoncement of LXCFS 0.18

Attachment: text/x-mailbox, 503 bytes
From ad60bd8860d6c46c7b155221d46898d1e15f6779 Mon Sep 17 00:00:00 2001
From: KATOH Yasufumi <karma <at> jazz.email.ne.jp>
Date: Mon, 8 Feb 2016 17:09:21 +0900
Subject: [PATCH] Add Japanese release annouoncement of LXCFS 0.18

Signed-off-by: KATOH Yasufumi <karma <at> jazz.email.ne.jp>
---
 content/lxcfs/news.ja.md | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/content/lxcfs/news.ja.md b/content/lxcfs/news.ja.md
index 5cc8657..e64df3a 100644
--- a/content/lxcfs/news.ja.md
+++ b/content/lxcfs/news.ja.md
 <at>  <at>  -1,5 +1,18  <at>  <at> 
 # News

+
+## LXCFS 0.18 リリースのお知らせ <!-- LXCFS 0.18 release announcement --><span
class="text-muted">2016 年 2 月 4 日<!-- 4th of February 2016 --></span>
+
+ * ほとんどの場合で lxcfs
の再起動がサポートされました。ほとんどの機能をライブラリに移動させたためです。このライブラリは
SIGUSR1 でリロードされます。
+   <!-- Support restarting lxcfs in most cases, by moving most functionality
+        into a library which is reloaded on SIGUSR1 -->
+
+### ダウンロード <!-- Downloads -->
+<!--
+The release tarballs can be found on our [download page](/lxcfs/downloads).
+-->
+このリリースの tarball は [ダウンロードページ](/lxcfs/downloads) から取得できます。
+
 ## LXCFS 0.17 リリースのお知らせ <!-- LXCFS 0.17 release announcement --><span
class="text-muted">2016 年 1 月 26 日 <!-- 8th of January 2016 --></span>

  * PAM モジュールを追加しました <!-- Add a PAM module -->
_______________________________________________
lxc-devel mailing list
lxc-devel <at> lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel
hallyn on Github | 8 Feb 08:14 2016

[lxc/master] apparmor: don't fail if current aa label is given

Attachment: text/x-mailbox, 1168 bytes
From e03f2119191b77674bd03bc8b3e707b967447e89 Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge.hallyn <at> ubuntu.com>
Date: Sun, 7 Feb 2016 23:06:10 -0800
Subject: [PATCH] apparmor: don't fail if current aa label is given

Ideally a container configuration will specify 'unchanged' if
it wants the container to use the current (parent) profile.  But
lxd passes its current label.  Support that too.

Note that if/when stackable profiles exist, this behavior may
or may not be what we want.  But the code to deal with aa
stacking will need some changes anyway so this is ok.

With this patch, I can create nested containers inside a
lxd xenial container both using

lxc launch x2

and unprivileged

lxc-start -n x2

Signed-off-by: Serge Hallyn <serge.hallyn <at> ubuntu.com>
---
 src/lxc/lsm/apparmor.c | 34 +++++++++++++++-------------------
 1 file changed, 15 insertions(+), 19 deletions(-)

diff --git a/src/lxc/lsm/apparmor.c b/src/lxc/lsm/apparmor.c
index 9d81224..64b7f4f 100644
--- a/src/lxc/lsm/apparmor.c
+++ b/src/lxc/lsm/apparmor.c
 <at>  <at>  -146,18 +146,6  <at>  <at>  static bool aa_stacking_supported(void) {
 	return false;
 }

-/* are we in a confined container? */
-static bool in_aa_confined_container(void) {
-	char *p = apparmor_process_label_get(getpid());
-	bool ret = false;
-	if (p && strcmp(p, "/usr/bin/lxc-start") != 0 && strcmp(p, "unconfined") != 0) {
-		INFO("Already apparmor-confined under %s", p);
-		ret = true;
-	}
-	free(p);
-	return ret;
-}
-
 /*
  * apparmor_process_label_set: Set AppArmor process profile
  *
 <at>  <at>  -174,6 +162,7  <at>  <at>  static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf
 				      int use_default, int on_exec)
 {
 	const char *label = inlabel ? inlabel : conf->lsm_aa_profile;
+	char *curlabel;

 	if (!aa_enabled)
 		return 0;
 <at>  <at>  -184,17 +173,24  <at>  <at>  static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf
 		return 0;
 	}

-	/*
-	 * If we are already confined and no profile was requested,
-	 * then default to unchanged
-	 */
-	if (in_aa_confined_container() && !aa_stacking_supported()) {
-		if (label) {
+	curlabel = apparmor_process_label_get(getpid());
+	if (!aa_stacking_supported() && curlabel) {
+		// we're already confined, and stacking isn't supported
+
+		if (!label || strcmp(curlabel, label) == 0) {
+			// no change requested
+			free(curlabel);
+			return 0;
+		}
+
+		if (strcmp(curlabel, "/usr/bin/lxc-start") != 0 &&
+				strcmp(label, AA_UNCHANGED) != 0) {
 			ERROR("already apparmor confined, but new label requested.");
+			free(curlabel);
 			return -1;
 		}
-		return 0;
 	}
+	free(curlabel);

 	if (!label) {
 		if (use_default)
_______________________________________________
lxc-devel mailing list
lxc-devel <at> lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel
Johannes Kastl | 7 Feb 19:01 2016
Picon

Packaging lxc 1.0.x for CentOS 7


Hi everyone,

as I recently acquired some machines running CentOS, I thought I
would build my lxc packages
(https://build.opensuse.org/project/monitor/home:ojkastl_buildservice:
LXC_Vanilla_stable-1.0)
also for CentOS, to see if my spec modifications would work on CentOS.

Works. But after installing I was wondering why there was no network
in the containers at all. And I think on openSUSE the network
(virbr0, lxcbr0 or similar) worked out of the box.

I have not gotten around to doing all the tests I can think of
(compiling directly on CentOS, installing a fresh openSUSE, ...). So
please excuse me asking before doing all those tests.

Should networking work with lxc 1.0.x on CentOS 7 after generating
an rpm?

Thanks in advance!

Johannes

P.S.: I also have not gotten time to try to get my spec
modifications upstream, sorry!
GitHub | 5 Feb 21:49 2016

[lxc/lxc] 740fe4: fix typo

  Branch: refs/heads/master
  Home:   https://github.com/lxc/lxc
  Commit: 740fe426b78ab4967ee5d3b2fe162b0664818091
      https://github.com/lxc/lxc/commit/740fe426b78ab4967ee5d3b2fe162b0664818091
  Author: Katze <binary@...>
  Date:   2016-02-05 (Fri, 05 Feb 2016)

  Changed paths:
    M src/lxc/lxccontainer.c

  Log Message:
  -----------
  fix typo

Signed-off-by: benaryorg <binary@...>

  Commit: e8f8436cc123707d49a8477702c9f58300e6ac02
      https://github.com/lxc/lxc/commit/e8f8436cc123707d49a8477702c9f58300e6ac02
  Author: Stéphane Graber <stgraber@...>
  Date:   2016-02-05 (Fri, 05 Feb 2016)

  Changed paths:
    M src/lxc/lxccontainer.c

  Log Message:
  -----------
  Merge pull request #805 from benaryorg/patch-1

fix typo

Compare: https://github.com/lxc/lxc/compare/c3d25c16ef3d...e8f8436cc123
_______________________________________________
lxc-devel mailing list
lxc-devel <at> lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel
benaryorg on Github | 5 Feb 18:54 2016

[lxc/master] fix typo

Attachment: text/x-mailbox, 406 bytes
From 86d4136ca48426dd3b28a5843bcfddabfb4fde37 Mon Sep 17 00:00:00 2001
From: Katze <binary <at> benary.org>
Date: Fri, 5 Feb 2016 18:53:59 +0100
Subject: [PATCH] fix typo

---
 src/lxc/lxccontainer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 402b96f..bb34bcd 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
 <at>  <at>  -173,7 +173,7  <at>  <at>  static int create_partial(struct lxc_container *c)
 		return -1;
 	}
 	if ((fd=open(path, O_RDWR | O_CREAT | O_EXCL, 0755)) < 0) {
-		SYSERROR("Erorr creating partial file");
+		SYSERROR("Error creating partial file");
 		return -1;
 	}
 	lk.l_type = F_WRLCK;
_______________________________________________
lxc-devel mailing list
lxc-devel <at> lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Gmane