The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/pylxd/pull/179

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
If a connection to LXD is a local connection, it should not be used to migrate, because it won't have a routable connection.

Originally, I had the idea that we could iterate through all the addresses in `metadata.environment.addresses` until we found a valid one, and while that made me laugh at the stupidity and possible genius of the hack, I think it's better to explicitly put the burden on the user to have a routable connection.
From c943a07b79d42aa72574a9c1c4c70bbce3441817 Mon Sep 17 00:00:00 2001
From: Paul Hummer <paul.hum...@canonical.com>
Date: Fri, 16 Sep 2016 09:17:33 -0600
Subject: [PATCH 1/2] Don't allow local connection clients to attempt a
 migration.

Fixes #162
---
 pylxd/models/container.py            |  3 +++
 pylxd/tests/models/test_container.py | 17 +++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/pylxd/models/container.py b/pylxd/models/container.py
index f7ef5d3..8acc243 100644
--- a/pylxd/models/container.py
+++ b/pylxd/models/container.py
@@ -231,6 +231,9 @@ def migrate(self, new_client, wait=False):
         first or criu must be installed on the source and destination
         machines.
         """
+        if self.api._api_endpoint.startswith('http+unix'):
+            raise ValueError('Cannot migrate from a local client connection')
+
         self.sync()  # Make sure the object isn't stale
         response = self.api.post(json={'migration': True})
         operation = self.client.operations.get(response.json()['operation'])
diff --git a/pylxd/tests/models/test_container.py 
b/pylxd/tests/models/test_container.py
index e2044a5..1cb12c0 100644
--- a/pylxd/tests/models/test_container.py
+++ b/pylxd/tests/models/test_container.py
@@ -191,6 +191,23 @@ def test_migrate(self):
         self.assertEqual('an-container', an_migrated_container.name)
         self.assertEqual(client2, an_migrated_container.client)
 
+    @mock.patch('pylxd.client._APINode.get')
+    def test_migrate_local_client(self, get):
+        """Migration from local clients is not supported."""
+        # Mock out the _APINode for the local instance.
+        response = mock.Mock()
+        response.json.return_value = {'metadata': {'fake': 'response'}}
+        response.status_code = 200
+        get.return_value = response
+
+        from pylxd.client import Client
+
+        client2 = Client(endpoint='http+unix://pylxd2.test')
+        an_container = models.Container(
+            client2, name='an-container')
+
+        self.assertRaises(ValueError, an_container.migrate, self.client)
+
     def test_publish(self):
         """Containers can be published."""
         self.add_rule({

From 85095e8374f0be8acdd4f600fb3eed375a7be0ff Mon Sep 17 00:00:00 2001
From: Paul Hummer <paul.hum...@canonical.com>
Date: Fri, 16 Sep 2016 09:37:46 -0600
Subject: [PATCH 2/2] Update _APINode to have a cleaner interface.

Stop reaching into private attributes.
---
 pylxd/client.py           | 17 ++++++++++++-----
 pylxd/models/container.py |  2 +-
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/pylxd/client.py b/pylxd/client.py
index e18028c..675e4a2 100644
--- a/pylxd/client.py
+++ b/pylxd/client.py
@@ -75,6 +75,14 @@ def _assert_response(self, response, 
allowed_status_codes=(200,)):
                 # Missing 'type' in response
                 raise exceptions.LXDAPIException(response)
 
+    @property
+    def scheme(self):
+        return parse.urlparse(self.api._api_endpoint).scheme
+
+    @property
+    def netloc(self):
+        return parse.urlparse(self.api._api_endpoint).netloc
+
     def get(self, *args, **kwargs):
         """Perform an HTTP GET."""
         response = self.session.get(self._api_endpoint, *args, **kwargs)
@@ -213,16 +221,15 @@ def authenticate(self, password):
 
     @property
     def websocket_url(self):
-        parsed = parse.urlparse(self.api._api_endpoint)
-        if parsed.scheme in ('http', 'https'):
-            host = parsed.netloc
-            if parsed.scheme == 'http':
+        if self.api.scheme in ('http', 'https'):
+            host = self.api.netloc
+            if self.api.scheme == 'http':
                 scheme = 'ws'
             else:
                 scheme = 'wss'
         else:
             scheme = 'ws+unix'
-            host = parse.unquote(parsed.netloc)
+            host = parse.unquote(self.api.netloc)
         url = parse.urlunparse((scheme, host, '', '', '', ''))
         return url
 
diff --git a/pylxd/models/container.py b/pylxd/models/container.py
index 8acc243..3bbf5d2 100644
--- a/pylxd/models/container.py
+++ b/pylxd/models/container.py
@@ -231,7 +231,7 @@ def migrate(self, new_client, wait=False):
         first or criu must be installed on the source and destination
         machines.
         """
-        if self.api._api_endpoint.startswith('http+unix'):
+        if self.api.scheme in ('http+unix',):
             raise ValueError('Cannot migrate from a local client connection')
 
         self.sync()  # Make sure the object isn't stale
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to