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 2014/08/31 18:41:43 UTC
git commit: Adds the following methods for the Softlayer driver: -
list_key_pairs() - get_key_pair() - import_key_pair_from_string() -
delete_key_pair() - create_key_pair() (only if Pycripto is installed)
Repository: libcloud
Updated Branches:
refs/heads/trunk 860674ac7 -> f007edaaf
Adds the following methods for the Softlayer driver: - list_key_pairs() - get_key_pair() - import_key_pair_from_string() - delete_key_pair() - create_key_pair() (only if Pycripto is installed)
Adds tests for all new methods.
Modifies the test_create_node() to use an ssh key.
Adds a new property on the Softlayer node "ex_keyname"which is the name of the key to be associated to the new node.
Closes #354
Signed-off-by: Tomaz Muraus <to...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/f007edaa
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/f007edaa
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/f007edaa
Branch: refs/heads/trunk
Commit: f007edaafcae79afb2890e75cd2ba1f91aa26d7e
Parents: 860674a
Author: Itxaka Serrano <it...@virdata.com>
Authored: Sun Aug 31 18:07:14 2014 +0200
Committer: Tomaz Muraus <to...@apache.org>
Committed: Sun Aug 31 18:34:45 2014 +0200
----------------------------------------------------------------------
CHANGES.rst | 4 +
libcloud/compute/drivers/softlayer.py | 96 +++++++++++++++++++-
.../v3__SoftLayer_Account_getSshKeys.xml | 63 +++++++++++++
..._SoftLayer_Security_Ssh_Key_createObject.xml | 39 ++++++++
..._SoftLayer_Security_Ssh_Key_deleteObject.xml | 15 +++
...v3__SoftLayer_Security_Ssh_Key_getObject.xml | 33 +++++++
libcloud/test/compute/test_softlayer.py | 64 ++++++++++++-
7 files changed, 308 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/f007edaa/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index 53345c8..69ab399 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -78,6 +78,10 @@ Compute
(LIBCLOUD-544, GITHUB-349, GITHUB-353)
[Raphael Theberge]
+- Add SSH key pair management methods to the Softlayer driver.
+ (GITHUB-321, GITHUB-354)
+ [Itxaka Serrano]
+
Storage
~~~~~~~
http://git-wip-us.apache.org/repos/asf/libcloud/blob/f007edaa/libcloud/compute/drivers/softlayer.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/softlayer.py b/libcloud/compute/drivers/softlayer.py
index 4fe8cdd..61a1e1a 100644
--- a/libcloud/compute/drivers/softlayer.py
+++ b/libcloud/compute/drivers/softlayer.py
@@ -17,13 +17,19 @@ Softlayer driver
"""
import time
+try:
+ from Crypto.PublicKey import RSA
+ crypto = True
+except ImportError:
+ crypto = False
from libcloud.common.base import ConnectionUserAndKey
from libcloud.common.xmlrpc import XMLRPCResponse, XMLRPCConnection
from libcloud.common.types import InvalidCredsError, LibcloudError
from libcloud.compute.types import Provider, NodeState
from libcloud.compute.base import NodeDriver, Node, NodeLocation, NodeSize, \
- NodeImage
+ NodeImage, KeyPair
+from libcloud.compute.types import KeyPairDoesNotExistError
DEFAULT_DOMAIN = 'example.com'
DEFAULT_CPU_SIZE = 1
@@ -158,7 +164,6 @@ class SoftLayerConnection(XMLRPCConnection, ConnectionUserAndKey):
args = ({'headers': headers}, ) + args
endpoint = '%s/%s' % (self.endpoint, service)
-
return super(SoftLayerConnection, self).request(method, *args,
**{'endpoint':
endpoint})
@@ -204,7 +209,7 @@ class SoftLayerNodeDriver(NodeDriver):
website = 'http://www.softlayer.com/'
type = Provider.SOFTLAYER
- features = {'create_node': ['generates_password']}
+ features = {'create_node': ['generates_password', 'ssh_key']}
def _to_node(self, host):
try:
@@ -330,6 +335,8 @@ class SoftLayerNodeDriver(NodeDriver):
:type ex_datacenter: ``str``
:keyword ex_os: e.g. UBUNTU_LATEST
:type ex_os: ``str``
+ :keyword ex_keyname: The name of the key pair
+ :type ex_keyname: ``str``
"""
name = kwargs['name']
os = 'DEBIAN_LATEST'
@@ -402,6 +409,9 @@ class SoftLayerNodeDriver(NodeDriver):
if datacenter:
newCCI['datacenter'] = {'name': datacenter}
+ if 'ex_keyname' in kwargs:
+ newCCI['sshKeys'] = [self._key_name_to_id(kwargs['ex_keyname'])]
+
res = self.connection.request(
'SoftLayer_Virtual_Guest', 'createObject', newCCI
).object
@@ -411,6 +421,59 @@ class SoftLayerNodeDriver(NodeDriver):
return self._to_node(raw_node)
+ def list_key_pairs(self):
+ result = self.connection.request(
+ 'SoftLayer_Account', 'getSshKeys'
+ ).object
+ elems = [x for x in result]
+ key_pairs = self._to_key_pairs(elems=elems)
+ return key_pairs
+
+ def get_key_pair(self, name):
+ key_id = self._key_name_to_id(name=name)
+ result = self.connection.request(
+ 'SoftLayer_Security_Ssh_Key', 'getObject', id=key_id
+ ).object
+ return self._to_key_pair(result)
+
+ # TODO: Check this with the libcloud guys,
+ # can we create new dependencies?
+ def create_key_pair(self, name, ex_size=4096):
+ if crypto is False:
+ raise NotImplementedError('create_key_pair needs'
+ 'the pycrypto library')
+ key = RSA.generate(ex_size)
+ new_key = {
+ 'key': key.publickey().exportKey('OpenSSH'),
+ 'label': name,
+ 'notes': '',
+ }
+ result = self.connection.request(
+ 'SoftLayer_Security_Ssh_Key', 'createObject', new_key
+ ).object
+ result['private'] = key.exportKey('PEM')
+ return self._to_key_pair(result)
+
+ def import_key_pair_from_string(self, name, key_material):
+ new_key = {
+ 'key': key_material,
+ 'label': name,
+ 'notes': '',
+ }
+ result = self.connection.request(
+ 'SoftLayer_Security_Ssh_Key', 'createObject', new_key
+ ).object
+
+ key_pair = self._to_key_pair(result)
+ return key_pair
+
+ def delete_key_pair(self, key_pair):
+ key = self._key_name_to_id(key_pair)
+ result = self.connection.request(
+ 'SoftLayer_Security_Ssh_Key', 'deleteObject', id=key
+ ).object
+ return result
+
def _to_image(self, img):
return NodeImage(
id=img['template']['operatingSystemReferenceCode'],
@@ -467,8 +530,31 @@ class SoftLayerNodeDriver(NodeDriver):
},
}
res = self.connection.request(
- "SoftLayer_Account",
- "getVirtualGuests",
+ 'SoftLayer_Account',
+ 'getVirtualGuests',
object_mask=mask
).object
return [self._to_node(h) for h in res]
+
+ def _to_key_pairs(self, elems):
+ key_pairs = [self._to_key_pair(elem=elem) for elem in elems]
+ return key_pairs
+
+ def _to_key_pair(self, elem):
+ key_pair = KeyPair(name=elem['label'],
+ public_key=elem['key'],
+ fingerprint=elem['fingerprint'],
+ private_key=elem.get('private', None),
+ driver=self,
+ extra={'id': elem['id']})
+ return key_pair
+
+ def _key_name_to_id(self, name):
+ result = self.connection.request(
+ 'SoftLayer_Account', 'getSshKeys'
+ ).object
+ key_id = [x for x in result if x['label'] == name]
+ if len(key_id) == 0:
+ raise KeyPairDoesNotExistError(name, self)
+ else:
+ return int(key_id[0]['id'])
http://git-wip-us.apache.org/repos/asf/libcloud/blob/f007edaa/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Account_getSshKeys.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Account_getSshKeys.xml b/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Account_getSshKeys.xml
new file mode 100644
index 0000000..a06952c
--- /dev/null
+++ b/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Account_getSshKeys.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<params>
+ <param>
+ <value>
+ <struct>
+ <member>
+ <name>id</name>
+ <value>
+ <int>1</int>
+ </value>
+ </member>
+ <member>
+ <name>key</name>
+ <value>
+ <string>ssh-key</string>
+ </value>
+ </member>
+ <member>
+ <name>label</name>
+ <value>
+ <string>test1</string>
+ </value>
+ </member>
+ <member>
+ <name>fingerprint</name>
+ <value>
+ <string>00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00</string>
+ </value>
+ </member>
+ </struct>
+ </value>
+ </param>
+ <param>
+ <value>
+ <struct>
+ <member>
+ <name>id</name>
+ <value>
+ <int>2</int>
+ </value>
+ </member>
+ <member>
+ <name>key</name>
+ <value>
+ <string>ssh-key</string>
+ </value>
+ </member>
+ <member>
+ <name>label</name>
+ <value>
+ <string>test2</string>
+ </value>
+ </member>
+ <member>
+ <name>fingerprint</name>
+ <value>
+ <string>00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00</string>
+ </value>
+ </member>
+ </struct>
+ </value>
+ </param>
+</params>
http://git-wip-us.apache.org/repos/asf/libcloud/blob/f007edaa/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_createObject.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_createObject.xml b/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_createObject.xml
new file mode 100644
index 0000000..716832e
--- /dev/null
+++ b/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_createObject.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<params>
+ <param>
+ <value>
+ <struct>
+ <member>
+ <name>id</name>
+ <value>
+ <int>1</int>
+ </value>
+ </member>
+ <member>
+ <name>key</name>
+ <value>
+ <string>ssh-key</string>
+ </value>
+ </member>
+ <member>
+ <name>label</name>
+ <value>
+ <string>my-key-pair</string>
+ </value>
+ </member>
+ <member>
+ <name>label</name>
+ <value>
+ <string>my-key-pair</string>
+ </value>
+ </member>
+ <member>
+ <name>fingerprint</name>
+ <value>
+ <string>1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f</string>
+ </value>
+ </member>
+ </struct>
+ </value>
+ </param>
+</params>
http://git-wip-us.apache.org/repos/asf/libcloud/blob/f007edaa/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_deleteObject.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_deleteObject.xml b/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_deleteObject.xml
new file mode 100644
index 0000000..119680e
--- /dev/null
+++ b/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_deleteObject.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<params>
+ <param>
+ <value>
+ <struct>
+ <member>
+ <name>status</name>
+ <value>
+ <string>success</string>
+ </value>
+ </member>
+ </struct>
+ </value>
+ </param>
+</params>
http://git-wip-us.apache.org/repos/asf/libcloud/blob/f007edaa/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_getObject.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_getObject.xml b/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_getObject.xml
new file mode 100644
index 0000000..cf96523
--- /dev/null
+++ b/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Security_Ssh_Key_getObject.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<params>
+ <param>
+ <value>
+ <struct>
+ <member>
+ <name>id</name>
+ <value>
+ <int>1</int>
+ </value>
+ </member>
+ <member>
+ <name>key</name>
+ <value>
+ <string>ssh-key</string>
+ </value>
+ </member>
+ <member>
+ <name>label</name>
+ <value>
+ <string>test1</string>
+ </value>
+ </member>
+ <member>
+ <name>fingerprint</name>
+ <value>
+ <string>00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00</string>
+ </value>
+ </member>
+ </struct>
+ </value>
+ </param>
+</params>
http://git-wip-us.apache.org/repos/asf/libcloud/blob/f007edaa/libcloud/test/compute/test_softlayer.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_softlayer.py b/libcloud/test/compute/test_softlayer.py
index 74f4a32..8f4536b 100644
--- a/libcloud/test/compute/test_softlayer.py
+++ b/libcloud/test/compute/test_softlayer.py
@@ -16,6 +16,13 @@
import unittest
import sys
+try:
+ import Crypto
+ Crypto
+ crypto = True
+except ImportError:
+ crypto = False
+
from libcloud.common.types import InvalidCredsError
from libcloud.utils.py3 import httplib
@@ -25,12 +32,15 @@ from libcloud.utils.py3 import next
from libcloud.compute.drivers.softlayer import SoftLayerNodeDriver as SoftLayer
from libcloud.compute.drivers.softlayer import SoftLayerException, \
NODE_STATE_MAP
-from libcloud.compute.types import NodeState
+from libcloud.compute.types import NodeState, KeyPairDoesNotExistError
from libcloud.test import MockHttp # pylint: disable-msg=E0611
from libcloud.test.file_fixtures import ComputeFileFixtures
from libcloud.test.secrets import SOFTLAYER_PARAMS
+null_fingerprint = '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:' + \
+ '00:00:00:00:00'
+
class SoftLayerTests(unittest.TestCase):
@@ -119,6 +129,7 @@ class SoftLayerTests(unittest.TestCase):
ex_cpus=2,
ex_ram=2048,
ex_disk=100,
+ ex_key='test1',
ex_bandwidth=10,
ex_local_disk=False,
ex_datacenter='Dal05',
@@ -132,6 +143,37 @@ class SoftLayerTests(unittest.TestCase):
node = self.driver.list_nodes()[0]
self.driver.destroy_node(node)
+ def test_list_keypairs(self):
+ keypairs = self.driver.list_key_pairs()
+ self.assertEqual(len(keypairs), 2)
+ self.assertEqual(keypairs[0].name, 'test1')
+ self.assertEqual(keypairs[0].fingerprint, null_fingerprint)
+
+ def test_get_key_pair(self):
+ key_pair = self.driver.get_key_pair(name='test1')
+ self.assertEqual(key_pair.name, 'test1')
+
+ def test_get_key_pair_does_not_exist(self):
+ self.assertRaises(KeyPairDoesNotExistError, self.driver.get_key_pair,
+ name='test-key-pair')
+
+ def test_create_key_pair(self):
+ if crypto:
+ key_pair = self.driver.create_key_pair(name='my-key-pair')
+ fingerprint = ('1f:51:ae:28:bf:89:e9:d8:1f:25:5d'
+ ':37:2d:7d:b8:ca:9f:f5:f1:6f')
+
+ self.assertEqual(key_pair.name, 'my-key-pair')
+ self.assertEqual(key_pair.fingerprint, fingerprint)
+ self.assertTrue(key_pair.private_key is not None)
+ else:
+ self.assertRaises(NotImplementedError, self.driver.create_key_pair,
+ name='my-key-pair')
+
+ def test_delete_key_pair(self):
+ success = self.driver.delete_key_pair('test1')
+ self.assertTrue(success)
+
class SoftLayerMockHttp(MockHttp):
fixtures = ComputeFileFixtures('softlayer')
@@ -188,6 +230,26 @@ class SoftLayerMockHttp(MockHttp):
body = self.fixtures.load('empty.xml')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ def _xmlrpc_v3_SoftLayer_Account_getSshKeys(
+ self, method, url, body, headers):
+ body = self.fixtures.load('v3__SoftLayer_Account_getSshKeys.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc_v3_SoftLayer_Security_Ssh_Key_getObject(
+ self, method, url, body, headers):
+ body = self.fixtures.load('v3__SoftLayer_Security_Ssh_Key_getObject.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc_v3_SoftLayer_Security_Ssh_Key_createObject(
+ self, method, url, body, headers):
+ body = self.fixtures.load('v3__SoftLayer_Security_Ssh_Key_createObject.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _xmlrpc_v3_SoftLayer_Security_Ssh_Key_deleteObject(
+ self, method, url, body, headers):
+ body = self.fixtures.load('v3__SoftLayer_Security_Ssh_Key_deleteObject.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
if __name__ == '__main__':
sys.exit(unittest.main())