The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/pylxd/pull/437
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) === Signed-off-by: Dougal Matthews <dou...@dougalmatthews.com>
From dcaa938e29ff1d31c5e2fc264d10b8a699dccf4e Mon Sep 17 00:00:00 2001 From: Dougal Matthews <dou...@dougalmatthews.com> Date: Fri, 11 Dec 2020 12:20:59 +0000 Subject: [PATCH] Blacken and isort contrib_testing, integration and migration code Signed-off-by: Dougal Matthews <dou...@dougalmatthews.com> --- contrib_testing/local-http-test.py | 35 +++--- contrib_testing/local-unix-test.py | 35 +++--- contrib_testing/remote-test.py | 37 ++++--- integration/busybox.py | 56 +++++----- integration/test_client.py | 6 +- integration/test_cluster_members.py | 5 +- integration/test_containers.py | 162 +++++++++++++--------------- integration/test_images.py | 15 ++- integration/test_networks.py | 51 +++++---- integration/test_profiles.py | 17 ++- integration/test_storage.py | 26 ++--- integration/testing.py | 71 ++++++------ migration/busybox.py | 56 +++++----- migration/test_containers.py | 63 +++++------ migration/testing.py | 71 ++++++------ tox.ini | 10 +- 16 files changed, 353 insertions(+), 363 deletions(-) diff --git a/contrib_testing/local-http-test.py b/contrib_testing/local-http-test.py index 3e47bcae..9ddde29e 100755 --- a/contrib_testing/local-http-test.py +++ b/contrib_testing/local-http-test.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 import datetime -import pylxd -import requests import time +import requests from requests.packages.urllib3.exceptions import InsecureRequestWarning +import pylxd requests.packages.urllib3.disable_warnings(InsecureRequestWarning) @@ -18,22 +18,25 @@ def log(s): def create_and_update(client): log("Creating...") - base = client.containers.create({ - 'name': 'ubuntu-1604', - 'source': { - 'type': 'image', - 'protocol': 'simplestreams', - 'server': 'https://images.linuxcontainers.org', - 'alias': 'ubuntu/xenial/amd64' - } - }, wait=True) + base = client.containers.create( + { + "name": "ubuntu-1604", + "source": { + "type": "image", + "protocol": "simplestreams", + "server": "https://images.linuxcontainers.org", + "alias": "ubuntu/xenial/amd64", + }, + }, + wait=True, + ) log("starting...") base.start(wait=True) - while len(base.state().network['eth0']['addresses']) < 2: + while len(base.state().network["eth0"]["addresses"]) < 2: time.sleep(1) commands = [ - ['apt-get', 'update'], - ['apt-get', 'install', 'openssh-server', 'sudo', 'man', '-y'] + ["apt-get", "update"], + ["apt-get", "install", "openssh-server", "sudo", "man", "-y"], ] for command in commands: log("command: {}".format(command)) @@ -43,9 +46,9 @@ def create_and_update(client): log("stderr: {}".format(result.stderr)) -if __name__ == '__main__': +if __name__ == "__main__": client = pylxd.Client("https://127.0.0.1:8443/", verify=False) log("Authenticating...") - client.authenticate('password') + client.authenticate("password") create_and_update(client) diff --git a/contrib_testing/local-unix-test.py b/contrib_testing/local-unix-test.py index 580c0d56..fa291d71 100755 --- a/contrib_testing/local-unix-test.py +++ b/contrib_testing/local-unix-test.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 import datetime -import pylxd -import requests import time +import requests from requests.packages.urllib3.exceptions import InsecureRequestWarning +import pylxd requests.packages.urllib3.disable_warnings(InsecureRequestWarning) @@ -18,22 +18,25 @@ def log(s): def create_and_update(client): log("Creating...") - base = client.containers.create({ - 'name': 'ubuntu-1604', - 'source': { - 'type': 'image', - 'protocol': 'simplestreams', - 'server': 'https://images.linuxcontainers.org', - 'alias': 'ubuntu/xenial/amd64' - } - }, wait=True) + base = client.containers.create( + { + "name": "ubuntu-1604", + "source": { + "type": "image", + "protocol": "simplestreams", + "server": "https://images.linuxcontainers.org", + "alias": "ubuntu/xenial/amd64", + }, + }, + wait=True, + ) log("starting...") base.start(wait=True) - while len(base.state().network['eth0']['addresses']) < 2: + while len(base.state().network["eth0"]["addresses"]) < 2: time.sleep(1) commands = [ - ['apt-get', 'update'], - ['apt-get', 'install', 'openssh-server', 'sudo', 'man', '-y'] + ["apt-get", "update"], + ["apt-get", "install", "openssh-server", "sudo", "man", "-y"], ] for command in commands: log("command: {}".format(command)) @@ -43,9 +46,9 @@ def create_and_update(client): log("stderr: {}".format(result.stderr)) -if __name__ == '__main__': +if __name__ == "__main__": client = pylxd.Client() log("Authenticating...") - client.authenticate('password') + client.authenticate("password") create_and_update(client) diff --git a/contrib_testing/remote-test.py b/contrib_testing/remote-test.py index 46b373cc..5eac5809 100755 --- a/contrib_testing/remote-test.py +++ b/contrib_testing/remote-test.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 import datetime -import pylxd -import requests import time +import requests from requests.packages.urllib3.exceptions import InsecureRequestWarning +import pylxd requests.packages.urllib3.disable_warnings(InsecureRequestWarning) @@ -18,23 +18,26 @@ def log(s): def create_and_update(client): log("Creating...") - base = client.containers.create({ - 'name': 'ubuntu-1604', - 'source': { - 'type': 'image', - 'protocol': 'simplestreams', - 'server': 'https://images.linuxcontainers.org', - 'alias': 'ubuntu/xenial/amd64' - } - }, wait=True) + base = client.containers.create( + { + "name": "ubuntu-1604", + "source": { + "type": "image", + "protocol": "simplestreams", + "server": "https://images.linuxcontainers.org", + "alias": "ubuntu/xenial/amd64", + }, + }, + wait=True, + ) log("starting...") base.start(wait=True) - while len(base.state().network['eth0']['addresses']) < 2: + while len(base.state().network["eth0"]["addresses"]) < 2: time.sleep(1) commands = [ - ['sleep', '10'], - ['apt-get', 'update'], - ['apt-get', 'install', 'openssh-server', 'sudo', 'man', '-y'] + ["sleep", "10"], + ["apt-get", "update"], + ["apt-get", "install", "openssh-server", "sudo", "man", "-y"], ] for command in commands: log("command: {}".format(command)) @@ -44,9 +47,9 @@ def create_and_update(client): log("stderr: {}".format(result.stderr)) -if __name__ == '__main__': +if __name__ == "__main__": client = pylxd.Client("https://10.245.162.33:8443/", verify=False) log("Authenticating...") - client.authenticate('password') + client.authenticate("password") create_and_update(client) diff --git a/integration/busybox.py b/integration/busybox.py index af08e0e7..c178b8e5 100644 --- a/integration/busybox.py +++ b/integration/busybox.py @@ -14,9 +14,9 @@ def find_on_path(command): """Is command on the executable search path?""" - if 'PATH' not in os.environ: + if "PATH" not in os.environ: return False - path = os.environ['PATH'] + path = os.environ["PATH"] for element in path.split(os.pathsep): if not element: continue @@ -44,20 +44,21 @@ def create_tarball(self, split=False): target_tarball = tarfile.open(destination_tar, "w:") if split: - destination_tar_rootfs = os.path.join(self.workdir, - "busybox.rootfs.tar") + destination_tar_rootfs = os.path.join(self.workdir, "busybox.rootfs.tar") target_tarball_rootfs = tarfile.open(destination_tar_rootfs, "w:") - metadata = {'architecture': os.uname()[4], - 'creation_date': int(os.stat("/bin/busybox").st_ctime), - 'properties': { - 'os': "Busybox", - 'architecture': os.uname()[4], - 'description': "Busybox %s" % os.uname()[4], - 'name': "busybox-%s" % os.uname()[4], - # Don't overwrite actual busybox images. - 'obfuscate': str(uuid.uuid4()), }, - } + metadata = { + "architecture": os.uname()[4], + "creation_date": int(os.stat("/bin/busybox").st_ctime), + "properties": { + "os": "Busybox", + "architecture": os.uname()[4], + "description": "Busybox %s" % os.uname()[4], + "name": "busybox-%s" % os.uname()[4], + # Don't overwrite actual busybox images. + "obfuscate": str(uuid.uuid4()), + }, + } # Add busybox with open("/bin/busybox", "rb") as fd: @@ -72,9 +73,11 @@ def create_tarball(self, split=False): target_tarball.addfile(busybox_file, fd) # Add symlinks - busybox = subprocess.Popen(["/bin/busybox", "--list-full"], - stdout=subprocess.PIPE, - universal_newlines=True) + busybox = subprocess.Popen( + ["/bin/busybox", "--list-full"], + stdout=subprocess.PIPE, + universal_newlines=True, + ) busybox.wait() for path in busybox.stdout.read().split("\n"): @@ -103,15 +106,21 @@ def create_tarball(self, split=False): target_tarball.addfile(directory_file) # Add the metadata file - metadata_yaml = json.dumps(metadata, sort_keys=True, - indent=4, separators=(',', ': '), - ensure_ascii=False).encode('utf-8') + b"\n" + metadata_yaml = ( + json.dumps( + metadata, + sort_keys=True, + indent=4, + separators=(",", ": "), + ensure_ascii=False, + ).encode("utf-8") + + b"\n" + ) metadata_file = tarfile.TarInfo() metadata_file.size = len(metadata_yaml) metadata_file.name = "metadata.yaml" - target_tarball.addfile(metadata_file, - io.BytesIO(metadata_yaml)) + target_tarball.addfile(metadata_file, io.BytesIO(metadata_yaml)) # Add an /etc/inittab; this is to work around: # http://lists.busybox.net/pipermail/busybox/2015-November/083618.html @@ -135,8 +144,7 @@ def create_tarball(self, split=False): if split: r = subprocess.call([xz, "-9", destination_tar_rootfs]) if r: - raise Exception("Failed to compress: %s" % - destination_tar_rootfs) + raise Exception("Failed to compress: %s" % destination_tar_rootfs) return destination_tar + ".xz", destination_tar_rootfs + ".xz" else: return destination_tar + ".xz" diff --git a/integration/test_client.py b/integration/test_client.py index 949c32ed..1093542c 100644 --- a/integration/test_client.py +++ b/integration/test_client.py @@ -11,10 +11,10 @@ # 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 pylxd import requests from requests.packages.urllib3.exceptions import InsecureRequestWarning +import pylxd from integration.testing import IntegrationTestCase requests.packages.urllib3.disable_warnings(InsecureRequestWarning) @@ -26,10 +26,10 @@ class TestClient(IntegrationTestCase): def test_authenticate(self): # This is another test with multiple assertions, as it is a test of # flow, rather than a single source of functionality. - client = pylxd.Client('https://127.0.0.1:8443/', verify=False) + client = pylxd.Client("https://127.0.0.1:8443/", verify=False) self.assertFalse(client.trusted) - client.authenticate('password') + client.authenticate("password") self.assertTrue(client.trusted) diff --git a/integration/test_cluster_members.py b/integration/test_cluster_members.py index 7708a264..b94d174a 100644 --- a/integration/test_cluster_members.py +++ b/integration/test_cluster_members.py @@ -16,12 +16,11 @@ class ClusterMemberTestCase(IntegrationTestCase): - def setUp(self): super(ClusterMemberTestCase, self).setUp() - if not self.client.has_api_extension('clustering'): - self.skipTest('Required LXD API extension not available!') + if not self.client.has_api_extension("clustering"): + self.skipTest("Required LXD API extension not available!") class TestClusterMembers(ClusterMemberTestCase): diff --git a/integration/test_containers.py b/integration/test_containers.py index 00404ba3..9563652a 100644 --- a/integration/test_containers.py +++ b/integration/test_containers.py @@ -13,8 +13,8 @@ # under the License. import unittest -from pylxd import exceptions from integration.testing import IntegrationTestCase +from pylxd import exceptions class TestContainers(IntegrationTestCase): @@ -42,19 +42,18 @@ def test_create(self): """Creates and returns a new container.""" _, alias = self.create_image() config = { - 'name': 'an-container', - 'architecture': '2', - 'profiles': ['default'], - 'ephemeral': True, - 'config': {'limits.cpu': '2'}, - 'source': {'type': 'image', - 'alias': alias}, + "name": "an-container", + "architecture": "2", + "profiles": ["default"], + "ephemeral": True, + "config": {"limits.cpu": "2"}, + "source": {"type": "image", "alias": alias}, } - self.addCleanup(self.delete_container, config['name']) + self.addCleanup(self.delete_container, config["name"]) container = self.client.containers.create(config, wait=True) - self.assertEqual(config['name'], container.name) + self.assertEqual(config["name"], container.name) class TestContainer(IntegrationTestCase): @@ -71,16 +70,16 @@ def tearDown(self): def test_save(self): """The container is updated to a new config.""" - self.container.config['limits.cpu'] = '1' + self.container.config["limits.cpu"] = "1" self.container.save(wait=True) - self.assertEqual('1', self.container.config['limits.cpu']) + self.assertEqual("1", self.container.config["limits.cpu"]) container = self.client.containers.get(self.container.name) - self.assertEqual('1', container.config['limits.cpu']) + self.assertEqual("1", container.config["limits.cpu"]) def test_rename(self): """The container is renamed.""" - name = 'an-renamed-container' + name = "an-renamed-container" self.container.rename(name, wait=True) self.assertEqual(name, self.container.name) @@ -92,8 +91,8 @@ def test_delete(self): self.container.delete(wait=True) self.assertRaises( - exceptions.LXDAPIException, - self.client.containers.get, self.container.name) + exceptions.LXDAPIException, self.client.containers.get, self.container.name + ) def test_start_stop(self): """The container is started and then stopped.""" @@ -102,31 +101,29 @@ def test_start_stop(self): # to test what we need. self.container.start(wait=True) - self.assertEqual('Running', self.container.status) + self.assertEqual("Running", self.container.status) container = self.client.containers.get(self.container.name) - self.assertEqual('Running', container.status) + self.assertEqual("Running", container.status) self.container.stop(wait=True) - self.assertEqual('Stopped', self.container.status) + self.assertEqual("Stopped", self.container.status) container = self.client.containers.get(self.container.name) - self.assertEqual('Stopped', container.status) + self.assertEqual("Stopped", container.status) def test_snapshot(self): """A container snapshot is made, renamed, and deleted.""" # NOTE: rockstar (15 Feb 2016) - Once again, multiple things # asserted in the same test. - name = 'an-snapshot' + name = "an-snapshot" snapshot = self.container.snapshots.create(name, wait=True) - self.assertEqual( - [name], [s.name for s in self.container.snapshots.all()]) + self.assertEqual([name], [s.name for s in self.container.snapshots.all()]) - new_name = 'an-other-snapshot' + new_name = "an-other-snapshot" snapshot.rename(new_name, wait=True) - self.assertEqual( - [new_name], [s.name for s in self.container.snapshots.all()]) + self.assertEqual([new_name], [s.name for s in self.container.snapshots.all()]) snapshot.delete(wait=True) @@ -134,8 +131,8 @@ def test_snapshot(self): def test_put_get_file(self): """A file is written to the container and then read.""" - filepath = '/tmp/an_file' - data = b'abcdef' + filepath = "/tmp/an_file" + data = b"abcdef" # raises an exception if this fails. self.container.files.put(filepath, data) @@ -149,50 +146,48 @@ def test_execute(self): self.container.start(wait=True) self.addCleanup(self.container.stop, wait=True) - result = self.container.execute(['echo', 'test']) + result = self.container.execute(["echo", "test"]) self.assertEqual(0, result.exit_code) - self.assertEqual('test\n', result.stdout) - self.assertEqual('', result.stderr) + self.assertEqual("test\n", result.stdout) + self.assertEqual("", result.stderr) def test_execute_no_buffer(self): - """A command is executed on the container without buffering the output. - """ + """A command is executed on the container without buffering the output.""" self.container.start(wait=True) self.addCleanup(self.container.stop, wait=True) buffer = [] - result = self.container.execute(['echo', 'test'], - stdout_handler=buffer.append) + result = self.container.execute(["echo", "test"], stdout_handler=buffer.append) self.assertEqual(0, result.exit_code) - self.assertEqual('', result.stdout) - self.assertEqual('', result.stderr) + self.assertEqual("", result.stdout) + self.assertEqual("", result.stderr) self.assertEqual("test\n", "".join(buffer)) def test_execute_no_decode(self): - """A command is executed on the container that isn't utf-8 decodable - """ + """A command is executed on the container that isn't utf-8 decodable""" self.container.start(wait=True) self.addCleanup(self.container.stop, wait=True) - result = self.container.execute(['printf', '\\xff'], decode=None) + result = self.container.execute(["printf", "\\xff"], decode=None) self.assertEqual(0, result.exit_code) - self.assertEqual(b'\xff', result.stdout) - self.assertEqual(b'', result.stderr) + self.assertEqual(b"\xff", result.stdout) + self.assertEqual(b"", result.stderr) def test_execute_force_decode(self): """A command is executed and force output to ascii""" self.container.start(wait=True) self.addCleanup(self.container.stop, wait=True) - result = self.container.execute(['printf', 'qu\\xe9'], decode=True, - encoding='latin1') + result = self.container.execute( + ["printf", "qu\\xe9"], decode=True, encoding="latin1" + ) self.assertEqual(0, result.exit_code) - self.assertEqual('qué', result.stdout) - self.assertEqual('', result.stderr) + self.assertEqual("qué", result.stdout) + self.assertEqual("", result.stderr) def test_execute_pipes(self): """A command receives data from stdin and write to stdout handler""" @@ -205,24 +200,24 @@ def stdout_handler(msg): stdout_msgs.append(msg) result = self.container.execute( - ['cat', '-'], stdin_payload=test_msg, stdout_handler=stdout_handler + ["cat", "-"], stdin_payload=test_msg, stdout_handler=stdout_handler ) self.assertEqual(0, result.exit_code) # if a handler is supplied then there is no stdout in result - self.assertEqual('', result.stdout) - self.assertEqual('', result.stderr) + self.assertEqual("", result.stdout) + self.assertEqual("", result.stderr) self.assertEqual(stdout_msgs, [test_msg]) def test_publish(self): """A container is published.""" # Hack to get around mocked data - self.container.type = 'container' + self.container.type = "container" image = self.container.publish(wait=True) self.assertIn( - image.fingerprint, - [i.fingerprint for i in self.client.images.all()]) + image.fingerprint, [i.fingerprint for i in self.client.images.all()] + ) # COMMENT gabrik - 29/08/2018: # This test is commented because CRIU does NOT work @@ -232,60 +227,49 @@ def test_publish(self): def test_migrate_running(self): """A running container is migrated.""" from pylxd.client import Client - first_host = 'https://10.0.3.111:8443/' - second_host = 'https://10.0.3.222:8443/' + + first_host = "https://10.0.3.111:8443/" + second_host = "https://10.0.3.222:8443/" client1 = Client(endpoint=first_host, verify=False) - client1.authenticate('password') + client1.authenticate("password") client2 = Client(endpoint=second_host, verify=False) - client2.authenticate('password') - an_container = \ - client1.containers.get(self.container.name) + client2.authenticate("password") + an_container = client1.containers.get(self.container.name) an_container.start(wait=True) an_container.sync() - an_migrated_container = \ - an_container.migrate(client2, wait=True) + an_migrated_container = an_container.migrate(client2, wait=True) - self.assertEqual(an_container.name, - an_migrated_container.name) - self.assertEqual(client2, - an_migrated_container.client) + self.assertEqual(an_container.name, an_migrated_container.name) + self.assertEqual(client2, an_migrated_container.client) @unittest.skip("This test is broken as it assumes particular network") def test_migrate_local_client(self): """Raise ValueError, cannot migrate from local connection""" from pylxd.client import Client - second_host = 'https://10.0.3.222:8443/' - client2 =\ - Client(endpoint=second_host, verify=False) - client2.authenticate('password') + second_host = "https://10.0.3.222:8443/" + client2 = Client(endpoint=second_host, verify=False) + client2.authenticate("password") - self.assertRaises(ValueError, - self.container.migrate, client2) + self.assertRaises(ValueError, self.container.migrate, client2) @unittest.skip("This test is broken as it assumes particular network") def test_migrate_stopped(self): """A stopped container is migrated.""" from pylxd.client import Client - first_host = 'https://10.0.3.111:8443/' - second_host = 'https://10.0.3.222:8443/' - - client1 = \ - Client(endpoint=first_host, verify=False) - client1.authenticate('password') - - client2 = \ - Client(endpoint=second_host, verify=False) - client2.authenticate('password') - an_container = \ - client1.containers.get(self.container.name) - an_migrated_container = \ - an_container.migrate(client2, wait=True) - - self.assertEqual(an_container.name, - an_migrated_container.name) - self.assertEqual(client2, - an_migrated_container.client) + first_host = "https://10.0.3.111:8443/" + second_host = "https://10.0.3.222:8443/" + + client1 = Client(endpoint=first_host, verify=False) + client1.authenticate("password") + + client2 = Client(endpoint=second_host, verify=False) + client2.authenticate("password") + an_container = client1.containers.get(self.container.name) + an_migrated_container = an_container.migrate(client2, wait=True) + + self.assertEqual(an_container.name, an_migrated_container.name) + self.assertEqual(client2, an_migrated_container.client) diff --git a/integration/test_images.py b/integration/test_images.py index f1a7473e..e2221991 100644 --- a/integration/test_images.py +++ b/integration/test_images.py @@ -14,10 +14,9 @@ import hashlib import time +from integration.testing import IntegrationTestCase, create_busybox_image from pylxd import exceptions -from integration.testing import create_busybox_image, IntegrationTestCase - class TestImages(IntegrationTestCase): """Tests for `Client.images.`""" @@ -48,7 +47,7 @@ def test_create(self): path, fingerprint = create_busybox_image() self.addCleanup(self.delete_image, fingerprint) - with open(path, 'rb') as f: + with open(path, "rb") as f: data = f.read() image = self.client.images.create(data, wait=True) @@ -69,20 +68,20 @@ def tearDown(self): def test_save(self): """The image properties are updated.""" - description = 'an description' - self.image.properties['description'] = description + description = "an description" + self.image.properties["description"] = description self.image.save() image = self.client.images.get(self.image.fingerprint) - self.assertEqual(description, image.properties['description']) + self.assertEqual(description, image.properties["description"]) def test_delete(self): """The image is deleted.""" self.image.delete(wait=True) self.assertRaises( - exceptions.LXDAPIException, - self.client.images.get, self.image.fingerprint) + exceptions.LXDAPIException, self.client.images.get, self.image.fingerprint + ) def test_export(self): """The image is successfully exported.""" diff --git a/integration/test_networks.py b/integration/test_networks.py index 1db1d30e..359dd6b2 100644 --- a/integration/test_networks.py +++ b/integration/test_networks.py @@ -17,12 +17,11 @@ class NetworkTestCase(IntegrationTestCase): - def setUp(self): super(NetworkTestCase, self).setUp() - if not self.client.has_api_extension('network'): - self.skipTest('Required LXD API extension not available!') + if not self.client.has_api_extension("network"): + self.skipTest("Required LXD API extension not available!") class TestNetworks(NetworkTestCase): @@ -49,40 +48,40 @@ def test_all(self): def test_create_default_arguments(self): """A network is created with default arguments""" - name = 'eth10' + name = "eth10" network = self.client.networks.create(name=name) self.addCleanup(self.delete_network, name) self.assertEqual(name, network.name) self.assertTrue(network.managed) - self.assertEqual('bridge', network.type) - self.assertEqual('', network.description) + self.assertEqual("bridge", network.type) + self.assertEqual("", network.description) def test_create_with_parameters(self): """A network is created with provided arguments""" kwargs = { - 'name': 'eth10', - 'config': { - 'ipv4.address': '10.10.10.1/24', - 'ipv4.nat': 'true', - 'ipv6.address': 'none', - 'ipv6.nat': 'false', + "name": "eth10", + "config": { + "ipv4.address": "10.10.10.1/24", + "ipv4.nat": "true", + "ipv6.address": "none", + "ipv6.nat": "false", }, - 'type': 'bridge', - 'description': 'network description', + "type": "bridge", + "description": "network description", } - if self.client.has_api_extension('network_hwaddr'): - kwargs['config']['bridge.hwaddr'] = '00:16:3e:12:34:56' + if self.client.has_api_extension("network_hwaddr"): + kwargs["config"]["bridge.hwaddr"] = "00:16:3e:12:34:56" network = self.client.networks.create(**kwargs) - self.addCleanup(self.delete_network, kwargs['name']) + self.addCleanup(self.delete_network, kwargs["name"]) - self.assertEqual(kwargs['name'], network.name) - self.assertEqual(kwargs['config'], network.config) - self.assertEqual(kwargs['type'], network.type) + self.assertEqual(kwargs["name"], network.name) + self.assertEqual(kwargs["config"], network.config) + self.assertEqual(kwargs["type"], network.type) self.assertTrue(network.managed) - self.assertEqual(kwargs['description'], network.description) + self.assertEqual(kwargs["description"], network.description) class TestNetwork(NetworkTestCase): @@ -99,15 +98,15 @@ def tearDown(self): def test_save(self): """A network is updated""" - self.network.config['ipv4.address'] = '11.11.11.1/24' + self.network.config["ipv4.address"] = "11.11.11.1/24" self.network.save() network = self.client.networks.get(self.network.name) - self.assertEqual('11.11.11.1/24', network.config['ipv4.address']) + self.assertEqual("11.11.11.1/24", network.config["ipv4.address"]) def test_rename(self): """A network is renamed""" - name = 'eth20' + name = "eth20" self.addCleanup(self.delete_network, name) self.network.rename(name) @@ -120,5 +119,5 @@ def test_delete(self): self.network.delete() self.assertRaises( - exceptions.LXDAPIException, - self.client.networks.get, self.network.name) + exceptions.LXDAPIException, self.client.networks.get, self.network.name + ) diff --git a/integration/test_profiles.py b/integration/test_profiles.py index 3e6dc0d4..0f3a16f6 100644 --- a/integration/test_profiles.py +++ b/integration/test_profiles.py @@ -11,9 +11,8 @@ # 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 pylxd import exceptions - from integration.testing import IntegrationTestCase +from pylxd import exceptions class TestProfiles(IntegrationTestCase): @@ -39,8 +38,8 @@ def test_all(self): def test_create(self): """A profile is created.""" - name = 'an-profile' - config = {'limits.memory': '1GB'} + name = "an-profile" + config = {"limits.memory": "1GB"} profile = self.client.profiles.create(name, config) self.addCleanup(self.delete_profile, name) @@ -62,15 +61,15 @@ def tearDown(self): def test_save(self): """A profile is updated.""" - self.profile.config['limits.memory'] = '16GB' + self.profile.config["limits.memory"] = "16GB" self.profile.save() profile = self.client.profiles.get(self.profile.name) - self.assertEqual('16GB', profile.config['limits.memory']) + self.assertEqual("16GB", profile.config["limits.memory"]) def test_rename(self): """A profile is renamed.""" - name = 'a-other-profile' + name = "a-other-profile" self.addCleanup(self.delete_profile, name) self.profile.rename(name) @@ -83,5 +82,5 @@ def test_delete(self): self.profile.delete() self.assertRaises( - exceptions.LXDAPIException, - self.client.profiles.get, self.profile.name) + exceptions.LXDAPIException, self.client.profiles.get, self.profile.name + ) diff --git a/integration/test_storage.py b/integration/test_storage.py index 52506617..85ace2e2 100644 --- a/integration/test_storage.py +++ b/integration/test_storage.py @@ -16,27 +16,27 @@ import string import unittest - -from integration.testing import IntegrationTestCase import pylxd.exceptions as exceptions +from integration.testing import IntegrationTestCase class StorageTestCase(IntegrationTestCase): - def setUp(self): super(StorageTestCase, self).setUp() - if not self.client.has_api_extension('storage'): - self.skipTest('Required LXD API extension not available!') + if not self.client.has_api_extension("storage"): + self.skipTest("Required LXD API extension not available!") def create_storage_pool(self): # create a storage pool in the form of 'xxx1' as a dir. - name = ''.join(random.sample(string.ascii_lowercase, 3)) + '1' - self.lxd.storage_pools.post(json={ - "config": {}, - "driver": "dir", - "name": name, - }) + name = "".join(random.sample(string.ascii_lowercase, 3)) + "1" + self.lxd.storage_pools.post( + json={ + "config": {}, + "driver": "dir", + "name": name, + } + ) return name def delete_storage_pool(self, name): @@ -49,6 +49,7 @@ def delete_storage_pool(self, name): class TestStoragePools(StorageTestCase): """Tests for :py:class:`pylxd.models.storage_pools.StoragePools""" + # note create and delete are tested in every method def test_get(self): @@ -125,6 +126,7 @@ def test_get(self): class TestStorageVolume(StorageTestCase): """Tests for :py:class:`pylxd.models.storage_pools.StorageVolume""" + # note create and delete are tested in every method def create_storage_volume(self, pool): @@ -146,7 +148,7 @@ def delete_storage_volume(self, pool, volume): if isinstance(volume, str): if isinstance(pool, str): pool = self.client.storage_pools.get(pool) - volume = pool.volumes.get('custom', volume) + volume = pool.volumes.get("custom", volume) volume.delete() def test_create_and_get_and_delete(self): diff --git a/integration/testing.py b/integration/testing.py index 33d145e8..1052b264 100644 --- a/integration/testing.py +++ b/integration/testing.py @@ -32,9 +32,9 @@ def setUp(self): def generate_object_name(self): """Generate a random object name.""" # Underscores are not allowed in container names. - test = self.id().split('.')[-1].replace('_', '') - rando = str(uuid.uuid1()).split('-')[-1] - return '{}-{}'.format(test, rando) + test = self.id().split(".")[-1].replace("_", "") + rando = str(uuid.uuid1()).split("-")[-1] + return "{}-{}".format(test, rando) def create_container(self): """Create a container in lxd.""" @@ -42,16 +42,15 @@ def create_container(self): name = self.generate_object_name() machine = { - 'name': name, - 'architecture': '2', - 'profiles': ['default'], - 'ephemeral': False, - 'config': {'limits.cpu': '2'}, - 'source': {'type': 'image', - 'alias': alias}, + "name": name, + "architecture": "2", + "profiles": ["default"], + "ephemeral": False, + "config": {"limits.cpu": "2"}, + "source": {"type": "image", "alias": alias}, } - result = self.lxd['containers'].post(json=machine) - operation_uuid = result.json()['operation'].split('/')[-1] + result = self.lxd["containers"].post(json=machine) + operation_uuid = result.json()["operation"].split("/")[-1] result = self.lxd.operations[operation_uuid].wait.get() self.addCleanup(self.delete_container, name) @@ -63,21 +62,21 @@ def delete_container(self, name, enforce=False): # To ensure we don't get an infinite loop, let's count. count = 0 try: - result = self.lxd['containers'][name].delete() + result = self.lxd["containers"][name].delete() except exceptions.LXDAPIException as e: if e.response.status_code in (400, 404): return raise while enforce and result.status_code == 404 and count < 10: try: - result = self.lxd['containers'][name].delete() + result = self.lxd["containers"][name].delete() except exceptions.LXDAPIException as e: if e.response.status_code in (400, 404): return raise count += 1 try: - operation_uuid = result.json()['operation'].split('/')[-1] + operation_uuid = result.json()["operation"].split("/")[-1] result = self.lxd.operations[operation_uuid].wait.get() except KeyError: pass # 404 cases are okay. @@ -85,20 +84,18 @@ def delete_container(self, name, enforce=False): def create_image(self): """Create an image in lxd.""" path, fingerprint = create_busybox_image() - with open(path, 'rb') as f: + with open(path, "rb") as f: headers = { - 'X-LXD-Public': '1', - } + "X-LXD-Public": "1", + } response = self.lxd.images.post(data=f.read(), headers=headers) - operation_uuid = response.json()['operation'].split('/')[-1] + operation_uuid = response.json()["operation"].split("/")[-1] self.lxd.operations[operation_uuid].wait.get() alias = self.generate_object_name() - response = self.lxd.images.aliases.post(json={ - 'description': '', - 'target': fingerprint, - 'name': alias - }) + response = self.lxd.images.aliases.post( + json={"description": "", "target": fingerprint, "name": alias} + ) self.addCleanup(self.delete_image, fingerprint) return fingerprint, alias @@ -115,11 +112,8 @@ def delete_image(self, fingerprint): def create_profile(self): """Create a profile.""" name = self.generate_object_name() - config = {'limits.memory': '1GB'} - self.lxd.profiles.post(json={ - 'name': name, - 'config': config - }) + config = {"limits.memory": "1GB"} + self.lxd.profiles.post(json={"name": name, "config": config}) return name def delete_profile(self, name): @@ -133,11 +127,13 @@ def delete_profile(self, name): def create_network(self): # get interface name in format xxx0 - name = ''.join(random.sample(string.ascii_lowercase, 3)) + '0' - self.lxd.networks.post(json={ - 'name': name, - 'config': {}, - }) + name = "".join(random.sample(string.ascii_lowercase, 3)) + "0" + self.lxd.networks.post( + json={ + "name": name, + "config": {}, + } + ) return name def delete_network(self, name): @@ -152,7 +148,8 @@ def assertCommon(self, response): LXD responses are relatively standard. This function makes assertions to all those standards. """ - self.assertEqual(response.status_code, response.json()['status_code']) + self.assertEqual(response.status_code, response.json()["status_code"]) self.assertEqual( - ['metadata', 'operation', 'status', 'status_code', 'type'], - sorted(response.json().keys())) + ["metadata", "operation", "status", "status_code", "type"], + sorted(response.json().keys()), + ) diff --git a/migration/busybox.py b/migration/busybox.py index af08e0e7..c178b8e5 100644 --- a/migration/busybox.py +++ b/migration/busybox.py @@ -14,9 +14,9 @@ def find_on_path(command): """Is command on the executable search path?""" - if 'PATH' not in os.environ: + if "PATH" not in os.environ: return False - path = os.environ['PATH'] + path = os.environ["PATH"] for element in path.split(os.pathsep): if not element: continue @@ -44,20 +44,21 @@ def create_tarball(self, split=False): target_tarball = tarfile.open(destination_tar, "w:") if split: - destination_tar_rootfs = os.path.join(self.workdir, - "busybox.rootfs.tar") + destination_tar_rootfs = os.path.join(self.workdir, "busybox.rootfs.tar") target_tarball_rootfs = tarfile.open(destination_tar_rootfs, "w:") - metadata = {'architecture': os.uname()[4], - 'creation_date': int(os.stat("/bin/busybox").st_ctime), - 'properties': { - 'os': "Busybox", - 'architecture': os.uname()[4], - 'description': "Busybox %s" % os.uname()[4], - 'name': "busybox-%s" % os.uname()[4], - # Don't overwrite actual busybox images. - 'obfuscate': str(uuid.uuid4()), }, - } + metadata = { + "architecture": os.uname()[4], + "creation_date": int(os.stat("/bin/busybox").st_ctime), + "properties": { + "os": "Busybox", + "architecture": os.uname()[4], + "description": "Busybox %s" % os.uname()[4], + "name": "busybox-%s" % os.uname()[4], + # Don't overwrite actual busybox images. + "obfuscate": str(uuid.uuid4()), + }, + } # Add busybox with open("/bin/busybox", "rb") as fd: @@ -72,9 +73,11 @@ def create_tarball(self, split=False): target_tarball.addfile(busybox_file, fd) # Add symlinks - busybox = subprocess.Popen(["/bin/busybox", "--list-full"], - stdout=subprocess.PIPE, - universal_newlines=True) + busybox = subprocess.Popen( + ["/bin/busybox", "--list-full"], + stdout=subprocess.PIPE, + universal_newlines=True, + ) busybox.wait() for path in busybox.stdout.read().split("\n"): @@ -103,15 +106,21 @@ def create_tarball(self, split=False): target_tarball.addfile(directory_file) # Add the metadata file - metadata_yaml = json.dumps(metadata, sort_keys=True, - indent=4, separators=(',', ': '), - ensure_ascii=False).encode('utf-8') + b"\n" + metadata_yaml = ( + json.dumps( + metadata, + sort_keys=True, + indent=4, + separators=(",", ": "), + ensure_ascii=False, + ).encode("utf-8") + + b"\n" + ) metadata_file = tarfile.TarInfo() metadata_file.size = len(metadata_yaml) metadata_file.name = "metadata.yaml" - target_tarball.addfile(metadata_file, - io.BytesIO(metadata_yaml)) + target_tarball.addfile(metadata_file, io.BytesIO(metadata_yaml)) # Add an /etc/inittab; this is to work around: # http://lists.busybox.net/pipermail/busybox/2015-November/083618.html @@ -135,8 +144,7 @@ def create_tarball(self, split=False): if split: r = subprocess.call([xz, "-9", destination_tar_rootfs]) if r: - raise Exception("Failed to compress: %s" % - destination_tar_rootfs) + raise Exception("Failed to compress: %s" % destination_tar_rootfs) return destination_tar + ".xz", destination_tar_rootfs + ".xz" else: return destination_tar + ".xz" diff --git a/migration/test_containers.py b/migration/test_containers.py index 167bf9d1..b29a8876 100644 --- a/migration/test_containers.py +++ b/migration/test_containers.py @@ -30,58 +30,47 @@ def tearDown(self): def test_migrate_running(self): """A running container is migrated.""" from pylxd.client import Client - first_host = 'https://10.0.3.111:8443/' - second_host = 'https://10.0.3.222:8443/' + + first_host = "https://10.0.3.111:8443/" + second_host = "https://10.0.3.222:8443/" client1 = Client(endpoint=first_host, verify=False) - client1.authenticate('password') + client1.authenticate("password") client2 = Client(endpoint=second_host, verify=False) - client2.authenticate('password') - an_container = \ - client1.containers.get(self.container.name) + client2.authenticate("password") + an_container = client1.containers.get(self.container.name) an_container.start(wait=True) an_container.sync() - an_migrated_container = \ - an_container.migrate(client2, wait=True) + an_migrated_container = an_container.migrate(client2, wait=True) - self.assertEqual(an_container.name, - an_migrated_container.name) - self.assertEqual(client2, - an_migrated_container.client) + self.assertEqual(an_container.name, an_migrated_container.name) + self.assertEqual(client2, an_migrated_container.client) def test_migrate_local_client(self): """Raise ValueError, cannot migrate from local connection""" from pylxd.client import Client - second_host = 'https://10.0.3.222:8443/' - client2 =\ - Client(endpoint=second_host, verify=False) - client2.authenticate('password') + second_host = "https://10.0.3.222:8443/" + client2 = Client(endpoint=second_host, verify=False) + client2.authenticate("password") - self.assertRaises(ValueError, - self.container.migrate, client2) + self.assertRaises(ValueError, self.container.migrate, client2) def test_migrate_stopped(self): """A stopped container is migrated.""" from pylxd.client import Client - first_host = 'https://10.0.3.111:8443/' - second_host = 'https://10.0.3.222:8443/' - - client1 = \ - Client(endpoint=first_host, verify=False) - client1.authenticate('password') - - client2 = \ - Client(endpoint=second_host, verify=False) - client2.authenticate('password') - an_container = \ - client1.containers.get(self.container.name) - an_migrated_container = \ - an_container.migrate(client2, wait=True) - - self.assertEqual(an_container.name, - an_migrated_container.name) - self.assertEqual(client2, - an_migrated_container.client) + first_host = "https://10.0.3.111:8443/" + second_host = "https://10.0.3.222:8443/" + + client1 = Client(endpoint=first_host, verify=False) + client1.authenticate("password") + + client2 = Client(endpoint=second_host, verify=False) + client2.authenticate("password") + an_container = client1.containers.get(self.container.name) + an_migrated_container = an_container.migrate(client2, wait=True) + + self.assertEqual(an_container.name, an_migrated_container.name) + self.assertEqual(client2, an_migrated_container.client) diff --git a/migration/testing.py b/migration/testing.py index 33d145e8..1052b264 100644 --- a/migration/testing.py +++ b/migration/testing.py @@ -32,9 +32,9 @@ def setUp(self): def generate_object_name(self): """Generate a random object name.""" # Underscores are not allowed in container names. - test = self.id().split('.')[-1].replace('_', '') - rando = str(uuid.uuid1()).split('-')[-1] - return '{}-{}'.format(test, rando) + test = self.id().split(".")[-1].replace("_", "") + rando = str(uuid.uuid1()).split("-")[-1] + return "{}-{}".format(test, rando) def create_container(self): """Create a container in lxd.""" @@ -42,16 +42,15 @@ def create_container(self): name = self.generate_object_name() machine = { - 'name': name, - 'architecture': '2', - 'profiles': ['default'], - 'ephemeral': False, - 'config': {'limits.cpu': '2'}, - 'source': {'type': 'image', - 'alias': alias}, + "name": name, + "architecture": "2", + "profiles": ["default"], + "ephemeral": False, + "config": {"limits.cpu": "2"}, + "source": {"type": "image", "alias": alias}, } - result = self.lxd['containers'].post(json=machine) - operation_uuid = result.json()['operation'].split('/')[-1] + result = self.lxd["containers"].post(json=machine) + operation_uuid = result.json()["operation"].split("/")[-1] result = self.lxd.operations[operation_uuid].wait.get() self.addCleanup(self.delete_container, name) @@ -63,21 +62,21 @@ def delete_container(self, name, enforce=False): # To ensure we don't get an infinite loop, let's count. count = 0 try: - result = self.lxd['containers'][name].delete() + result = self.lxd["containers"][name].delete() except exceptions.LXDAPIException as e: if e.response.status_code in (400, 404): return raise while enforce and result.status_code == 404 and count < 10: try: - result = self.lxd['containers'][name].delete() + result = self.lxd["containers"][name].delete() except exceptions.LXDAPIException as e: if e.response.status_code in (400, 404): return raise count += 1 try: - operation_uuid = result.json()['operation'].split('/')[-1] + operation_uuid = result.json()["operation"].split("/")[-1] result = self.lxd.operations[operation_uuid].wait.get() except KeyError: pass # 404 cases are okay. @@ -85,20 +84,18 @@ def delete_container(self, name, enforce=False): def create_image(self): """Create an image in lxd.""" path, fingerprint = create_busybox_image() - with open(path, 'rb') as f: + with open(path, "rb") as f: headers = { - 'X-LXD-Public': '1', - } + "X-LXD-Public": "1", + } response = self.lxd.images.post(data=f.read(), headers=headers) - operation_uuid = response.json()['operation'].split('/')[-1] + operation_uuid = response.json()["operation"].split("/")[-1] self.lxd.operations[operation_uuid].wait.get() alias = self.generate_object_name() - response = self.lxd.images.aliases.post(json={ - 'description': '', - 'target': fingerprint, - 'name': alias - }) + response = self.lxd.images.aliases.post( + json={"description": "", "target": fingerprint, "name": alias} + ) self.addCleanup(self.delete_image, fingerprint) return fingerprint, alias @@ -115,11 +112,8 @@ def delete_image(self, fingerprint): def create_profile(self): """Create a profile.""" name = self.generate_object_name() - config = {'limits.memory': '1GB'} - self.lxd.profiles.post(json={ - 'name': name, - 'config': config - }) + config = {"limits.memory": "1GB"} + self.lxd.profiles.post(json={"name": name, "config": config}) return name def delete_profile(self, name): @@ -133,11 +127,13 @@ def delete_profile(self, name): def create_network(self): # get interface name in format xxx0 - name = ''.join(random.sample(string.ascii_lowercase, 3)) + '0' - self.lxd.networks.post(json={ - 'name': name, - 'config': {}, - }) + name = "".join(random.sample(string.ascii_lowercase, 3)) + "0" + self.lxd.networks.post( + json={ + "name": name, + "config": {}, + } + ) return name def delete_network(self, name): @@ -152,7 +148,8 @@ def assertCommon(self, response): LXD responses are relatively standard. This function makes assertions to all those standards. """ - self.assertEqual(response.status_code, response.json()['status_code']) + self.assertEqual(response.status_code, response.json()["status_code"]) self.assertEqual( - ['metadata', 'operation', 'status', 'status_code', 'type'], - sorted(response.json().keys())) + ["metadata", "operation", "status", "status_code", "type"], + sorted(response.json().keys()), + ) diff --git a/tox.ini b/tox.ini index f7c5488c..d706e82e 100644 --- a/tox.ini +++ b/tox.ini @@ -26,8 +26,8 @@ deps = flake8>=2.5.0 isort==5.6.4 commands= - isort --profile black {toxinidir}/pylxd - black {toxinidir}/pylxd + isort --profile black {toxinidir} + black {toxinidir} [testenv:lint] basepython=python3 @@ -36,9 +36,9 @@ deps = flake8>=2.5.0 isort==5.6.4 commands= - black --check {toxinidir}/pylxd - isort --profile black --check-only --diff {toxinidir}/pylxd - flake8 {toxinidir}/pylxd + black --check {toxinidir} + isort --profile black --check-only --diff {toxinidir} + flake8 {toxinidir} [flake8]
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel