You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2015/06/13 14:44:12 UTC

[2/7] libcloud git commit: Added Gandi keypair management

Added Gandi keypair management

Closes #534

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/3fe88d07
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/3fe88d07
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/3fe88d07

Branch: refs/heads/trunk
Commit: 3fe88d073351555909b71818483735a09854a53d
Parents: 562e4d2
Author: ZuluPro <mo...@hotmail.com>
Authored: Wed May 27 18:26:34 2015 -0400
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sat Jun 13 20:31:58 2015 +0800

----------------------------------------------------------------------
 libcloud/compute/drivers/gandi.py               | 59 +++++++++++++++++---
 .../test/compute/fixtures/gandi/ssh_delete.xml  |  8 +++
 .../test/compute/fixtures/gandi/ssh_info.xml    | 25 +++++++++
 .../test/compute/fixtures/gandi/ssh_list.xml    | 23 ++++++++
 libcloud/test/compute/test_gandi.py             | 33 +++++++++++
 5 files changed, 141 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/3fe88d07/libcloud/compute/drivers/gandi.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/gandi.py b/libcloud/compute/drivers/gandi.py
index 7a54ada..420d25d 100644
--- a/libcloud/compute/drivers/gandi.py
+++ b/libcloud/compute/drivers/gandi.py
@@ -215,12 +215,15 @@ class GandiNodeDriver(BaseGandiDriver, NodeDriver):
         :keyword    inet_family: version of ip to use, default 4 (optional)
         :type       inet_family: ``int``
 
