[lxc-devel] [pylxd/master] Add support for LXD storage pools

ChrisMacNaughton on Github lxc-bot at linuxcontainers.org
Wed Jul 12 07:23:44 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 417 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170712/3342b713/attachment.bin>
-------------- next part --------------
From 4fd212b9029cdb3a0dc2baca45392daaacf0cdf2 Mon Sep 17 00:00:00 2001
From: Chris MacNaughton <chris at centaurisolutions.nl>
Date: Wed, 12 Jul 2017 09:21:03 +0200
Subject: [PATCH] Add support for LXD storage pools

This adds basic support for storage pools as well
as tests to verify their function, taken from the
LXD REST API.
---
 pylxd/client.py                    |  5 ++--
 pylxd/managers.py                  |  4 +++
 pylxd/models/__init__.py           |  1 +
 pylxd/models/storage_pool.py       | 55 ++++++++++++++++++++++++++++++++++++++
 pylxd/tests/mock_lxd.py            | 26 ++++++++++++++++++
 pylxd/tests/models/test_storage.py | 53 ++++++++++++++++++++++++++++++++++++
 6 files changed, 142 insertions(+), 2 deletions(-)
 create mode 100644 pylxd/models/storage_pool.py
 create mode 100644 pylxd/tests/models/test_storage.py

diff --git a/pylxd/client.py b/pylxd/client.py
index d4fb2a7..1e7dd77 100644
--- a/pylxd/client.py
+++ b/pylxd/client.py
@@ -46,12 +46,12 @@ def __init__(self, api_endpoint, cert=None, verify=True, timeout=None):
 
     def __getattr__(self, name):
         return self.__class__(
-            '{}/{}'.format(self._api_endpoint, name),
+            '{}/{}'.format(self._api_endpoint, name.replace('_', '-')),
             cert=self.session.cert, verify=self.session.verify)
 
     def __getitem__(self, item):
         return self.__class__(
-            '{}/{}'.format(self._api_endpoint, item),
+            '{}/{}'.format(self._api_endpoint, item.replace('_', '-')),
             cert=self.session.cert,
             verify=self.session.verify,
             timeout=self._timeout)
@@ -237,6 +237,7 @@ def __init__(
         self.networks = managers.NetworkManager(self)
         self.operations = managers.OperationManager(self)
         self.profiles = managers.ProfileManager(self)
+        self.storage_pools = managers.StoragePoolManager(self)
 
     @property
     def trusted(self):
diff --git a/pylxd/managers.py b/pylxd/managers.py
index c67e781..a7dbb7e 100644
--- a/pylxd/managers.py
+++ b/pylxd/managers.py
@@ -55,6 +55,10 @@ class SnapshotManager(BaseManager):
     manager_for = 'pylxd.models.Snapshot'
 
 
+class StoragePoolManager(BaseManager):
+    manager_for = 'pylxd.models.StoragePool'
+
+
 @contextmanager
 def web_socket_manager(manager):
     try:
diff --git a/pylxd/models/__init__.py b/pylxd/models/__init__.py
index 725fb66..5f3a42b 100644
--- a/pylxd/models/__init__.py
+++ b/pylxd/models/__init__.py
@@ -4,3 +4,4 @@
 from pylxd.models.network import Network  # NOQA
 from pylxd.models.operation import Operation  # NOQA
 from pylxd.models.profile import Profile  # NOQA
+from pylxd.models.storage_pool import StoragePool  # NOQA
diff --git a/pylxd/models/storage_pool.py b/pylxd/models/storage_pool.py
new file mode 100644
index 0000000..f6c8101
--- /dev/null
+++ b/pylxd/models/storage_pool.py
@@ -0,0 +1,55 @@
+# Copyright (c) 2016 Canonical Ltd
+#
+#    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 pylxd.models import _model as model
+
+
+class StoragePool(model.Model):
+    """A LXD storage_pool."""
+    name = model.Attribute()
+    driver = model.Attribute()
+    description = model.Attribute()
+    used_by = model.Attribute()
+    config = model.Attribute()
+    managed = model.Attribute()
+
+    @classmethod
+    def get(cls, client, name):
+        """Get a storage_pool by name."""
+        response = client.api.storage_pools[name].get()
+
+        storage_pool = cls(client, **response.json()['metadata'])
+        return storage_pool
+
+    @classmethod
+    def all(cls, client):
+        """Get all storage_pools."""
+        response = client.api.storage_pools.get()
+
+        storage_pools = []
+        for url in response.json()['metadata']:
+            name = url.split('/')[-1]
+            storage_pools.append(cls(client, name=name))
+        return storage_pools
+
+    @property
+    def api(self):
+        return self.client.api.storage_pools[self.name]
+
+    def save(self, wait=False):
+        """Save is not available for storage_pools."""
+        raise NotImplementedError('save is not implemented')
+
+    def delete(self):
+        """Delete is not available for storage_pools."""
+        raise NotImplementedError('delete is not implemented')
diff --git a/pylxd/tests/mock_lxd.py b/pylxd/tests/mock_lxd.py
index 12f3c79..d42d2f2 100644
--- a/pylxd/tests/mock_lxd.py
+++ b/pylxd/tests/mock_lxd.py
@@ -545,6 +545,32 @@ def profile_GET(request, context):
         'url': r'^http://pylxd.test/1.0/networks/lo$',
     },
 
