[lxc-devel] [pylxd/master] List operations and cancel operations added features

lasizoillo on Github lxc-bot at linuxcontainers.org
Thu Apr 12 17:40:26 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 427 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180412/76d8d044/attachment.bin>
-------------- next part --------------
From cf5a47ffa818b530e8b4b9446feae299e92aa59c Mon Sep 17 00:00:00 2001
From: "javier.lasheras" <javier.lasheras at avature.net>
Date: Thu, 12 Apr 2018 19:35:52 +0200
Subject: [PATCH] List operations and cancel operations added features

Signed-off-by: javier.lasheras <javier.lasheras at avature.net>
---
 doc/source/operations.rst            |  3 ++-
 pylxd/models/operation.py            | 34 +++++++++++++++++++++++++++++++++-
 pylxd/tests/mock_lxd.py              | 23 +++++++++++++++++++++++
 pylxd/tests/models/test_operation.py | 19 +++++++++++++++++++
 4 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/doc/source/operations.rst b/doc/source/operations.rst
index eba3754..8b3dfbc 100644
--- a/doc/source/operations.rst
+++ b/doc/source/operations.rst
@@ -13,6 +13,7 @@ Manager methods
 
 Operations can be queried through the following client manager methods:
 
+  - `all()` - List operations
   - `get()` - Get a specific network, by its name.
   - `wait_for_operation()` - get an operation, but wait until it is complete
     before returning the operation object.
@@ -23,4 +24,4 @@ Operation object methods
 
   - `wait()` - Wait for the operation to complete and return.  Note that this
     can raise a `LXDAPIExceptiion` if the operations fails.
-
+  - `cancel()` - Cancel an operation
diff --git a/pylxd/models/operation.py b/pylxd/models/operation.py
index 94e102d..8720f31 100644
--- a/pylxd/models/operation.py
+++ b/pylxd/models/operation.py
@@ -40,8 +40,28 @@ def get(cls, client, operation_id):
         response = client.api.operations[operation_id].get()
         return cls(_client=client, **response.json()['metadata'])
 
-    def __init__(self, **kwargs):
+    @classmethod
+    def all(cls, client):
+        """List of operations"""
+        response = client.api.operations.get()
+
+        operations = []
+        for op_id in response.json()['metadata']['running']:
+            operations.append(cls.get(client, op_id))
+        return operations
+
+    @property
+    def api(self):
+        return self._client.api.operations[self.id]
+
+    @property
+    def class_(self):
+        """ Avoid class as reserved keyworkds """
+        return getattr(self, "class")
+
+    def __init__(self, client=None, **kwargs):
         super(Operation, self).__init__()
+        self._client = client
         for key, value in kwargs.items():
             try:
                 setattr(self, key, value)
@@ -64,3 +84,15 @@ def wait(self):
         except KeyError:
             # Support for legacy LXD
             pass
+
+    def cancel(self):
+        """
+        Cancel an operation. If may_cancel is False do nothing.
+
+        Calling this will change the state to "cancelling" rather than
+        actually removing the entry.
+        """
+        if not self.may_cancel:
+            return
+        self.api.delete()
+        self.status = "cancelling"
diff --git a/pylxd/tests/mock_lxd.py b/pylxd/tests/mock_lxd.py
index d23004c..467a988 100644
--- a/pylxd/tests/mock_lxd.py
+++ b/pylxd/tests/mock_lxd.py
@@ -84,6 +84,13 @@ def profile_GET(request, context):
     })
 
 
+def operation_DELETE(request, context):
+    context.status_code = 200
+    return json.dumps({
+        'type': 'sync'
+    })
+
+
 RULES = [
     # General service endpoints
     {
@@ -629,6 +636,17 @@ def profile_GET(request, context):
 
 
     # Operations
+    {
+        'text': json.dumps({
+            'type': 'sync',
+            'metadata': {
+                'running': [
+                    '/1.0/operations/operation-abc'
+                ]},
+            }),
+        'method': 'GET',
+        'url': r'^http://pylxd.test/1.0/operations$',
+    },
     {
         'text': json.dumps({
             'type': 'sync',
@@ -693,5 +711,10 @@ def profile_GET(request, context):
             }),
         'method': 'GET',
         'url': r'^http://pylxd2.test/1.0/operations/images-create-operation/wait$',  # NOQA
+    },
+    {
+        'text': operation_DELETE,
+        'method': 'DELETE',
+        'url': r'http://pylxd.test/1.0/operations/cancel-test$'
     }
 ]
diff --git a/pylxd/tests/models/test_operation.py b/pylxd/tests/models/test_operation.py
index d42b83e..9dc5eda 100644
--- a/pylxd/tests/models/test_operation.py
+++ b/pylxd/tests/models/test_operation.py
@@ -72,3 +72,22 @@ def test_unknown_attribute(self):
         })
         url = '/1.0/operations/operation-unknown'
         models.Operation.get(self.client, url)
+
+    def test_all(self):
+        operations = models.Operation.all(self.client)
+
+        self.assertEqual(1, len(operations))
+
+    def test_cancel(self):
+        non_cancellable = {
+            "id": "cancel-test",
+            "may_cancel": False,
+            "status": "Running"
+        }
+        operation = models.Operation(client=self.client, **non_cancellable)
+        operation.cancel()
+        self.assertEqual(operation.status, "Running")
+
+        operation.may_cancel = True
+        operation.cancel()
+        self.assertEqual(operation.status, "cancelling")


More information about the lxc-devel mailing list