+        :keyword    keypairs: IDs of keypairs or Keypairs object
+        :type       keypairs: ``int`` or :class:`.KeyPair`
+
         :rtype: :class:`Node`
         """
 
-        if kwargs.get('login') is None or kwargs.get('password') is None:
-            raise GandiException(
-                1020, 'login and password must be defined for node creation')
+        if not kwargs.get('login') and not kwargs.get('keypairs'):
+            raise GandiException(1020, "Login and password or ssh keypair "
+                                 "must be defined for node creation")
 
         location = kwargs.get('location')
         if location and isinstance(location, NodeLocation):
@@ -234,6 +237,12 @@ class GandiNodeDriver(BaseGandiDriver, NodeDriver):
             raise GandiException(
                 1022, 'size must be a subclass of NodeSize')
 
+        keypairs = kwargs.get('keypairs', [])
+        keypair_ids = [
+            k if isinstance(k, int) else k.extra['id']
+            for k in keypairs
+        ]
+
         # If size name is in INSTANCE_TYPE we use new rating model
         instance = INSTANCE_TYPES.get(size.id)
         cores = instance['cpu'] if instance else int(size.id)
@@ -248,14 +257,20 @@ class GandiNodeDriver(BaseGandiDriver, NodeDriver):
         vm_spec = {
             'datacenter_id': dc_id,
             'hostname': kwargs['name'],
-            'login': kwargs['login'],
-            'password': kwargs['password'],  # TODO : use NodeAuthPassword
             'memory': int(size.ram),
             'cores': cores,
             'bandwidth': int(size.bandwidth),
             'ip_version': kwargs.get('inet_family', 4),
         }
 
+        if kwargs.get('login') and kwargs.get('password'):
+            vm_spec.update({
+                'login': kwargs['login'],
+                'password': kwargs['password'],  # TODO : use NodeAuthPassword
+            })
+        if keypair_ids:
+            vm_spec['keys'] = keypair_ids
+
         # Call create_from helper api. Return 3 operations : disk_create,
         # iface_create,vm_create
         (op_disk, op_iface, op_vm) = self.connection.request(
@@ -535,7 +550,6 @@ class GandiNodeDriver(BaseGandiDriver, NodeDriver):
         :param      node: Node which should be used
         :type       node: :class:`Node`
 
-
         :param      iface: Network interface which should be used
         :type       iface: :class:`GandiNetworkInterface`
 
@@ -554,7 +568,6 @@ class GandiNodeDriver(BaseGandiDriver, NodeDriver):
         :param      node: Node which should be used
         :type       node: :class:`Node`
 
-
         :param      iface: Network interface which should be used
         :type       iface: :class:`GandiNetworkInterface`
 
@@ -652,3 +665,35 @@ class GandiNodeDriver(BaseGandiDriver, NodeDriver):
         filter_params = {'name': name}
         kps = self.connection.request('hosting.ssh.list', filter_params).object
         return self._to_key_pair(kps[0])
+
+    def import_key_pair_from_string(self, name, key_material):
+        """
+        Create a new key pair object.
+
+        :param name: Key pair name.
+        :type name: ``str``
+
+        :param key_material: Public key material.
+        :type key_material: ``str``
+
+        :return: Imported key pair object.
+        :rtype: :class:`.KeyPair`
+        """
+        params = {'name': name, 'value': key_material}
+        kp = self.connection.request('hosting.ssh.create', params).object
+        return self._to_key_pair(kp)
+
+    def delete_key_pair(self, key_pair):
+        """
+        Delete an existing key pair.
+
+        :param key_pair: Key pair object or ID.
+        :type key_pair: :class.KeyPair` or ``int``
+
+        :return:   True of False based on success of Keypair deletion
+        :rtype:    ``bool``
+        """
+        key_id = key_pair if isinstance(key_pair, int) \
+            else key_pair.extra['id']
+        success = self.connection.request('hosting.ssh.delete', key_id).object
+        return success

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3fe88d07/libcloud/test/compute/fixtures/gandi/ssh_delete.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/gandi/ssh_delete.xml b/libcloud/test/compute/fixtures/gandi/ssh_delete.xml
new file mode 100644
index 0000000..6dbecc1
--- /dev/null
+++ b/libcloud/test/compute/fixtures/gandi/ssh_delete.xml
@@ -0,0 +1,8 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<methodResponse>
+<params>
+<param>
+<value><boolean>1</boolean></value>
+</param>
+</params>
+</methodResponse>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3fe88d07/libcloud/test/compute/fixtures/gandi/ssh_info.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/gandi/ssh_info.xml b/libcloud/test/compute/fixtures/gandi/ssh_info.xml
new file mode 100644
index 0000000..b48bace
--- /dev/null
+++ b/libcloud/test/compute/fixtures/gandi/ssh_info.xml
@@ -0,0 +1,25 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<methodResponse>
+<params>
+<param>
+<value><struct>
+<member>
+<name>fingerprint</name>
+<value><string>a6:1f:b8:b4:19:91:99:d8:af:ab:d6:17:72:8b:d1:6c</string></value>
+</member>
+<member>
+<name>name</name>
+<value><string>testkey</string></value>
+</member>
+<member>
+<name>value</name>
+<value><string>ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCaCXFxl0cPZa+PkXSaux/9Sfn4J81eNJ4f/ZkjdIlmLJVYFUKbpC16eEwXYEfw/QBAZFPODCDQOFAZdgajO572y9scp09F7L7Rhwrw7DYu8STMIBz0XBIO8eOUyu5hVRpxaZGDih9B99e1hITTGFg+BveAmrdB8CPtygKo/fUmaamrocZBrD1betaLTC0i6/DVz7YAbR0CleZLlaBogqVhqmS0TB4J67aG2vvq1MjyOixQY5Ab4aXo4Dz1jd7oqCGCKCO9oKAG0ok94foxkfnCmfRrnfWzOA7SFWjUs65SOrGYZghspDcbJ9vA4ZkUuWJXPPvLVgsI8aHwkezJPD8Th root@testhost</string></value>
+</member>
+<member>
+<name>id</name>
+<value><int>10</int></value>
+</member>
+</struct></value>
+</param>
+</params>
+</methodResponse>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3fe88d07/libcloud/test/compute/fixtures/gandi/ssh_list.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/gandi/ssh_list.xml b/libcloud/test/compute/fixtures/gandi/ssh_list.xml
new file mode 100644
index 0000000..003e546
--- /dev/null
+++ b/libcloud/test/compute/fixtures/gandi/ssh_list.xml
@@ -0,0 +1,23 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<methodResponse>
+<params>
+<param>
+<value><array><data>
+<value><struct>
+<member>
+<name>fingerprint</name>
+<value><string>a6:1f:b8:b4:19:91:99:d8:af:ab:d6:17:72:8b:d1:6c</string></value>
+</member>
+<member>
+<name>id</name>
+<value><int>10</int></value>
+</member>
+<member>
+<name>name</name>
+<value><string>testkey</string></value>
+</member>
+</struct></value>
+</data></array></value>
+</param>
+</params>
+</methodResponse>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3fe88d07/libcloud/test/compute/test_gandi.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_gandi.py b/libcloud/test/compute/test_gandi.py
index e4a11e8..5336820 100644
--- a/libcloud/test/compute/test_gandi.py
+++ b/libcloud/test/compute/test_gandi.py
@@ -154,6 +154,23 @@ class GandiTests(unittest.TestCase):
         disks = self.driver.list_volumes()
         self.assertTrue(self.driver.ex_update_disk(disks[0], new_size=4096))
 
+    def test_list_key_pairs(self):
+        keys = self.driver.list_key_pairs()
+        self.assertGreater(len(keys), 0)
+
+    def test_get_key_pair(self):
+        key = self.driver.get_key_pair(10)
+        self.assertEqual(key.name, 'testkey')
+
+    def test_import_key_pair_from_string(self):
+        key = self.driver.import_key_pair_from_string('testkey', '12345')
+        self.assertEqual(key.name, 'testkey')
+        self.assertEqual(key.extra['id'], 10)
+
+    def test_delete_key_pair(self):
+        response = self.driver.delete_key_pair(10)
+        self.assertTrue(response)
+
 
 class GandiRatingTests(unittest.TestCase):
 
@@ -285,6 +302,22 @@ class GandiMockHttp(BaseGandiMockHttp):
         body = self.fixtures.load('disk_delete.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def _xmlrpc__hosting_ssh_info(self, method, url, body, headers):
+        body = self.fixtures.load('ssh_info.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _xmlrpc__hosting_ssh_list(self, method, url, body, headers):
+        body = self.fixtures.load('ssh_list.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _xmlrpc__hosting_ssh_create(self, method, url, body, headers):
+        body = self.fixtures.load('ssh_info.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _xmlrpc__hosting_ssh_delete(self, method, url, body, headers):
+        body = self.fixtures.load('ssh_delete.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
 
 class GandiMockRatingHttp(BaseGandiMockHttp):