+    # Storage Pools
+    {
+        'json': {
+            'type': 'sync',
+            'metadata': [
+                'http://pylxd.test/1.0/storage-pools/lxd',
+            ]},
+        'method': 'GET',
+        'url': r'^http://pylxd.test/1.0/storage-pools$',
+    },
+    {
+        'json': {
+            'type': 'sync',
+            'metadata': {
+                'config': {
+                    'size': '0',
+                    'source': '/var/lib/lxd/disks/lxd.img'
+                },
+                'description': '',
+                'name': 'lxd',
+                'driver': 'zfs',
+                'used_by': [],
+            }},
+        'method': 'GET',
+        'url': r'^http://pylxd.test/1.0/storage-pools/lxd$',
+    },
 
     # Profiles
     {
diff --git a/pylxd/tests/models/test_storage.py b/pylxd/tests/models/test_storage.py
new file mode 100644
index 0000000..f2373ab
--- /dev/null
+++ b/pylxd/tests/models/test_storage.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2016 Canonical Ltd
+#
+#    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 pylxd import models
+from pylxd.tests import testing
+
+
+class TestStoragePool(testing.PyLXDTestCase):
+    """Tests for pylxd.models.StoragePool."""
+
+    def test_all(self):
+        """A list of all storage_pools are returned."""
+        storage_pools = models.StoragePool.all(self.client)
+
+        self.assertEqual(1, len(storage_pools))
+
+    def test_get(self):
+        """Return a container."""
+        name = 'lxd'
+
+        an_storage_pool = models.StoragePool.get(self.client, name)
+
+        self.assertEqual(name, an_storage_pool.name)
+
+    def test_partial(self):
+        """A partial storage_pool is synced."""
+        an_storage_pool = models.StoragePool(self.client, name='lxd')
+
+        self.assertEqual('zfs', an_storage_pool.driver)
+
+    def test_delete(self):
+        """delete is not implemented in storage_pools."""
+        an_storage_pool = models.StoragePool(self.client, name='lxd')
+
+        with self.assertRaises(NotImplementedError):
+            an_storage_pool.delete()
+
+    def test_save(self):
+        """save is not implemented in storage_pools."""
+        an_storage_pool = models.StoragePool(self.client, name='lxd')
+
+        with self.assertRaises(NotImplementedError):
+            an_storage_pool.save()


More information about the lxc-devel mailing list