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 2013/12/10 22:08:35 UTC
[2/8] git commit: Update existing compute drivers (OpenStack,
CloudStack,
EC2) which expose key pair management through the extension methods to expose
it through a new standard key pair management API.
Update existing compute drivers (OpenStack, CloudStack, EC2) which expose key
pair management through the extension methods to expose it through a new
standard key pair management API.
Also update affected code and tests, deprecate existing extension methods and
add some missing tests.
Note: Old and now deprecated methods will work until a next major release.
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/b398aebd
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/b398aebd
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/b398aebd
Branch: refs/heads/trunk
Commit: b398aebdbb50fbba06b46b466e95904c96c1ad99
Parents: eed9777
Author: Tomaz Muraus <to...@apache.org>
Authored: Fri Dec 6 15:36:09 2013 +0100
Committer: Tomaz Muraus <to...@apache.org>
Committed: Sun Dec 8 13:45:42 2013 +0100
----------------------------------------------------------------------
libcloud/compute/drivers/cloudstack.py | 290 +++++++++++++++----
libcloud/compute/drivers/ec2.py | 196 +++++++++----
libcloud/compute/drivers/openstack.py | 96 ++++--
.../cloudstack/createSSHKeyPair_default.json | 1 +
.../compute/fixtures/ec2/create_key_pair.xml | 22 ++
libcloud/test/compute/test_cloudstack.py | 72 +++--
libcloud/test/compute/test_ec2.py | 57 +++-
libcloud/test/compute/test_openstack.py | 26 +-
8 files changed, 567 insertions(+), 193 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/b398aebd/libcloud/compute/drivers/cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/cloudstack.py b/libcloud/compute/drivers/cloudstack.py
index 27498fd..e9742fa 100644
--- a/libcloud/compute/drivers/cloudstack.py
+++ b/libcloud/compute/drivers/cloudstack.py
@@ -15,16 +15,17 @@
from __future__ import with_statement
-import os
import base64
+import warnings
from libcloud.utils.py3 import b
from libcloud.utils.py3 import urlparse
from libcloud.compute.providers import Provider
from libcloud.common.cloudstack import CloudStackDriverMixIn
-from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeLocation,\
- NodeSize, StorageVolume
+from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeLocation
+from libcloud.compute.base import NodeSize, StorageVolume
+from libcloud.compute.base import KeyPair
from libcloud.compute.types import NodeState, LibcloudError
from libcloud.utils.networking import is_private_subnet
@@ -649,6 +650,147 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
driver=self))
return list_volumes
+ def list_key_pairs(self, **kwargs):
+ """
+ List registered key pairs.
+
+ :param projectid: list objects by project
+ :type projectid: ``str``
+
+ :param page: The page to list the keypairs from
+ :type page: ``int``
+
+ :param keyword: List by keyword
+ :type keyword: ``str``
+
+ :param listall: If set to false, list only resources
+ belonging to the command's caller;
+ if set to true - list resources that
+ the caller is authorized to see.
+ Default value is false
+
+ :type listall: ``bool``
+
+ :param pagesize: The number of results per page
+ :type pagesize: ``int``
+
+ :param account: List resources by account.
+ Must be used with the domainId parameter
+ :type account: ``str``
+
+ :param isrecursive: Defaults to false, but if true,
+ lists all resources from
+ the parent specified by the
+ domainId till leaves.
+ :type isrecursive: ``bool``
+
+ :param fingerprint: A public key fingerprint to look for
+ :type fingerprint: ``str``
+
+ :param name: A key pair name to look for
+ :type name: ``str``
+
+ :param domainid: List only resources belonging to
+ the domain specified
+ :type domainid: ``str``
+
+ :return: A list of key par objects.
+ :rtype: ``list`` of :class:`libcloud.compute.base.KeyPair`
+ """
+ extra_args = kwargs.copy()
+ res = self._sync_request(command='listSSHKeyPairs',
+ params=extra_args,
+ method='GET')
+ key_pairs = res.get('sshkeypair', [])
+ key_pairs = self._to_key_pairs(data=key_pairs)
+ return key_pairs
+
+ def create_key_pair(self, name, **kwargs):
+ """
+ Create a new key pair object.
+
+ :param name: Key pair name.
+ :type name: ``str``
+
+ :param name: Name of the keypair (required)
+ :type name: ``str``
+
+ :param projectid: An optional project for the ssh key
+ :type projectid: ``str``
+
+ :param domainid: An optional domainId for the ssh key.
+ If the account parameter is used,
+ domainId must also be used.
+ :type domainid: ``str``
+
+ :param account: An optional account for the ssh key.
+ Must be used with domainId.
+ :type account: ``str``
+
+ :return: Created key pair object.
+ :rtype: :class:`libcloud.compute.base.KeyPair`
+ """
+ extra_args = kwargs.copy()
+
+ params = {'name': name}
+ params.update(extra_args)
+
+ res = self._sync_request(command='createSSHKeyPair',
+ params=params,
+ method='GET')
+ key_pair = self._to_key_pair(data=res['keypair'])
+ return key_pair
+
+ def import_key_pair_from_string(self, name, key_material):
+ """
+ Import a new public key from string.
+
+ :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:`libcloud.compute.base.KeyPair`
+ """
+ res = self._sync_request(command='registerSSHKeyPair',
+ params={'name': name,
+ 'publickey': key_material},
+ method='GET')
+ key_pair = self._to_key_pair(data=res['keypair'])
+ return key_pair
+
+ def delete_key_pair(self, key_pair, **kwargs):
+ """
+ Delete an existing key pair.
+
+ :param key_pair: Key pair object.
+ :type key_pair: :class`libcloud.compute.base.KeyPair`
+
+ :param projectid: The project associated with keypair
+ :type projectid: ``str``
+
+ :param domainid : The domain ID associated with the keypair
+ :type domainid: ``str``
+
+ :param account : The account associated with the keypair.
+ Must be used with the domainId parameter.
+ :type account: ``str``
+
+ :return: True of False based on success of Keypair deletion
+ :rtype: ``bool``
+ """
+
+ extra_args = kwargs.copy()
+ params = {'name': key_pair.name}
+ params.update(extra_args)
+
+ res = self._sync_request(command='deleteSSHKeyPair',
+ params=params,
+ method='GET')
+ return res['success'] == 'true'
+
def ex_list_public_ips(self):
"""
Lists all Public IP Addresses.
@@ -914,13 +1056,22 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
:return: A list of keypair dictionaries
:rtype: ``list`` of ``dict``
"""
+ warnings.warn('This method has been deprecated in favor of '
+ 'list_key_pairs method')
- extra_args = kwargs.copy()
- res = self._sync_request(command='listSSHKeyPairs',
- params=extra_args,
- method='GET')
- keypairs = res.get('sshkeypair', [])
- return keypairs
+ key_pairs = self.list_key_pairs(**kwargs)
+
+ result = []
+
+ for key_pair in key_pairs:
+ item = {
+ 'name': key_pair.name,
+ 'fingerprint': key_pair.fingerprint,
+ 'privateKey': key_pair.private_key
+ }
+ result.append(item)
+
+ return result
def ex_create_keypair(self, name, **kwargs):
"""
@@ -944,50 +1095,18 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
:return: A keypair dictionary
:rtype: ``dict``
"""
- extra_args = kwargs.copy()
-
- for keypair in self.ex_list_keypairs():
- if keypair['name'] == name:
- raise LibcloudError('SSH KeyPair with name=%s already exists'
- % (name))
-
- params = {'name': name}
- params.update(extra_args)
-
- res = self._sync_request(command='createSSHKeyPair',
- params=params,
- method='GET')
- return res['keypair']
-
- def ex_delete_keypair(self, keypair, **kwargs):
- """
- Deletes an existing SSH KeyPair
-
- :param keypair: Name of the keypair (required)
- :type keypair: ``str``
-
- :param projectid: The project associated with keypair
- :type projectid: ``str``
-
- :param domainid : The domain ID associated with the keypair
- :type domainid: ``str``
+ warnings.warn('This method has been deprecated in favor of '
+ 'create_key_pair method')
- :param account : The account associated with the keypair.
- Must be used with the domainId parameter.
- :type account: ``str``
-
- :return: True of False based on success of Keypair deletion
- :rtype: ``bool``
- """
+ key_pair = self.create_key_pair(name=name, **kwargs)
- extra_args = kwargs.copy()
- params = {'name': keypair}
- params.update(extra_args)
+ result = {
+ 'name': key_pair.name,
+ 'fingerprint': key_pair.fingerprint,
+ 'privateKey': key_pair.private_key
+ }
- res = self._sync_request(command='deleteSSHKeyPair',
- params=params,
- method='GET')
- return res['success']
+ return result
def ex_import_keypair_from_string(self, name, key_material):
"""
@@ -1001,15 +1120,18 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
:rtype: ``dict``
"""
- res = self._sync_request(command='registerSSHKeyPair',
- params={'name': name,
- 'publickey': key_material},
- method='GET')
- return {
- 'keyName': res['keypair']['name'],
- 'keyFingerprint': res['keypair']['fingerprint']
+ warnings.warn('This method has been deprecated in favor of '
+ 'import_key_pair_from_string method')
+
+ key_pair = self.import_key_pair_from_string(name=name,
+ key_material=key_material)
+ result = {
+ 'keyName': key_pair.name,
+ 'keyFingerprint': key_pair.fingerprint
}
+ return result
+
def ex_import_keypair(self, name, keyfile):
"""
Imports a new public key where the public key is passed via a filename
@@ -1022,9 +1144,45 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
:rtype: ``dict``
"""
- with open(os.path.expanduser(keyfile)) as fh:
- content = fh.read()
- return self.ex_import_keypair_from_string(name, content)
+ warnings.warn('This method has been deprecated in favor of '
+ 'import_key_pair_from_file method')
+
+ key_pair = self.import_key_pair_from_file(name=name,
+ key_file_path=keyfile)
+ result = {
+ 'keyName': key_pair.name,
+ 'keyFingerprint': key_pair.fingerprint
+ }
+
+ return result
+
+ def ex_delete_keypair(self, keypair, **kwargs):
+ """
+ Deletes an existing SSH KeyPair
+
+ :param keypair: Name of the keypair (required)
+ :type keypair: ``str``
+
+ :param projectid: The project associated with keypair
+ :type projectid: ``str``
+
+ :param domainid : The domain ID associated with the keypair
+ :type domainid: ``str``
+
+ :param account : The account associated with the keypair.
+ Must be used with the domainId parameter.
+ :type account: ``str``
+
+ :return: True of False based on success of Keypair deletion
+ :rtype: ``bool``
+ """
+ warnings.warn('This method has been deprecated in favor of '
+ 'delete_key_pair method')
+
+ key_pair = KeyPair(name=keypair, public_key=None, fingerprint=None,
+ driver=self)
+
+ return self.delete_key_pair(key_pair=key_pair)
def ex_list_security_groups(self, **kwargs):
"""
@@ -1313,3 +1471,15 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
public_ips=public_ips, private_ips=private_ips,
driver=self, extra=extra)
return node
+
+ def _to_key_pairs(self, data):
+ key_pairs = [self._to_key_pair(data=item) for item in data]
+ return key_pairs
+
+ def _to_key_pair(self, data):
+ key_pair = KeyPair(name=data['name'],
+ fingerprint=data['fingerprint'],
+ public_key=data.get('publicKey', None),
+ private_key=data.get('privateKey', None),
+ driver=self)
+ return key_pair
http://git-wip-us.apache.org/repos/asf/libcloud/blob/b398aebd/libcloud/compute/drivers/ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py
index c79d6fe..3db3c35 100644
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@ -17,12 +17,10 @@
Amazon EC2, Eucalyptus and Nimbus drivers.
"""
-from __future__ import with_statement
-
import sys
import base64
-import os
import copy
+import warnings
from xml.etree import ElementTree as ET
@@ -39,6 +37,7 @@ from libcloud.compute.providers import Provider
from libcloud.compute.types import NodeState
from libcloud.compute.base import Node, NodeDriver, NodeLocation, NodeSize
from libcloud.compute.base import NodeImage, StorageVolume, VolumeSnapshot
+from libcloud.compute.base import KeyPair
API_VERSION = '2010-08-31'
NAMESPACE = 'http://ec2.amazonaws.com/doc/%s/' % (API_VERSION)
@@ -912,6 +911,71 @@ class BaseEC2NodeDriver(NodeDriver):
response = self.connection.request(self.path, params=params).object
return self._get_boolean(response)
+ 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):
+ name = findtext(element=elem, xpath='keyName', namespace=NAMESPACE)
+ fingerprint = findtext(element=elem, xpath='keyFingerprint',
+ namespace=NAMESPACE).strip()
+ private_key = findtext(element=elem, xpath='keyMaterial',
+ namespace=NAMESPACE)
+
+ key_pair = KeyPair(name=name,
+ public_key=None,
+ fingerprint=fingerprint,
+ private_key=private_key,
+ driver=self)
+ return key_pair
+
+ def list_key_pairs(self):
+ params = {
+ 'Action': 'DescribeKeyPairs'
+ }
+
+ response = self.connection.request(self.path, params=params)
+ elems = findall(element=response.object, xpath='keySet/item',
+ namespace=NAMESPACE)
+
+ key_pairs = self._to_key_pairs(elems=elems)
+ return key_pairs
+
+ def create_key_pair(self, name):
+ params = {
+ 'Action': 'CreateKeyPair',
+ 'KeyName': name
+ }
+
+ response = self.connection.request(self.path, params=params)
+ elem = response.object
+ key_pair = self._to_key_pair(elem=elem)
+ return key_pair
+
+ def import_key_pair_from_string(self, name, key_material):
+ base64key = base64.b64encode(b(key_material))
+
+ params = {
+ 'Action': 'ImportKeyPair',
+ 'KeyName': name,
+ 'PublicKeyMaterial': base64key
+ }
+
+ response = self.connection.request(self.path, params=params)
+ elem = response.object
+ key_pair = self._to_key_pair(elem=elem)
+ return key_pair
+
+ def delete_key_pair(self, key_pair):
+ params = {
+ 'Action': 'DeleteKeyPair',
+ 'KeyName': key_pair
+ }
+ result = self.connection.request(self.path, params=params).object
+ element = findtext(element=result, xpath='return',
+ namespace=NAMESPACE)
+ return element == 'true'
+
def ex_destroy_image(self, image):
params = {
'Action': 'DeregisterImage',
@@ -921,7 +985,8 @@ class BaseEC2NodeDriver(NodeDriver):
return self._get_boolean(response)
def ex_create_keypair(self, name):
- """Creates a new keypair
+ """
+ Creates a new keypair
@note: This is a non-standard extension API, and only works for EC2.
@@ -931,20 +996,18 @@ class BaseEC2NodeDriver(NodeDriver):
:rtype: ``dict``
"""
- params = {
- 'Action': 'CreateKeyPair',
- 'KeyName': name,
- }
- response = self.connection.request(self.path, params=params).object
- key_material = findtext(element=response, xpath='keyMaterial',
- namespace=NAMESPACE)
- key_fingerprint = findtext(element=response, xpath='keyFingerprint',
- namespace=NAMESPACE)
- return {
- 'keyMaterial': key_material,
- 'keyFingerprint': key_fingerprint,
+ warnings.warn('This method has been deprecated in favor of '
+ 'create_key_pair method')
+
+ key_pair = self.create_key_pair(name=name)
+
+ result = {
+ 'keyMaterial': key_pair.private_key,
+ 'keyFingerprint': key_pair.fingerprint
}
+ return result
+
def ex_delete_keypair(self, keypair):
"""
Delete a key pair by name.
@@ -956,14 +1019,10 @@ class BaseEC2NodeDriver(NodeDriver):
:rtype: ``bool``
"""
- params = {
- 'Action': 'DeleteKeyPair',
- 'KeyName': keypair
- }
- result = self.connection.request(self.path, params=params).object
- element = findtext(element=result, xpath='return',
- namespace=NAMESPACE)
- return element == 'true'
+ warnings.warn('This method has been deprecated in favor of '
+ 'delete_key_pair method')
+
+ return self.delete_key_pair(name=keypair)
def ex_import_keypair_from_string(self, name, key_material):
"""
@@ -980,23 +1039,17 @@ class BaseEC2NodeDriver(NodeDriver):
:rtype: ``dict``
"""
- base64key = base64.b64encode(b(key_material))
+ warnings.warn('This method has been deprecated in favor of '
+ 'import_key_pair_from_string method')
- params = {
- 'Action': 'ImportKeyPair',
- 'KeyName': name,
- 'PublicKeyMaterial': base64key
- }
+ key_pair = self.import_key_pair_from_string(name=name,
+ key_material=key_material)
- response = self.connection.request(self.path, params=params).object
- key_name = findtext(element=response, xpath='keyName',
- namespace=NAMESPACE)
- key_fingerprint = findtext(element=response, xpath='keyFingerprint',
- namespace=NAMESPACE)
- return {
- 'keyName': key_name,
- 'keyFingerprint': key_fingerprint,
+ result = {
+ 'keyName': key_pair.name,
+ 'keyFingerprint': key_pair.fingerprint
}
+ return result
def ex_import_keypair(self, name, keyfile):
"""
@@ -1013,9 +1066,17 @@ class BaseEC2NodeDriver(NodeDriver):
:rtype: ``dict``
"""
- with open(os.path.expanduser(keyfile)) as fh:
- content = fh.read()
- return self.ex_import_keypair_from_string(name, content)
+ warnings.warn('This method has been deprecated in favor of '
+ 'import_key_pair_from_file method')
+
+ key_pair = self.import_key_pair_from_file(name=name,
+ key_file_path=keyfile)
+
+ result = {
+ 'keyName': key_pair.name,
+ 'keyFingerprint': key_pair.fingerprint
+ }
+ return result
def ex_find_or_import_keypair_by_key_material(self, pubkey):
"""
@@ -1023,16 +1084,27 @@ class BaseEC2NodeDriver(NodeDriver):
exists, return any information we have about it. Otherwise, create it.
Keys that are created are named based on their comment and fingerprint.
+
+ :rtype: ``dict``
"""
key_fingerprint = get_pubkey_ssh2_fingerprint(pubkey)
key_comment = get_pubkey_comment(pubkey, default='unnamed')
- key_name = "%s-%s" % (key_comment, key_fingerprint)
+ key_name = '%s-%s' % (key_comment, key_fingerprint)
- for keypair in self.ex_list_keypairs():
- if keypair['keyFingerprint'] == key_fingerprint:
- return keypair
+ key_pairs = self.list_key_pairs()
+ key_pairs = [key_pair for key_pair in key_pairs if
+ key_pair.fingerprint == key_fingerprint]
- return self.ex_import_keypair_from_string(key_name, pubkey)
+ if len(key_pairs) >= 1:
+ key_pair = key_pairs[0]
+ result = {
+ 'keyName': key_pair.name,
+ 'keyFingerprint': key_pair.fingerprint
+ }
+ else:
+ result = self.ex_import_keypair_from_string(key_name, pubkey)
+
+ return result
def ex_list_keypairs(self):
"""
@@ -1040,34 +1112,32 @@ class BaseEC2NodeDriver(NodeDriver):
:rtype: ``list`` of ``dict``
"""
- params = {
- 'Action': 'DescribeKeyPairs'
- }
+ warnings.warn('This method has been deprecated in favor of '
+ 'list_key_pairs method')
- response = self.connection.request(self.path, params=params).object
- keypairs = []
- for elem in findall(element=response, xpath='keySet/item',
- namespace=NAMESPACE):
- keypair = {
- 'keyName': findtext(element=elem, xpath='keyName',
- namespace=NAMESPACE),
- 'keyFingerprint': findtext(element=elem,
- xpath='keyFingerprint',
- namespace=NAMESPACE).strip(),
+ key_pairs = self.list_key_pairs()
+
+ result = []
+
+ for key_pair in key_pairs:
+ item = {
+ 'keyName': key_pair.name,
+ 'keyFingerprint': key_pair.fingerprint,
}
- keypairs.append(keypair)
+ result.append(item)
- return keypairs
+ return result
def ex_describe_all_keypairs(self):
"""
- Describes all keypairs. This is here for backward compatibilty.
+ Return names for all the available key pairs.
@note: This is a non-standard extension API, and only works for EC2.
:rtype: ``list`` of ``str``
"""
- return [k['keyName'] for k in self.ex_list_keypairs()]
+ names = [key_pair.name for key_pair in self.list_key_pairs()]
+ return names
def ex_describe_keypairs(self, name):
"""
http://git-wip-us.apache.org/repos/asf/libcloud/blob/b398aebd/libcloud/compute/drivers/openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/openstack.py b/libcloud/compute/drivers/openstack.py
index 7d0958a..1866120 100644
--- a/libcloud/compute/drivers/openstack.py
+++ b/libcloud/compute/drivers/openstack.py
@@ -16,23 +16,19 @@
OpenStack driver
"""
-from __future__ import with_statement
-
try:
import simplejson as json
except ImportError:
import json
import warnings
+import base64
from libcloud.utils.py3 import httplib
from libcloud.utils.py3 import b
from libcloud.utils.py3 import next
from libcloud.utils.py3 import urlparse
-import os
-import base64
-
from xml.etree import ElementTree as ET
from libcloud.common.openstack import OpenStackBaseConnection
@@ -41,6 +37,7 @@ from libcloud.common.types import MalformedResponseError, ProviderError
from libcloud.compute.types import NodeState, Provider
from libcloud.compute.base import NodeSize, NodeImage
from libcloud.compute.base import NodeDriver, Node, NodeLocation, StorageVolume
+from libcloud.compute.base import KeyPair
from libcloud.pricing import get_size_price
from libcloud.common.base import Response
from libcloud.utils.xml import findall
@@ -1710,16 +1707,51 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
(rule.id), method='DELETE')
return resp.status == httplib.NO_CONTENT
- def _to_keypairs(self, obj):
- keypairs = obj['keypairs']
- return [self._to_keypair(keypair['keypair']) for keypair in keypairs]
+ def _to_key_pairs(self, obj):
+ key_pairs = obj['keypairs']
+ key_pairs = [self._to_key_pair(key_pair['keypair']) for key_pair in
+ key_pairs]
+ return key_pairs
+
+ def _to_key_pair(self, obj):
+ key_pair = KeyPair(name=obj['name'],
+ fingerprint=obj['fingerprint'],
+ public_key=obj['public_key'],
+ private_key=obj.get('private_key', None),
+ driver=self)
+ return key_pair
+
+ def list_key_pairs(self):
+ response = self.connection.request('/os-keypairs')
+ key_pairs = self._to_key_pairs(response.object)
+ return key_pairs
+
+ def create_key_pair(self, name):
+ data = {'keypair': {'name': name}}
+ response = self.connection.request('/os-keypairs', method='POST',
+ data=data)
+ key_pair = self._to_key_pair(response.object['keypair'])
+ return key_pair
+
+ def import_key_pair_from_string(self, name, key_material):
+ data = {'keypair': {'name': name, 'public_key': key_material}}
+ response = self.connection.request('/os-keypairs', method='POST',
+ data=data)
+ key_pair = self._to_key_pair(response.object['keypair'])
+ return key_pair
+
+ def delete_key_pair(self, key_pair):
+ """
+ Delete a KeyPair.
- def _to_keypair(self, obj):
- return OpenStackKeyPair(name=obj['name'],
- fingerprint=obj['fingerprint'],
- public_key=obj['public_key'],
- private_key=obj.get('private_key', None),
- driver=self)
+ :param keypair: KeyPair to delete
+ :type keypair: :class:`OpenStackKeyPair`
+
+ :rtype: ``bool``
+ """
+ response = self.connection.request('/os-keypairs/%s' % (key_pair.name),
+ method='DELETE')
+ return response.status == httplib.ACCEPTED
def ex_list_keypairs(self):
"""
@@ -1727,8 +1759,10 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
:rtype: ``list`` of :class:`OpenStackKeyPair`
"""
- return self._to_keypairs(
- self.connection.request('/os-keypairs').object)
+ warnings.warn('This method has been deprecated in favor of '
+ 'list_key_pairs method')
+
+ return self.list_key_pairs()
def ex_create_keypair(self, name):
"""
@@ -1739,10 +1773,10 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
:rtype: :class:`OpenStackKeyPair`
"""
- return self._to_keypair(self.connection.request(
- '/os-keypairs', method='POST',
- data={'keypair': {'name': name}}
- ).object['keypair'])
+ warnings.warn('This method has been deprecated in favor of '
+ 'create_key_pair method')
+
+ return self.create_key_pair(name=name)
def ex_import_keypair(self, name, keyfile):
"""
@@ -1756,10 +1790,10 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
:rtype: :class:`OpenStackKeyPair`
"""
- with open(os.path.expanduser(keyfile), 'r') as fp:
- public_key = fp.read()
+ warnings.warn('This method has been deprecated in favor of '
+ 'import_key_pair_from_file method')
- return self.ex_import_keypair_from_string(name, public_key)
+ return self.import_key_pair_from_file(name=name, key_file_path=keyfile)
def ex_import_keypair_from_string(self, name, key_material):
"""
@@ -1773,10 +1807,11 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
:rtype: :class:`OpenStackKeyPair`
"""
- return self._to_keypair(self.connection.request(
- '/os-keypairs', method='POST',
- data={'keypair': {'name': name, 'public_key': key_material}}
- ).object['keypair'])
+ warnings.warn('This method has been deprecated in favor of '
+ 'import_key_pair_from_string method')
+
+ return self.import_key_pair_from_string(name=name,
+ key_material=key_material)
def ex_delete_keypair(self, keypair):
"""
@@ -1787,9 +1822,10 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
:rtype: ``bool``
"""
- resp = self.connection.request('/os-keypairs/%s' % (keypair.name),
- method='DELETE')
- return resp.status == httplib.ACCEPTED
+ warnings.warn('This method has been deprecated in favor of '
+ 'delete_key_pair method')
+
+ return self.delete_key_pair(key_pair=keypair)
def ex_get_size(self, size_id):
"""
http://git-wip-us.apache.org/repos/asf/libcloud/blob/b398aebd/libcloud/test/compute/fixtures/cloudstack/createSSHKeyPair_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/createSSHKeyPair_default.json b/libcloud/test/compute/fixtures/cloudstack/createSSHKeyPair_default.json
new file mode 100644
index 0000000..2d0740d
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/createSSHKeyPair_default.json
@@ -0,0 +1 @@
+{ "createsshkeypairresponse" : { "keypair" : {"name":"test-keypair","fingerprint":"51:9f:81:30:ec:82:0c:e5:8c:81:ac:14:27:d0:e5:e2","privateKey":"-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQDMaSZY4v228AWWcXYLoojgaZ+K8SbuI8YoPDEi9UWcww5mWSTx\nVl6Ksb8YPFxL6+3/unlfr4zK1LksxgN8XRuZr+YBFGphUB6a5EcyshkXi3mfAE7d\n6a26ah6ySXFK9GmZoXcJqQ1xLC9rKGPL7tWgHmbX1lCbN6QinV0mZVEHNwIDAQAB\nAoGACXQngN7mqwpIx99xfTJEMFTSOyPSEBt5c6zs/NfpI0nmJZej3MGI19NGqkFI\nZ35+4F/ocyN0WIEkG00BJkRMHWdPNd+YnVSuVgEyGCD8hDvBbUEQrmdZ0VfQt+2q\nd52g573s6D6Skk/SZHGi3yHca4H52c3EpLJzThxUmJSSqmECQQD0loEIiQzQaap3\n/Gce7nZeLCSNXf0Q5aKFQv/X22srw6YvJ9/25cLahiFtQUadId9VUXSYTgEKX0ST\nB2CZ4UJxAkEA1fK/PT+YIHaiQIiCK/xTnoIuTvdXmH0IozolRxGAKpQZNvaMpKgn\nvXU84/yztekEPG0pKmCm7CZUZoGdfiJoJwJALwUsAy8NtpdJvU1ZqbmgKdSEpmS2\nPORYjRPnSWEWRlCThyc8SCO9hPMaQ/2zjIuxep5xMsJ0MsFD1pwpdwu2EQJBAMrG\nEZ7ZQTOzfMAxIT7THeWjeIR7RNhP2PnrSB19Zr30M5m2P0Jn5ZJZJWbnwOPuf4dN\n5rA1fr9e7KtiuYQs1A0CQQCT06qHdHaQr78A6YTEbDVr0M57qVrdsm5xyXzCmpMy\n9LxXAACghjHbjF//FEOjNG21I
utbCg6cNIRz5EM8+MD+\n-----END RSA PRIVATE KEY-----\n"} } }
http://git-wip-us.apache.org/repos/asf/libcloud/blob/b398aebd/libcloud/test/compute/fixtures/ec2/create_key_pair.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/create_key_pair.xml b/libcloud/test/compute/fixtures/ec2/create_key_pair.xml
new file mode 100644
index 0000000..10aec6d
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/create_key_pair.xml
@@ -0,0 +1,22 @@
+<CreateKeyPairResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/">
+ <keyName>my-key-pair</keyName>
+ <keyFingerprint>
+ 1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f
+ </keyFingerprint>
+ <keyMaterial>---- BEGIN RSA PRIVATE KEY ----
+MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6
+b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAd
+BgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhcNMTEwNDI1MjA0NTIxWhcN
+MTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYD
+VQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25z
+b2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFt
+YXpvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMaK0dn+a4GmWIWJ
+21uUSfwfEvySWtC2XADZ4nB+BLYgVIk60CpiwsZ3G93vUEIO3IyNoH/f0wYK8m9T
+rDHudUZg3qX4waLG5M43q7Wgc/MbQITxOUSQv7c7ugFFDzQGBzZswY6786m86gpE
+Ibb3OhjZnzcvQAaRHhdlQWIMm2nrAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtCu4
+nUhVVxYUntneD9+h8Mg9q6q+auNKyExzyLwaxlAoo7TJHidbtS4J5iNmZgXL0Fkb
+FFBjvSfpJIlJ00zbhNYS5f6GuoEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTb
+NYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE
+-----END RSA PRIVATE KEY-----</keyMaterial>
+</CreateKeyPairResponse>
http://git-wip-us.apache.org/repos/asf/libcloud/blob/b398aebd/libcloud/test/compute/test_cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudstack.py b/libcloud/test/compute/test_cloudstack.py
index f7c99a4..65a0c28 100644
--- a/libcloud/test/compute/test_cloudstack.py
+++ b/libcloud/test/compute/test_cloudstack.py
@@ -271,51 +271,81 @@ class CloudStackCommonTestCase(TestCaseMixin):
res = node.reboot()
self.assertTrue(res)
- def test_ex_list_keypairs(self):
- keypairs = self.driver.ex_list_keypairs()
+ def test_list_key_pairs(self):
+ keypairs = self.driver.list_key_pairs()
fingerprint = '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:' + \
'00:00:00:00:00'
+ self.assertEqual(keypairs[0].name, 'cs-keypair')
+ self.assertEqual(keypairs[0].fingerprint, fingerprint)
+
+ # Test old and deprecated way
+ keypairs = self.driver.ex_list_keypairs()
+
self.assertEqual(keypairs[0]['name'], 'cs-keypair')
self.assertEqual(keypairs[0]['fingerprint'], fingerprint)
- def test_ex_list_keypairs_no_keypair_key(self):
+ def test_list_key_pairs_no_keypair_key(self):
CloudStackMockHttp.fixture_tag = 'no_keys'
- keypairs = self.driver.ex_list_keypairs()
+ keypairs = self.driver.list_key_pairs()
self.assertEqual(keypairs, [])
- def test_ex_create_keypair(self):
- self.assertRaises(
- LibcloudError,
- self.driver.ex_create_keypair,
- 'cs-keypair')
+ def test_create_keypair(self):
+ key_pair = self.driver.create_key_pair(name='test-keypair')
- def test_ex_delete_keypair(self):
- res = self.driver.ex_delete_keypair('cs-keypair')
- self.assertTrue(res)
+ self.assertEqual(key_pair.name, 'test-keypair')
+ self.assertTrue(key_pair.fingerprint is not None)
+ self.assertTrue(key_pair.private_key is not None)
+
+ # Test old and deprecated way
+ res = self.driver.ex_create_keypair(name='test-keypair')
+ self.assertEqual(res['name'], 'test-keypair')
+ self.assertTrue(res['fingerprint'] is not None)
+ self.assertTrue(res['privateKey'] is not None)
- def test_ex_import_keypair(self):
+ def test_import_keypair_from_file(self):
fingerprint = 'c4:a1:e5:d4:50:84:a9:4c:6b:22:ee:d6:57:02:b8:15'
- path = os.path.join(os.path.dirname(__file__), "fixtures",
- "cloudstack",
- "dummy_rsa.pub")
+ path = os.path.join(os.path.dirname(__file__), 'fixtures',
+ 'cloudstack',
+ 'dummy_rsa.pub')
+ key_pair = self.driver.import_key_pair_from_file('foobar', path)
+ self.assertEqual(key_pair.name, 'foobar')
+ self.assertEqual(key_pair.fingerprint, fingerprint)
+
+ # Test old and deprecated way
res = self.driver.ex_import_keypair('foobar', path)
self.assertEqual(res['keyName'], 'foobar')
self.assertEqual(res['keyFingerprint'], fingerprint)
def test_ex_import_keypair_from_string(self):
fingerprint = 'c4:a1:e5:d4:50:84:a9:4c:6b:22:ee:d6:57:02:b8:15'
- path = os.path.join(os.path.dirname(__file__), "fixtures",
- "cloudstack",
- "dummy_rsa.pub")
+ path = os.path.join(os.path.dirname(__file__), 'fixtures',
+ 'cloudstack',
+ 'dummy_rsa.pub')
fh = open(path)
- res = self.driver.ex_import_keypair_from_string('foobar',
- fh.read())
+ key_material = fh.read()
fh.close()
+
+ key_pair = self.driver.import_key_pair_from_string('foobar', key_material=key_material)
+ self.assertEqual(key_pair.name, 'foobar')
+ self.assertEqual(key_pair.fingerprint, fingerprint)
+
+ # Test old and deprecated way
+ res = self.driver.ex_import_keypair_from_string('foobar', key_material=key_material)
self.assertEqual(res['keyName'], 'foobar')
self.assertEqual(res['keyFingerprint'], fingerprint)
+ def test_delete_key_pair(self):
+ key_pair = self.driver.list_key_pairs()[0]
+
+ res = self.driver.delete_key_pair(key_pair=key_pair)
+ self.assertTrue(res)
+
+ # Test old and deprecated way
+ res = self.driver.ex_delete_keypair(keypair='cs-keypair')
+ self.assertTrue(res)
+
def test_ex_list_security_groups(self):
groups = self.driver.ex_list_security_groups()
self.assertEqual(2, len(groups))
http://git-wip-us.apache.org/repos/asf/libcloud/blob/b398aebd/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ec2.py b/libcloud/test/compute/test_ec2.py
index 3952c68..c32bffe 100644
--- a/libcloud/test/compute/test_ec2.py
+++ b/libcloud/test/compute/test_ec2.py
@@ -375,13 +375,35 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
self.assertEqual(availability_zone.zone_state, 'available')
self.assertEqual(availability_zone.region_name, 'eu-west-1')
- def test_ex_list_keypairs(self):
+ def test_list_keypairs(self):
+ keypairs = self.driver.list_key_pairs()
+
+ self.assertEqual(len(keypairs), 1)
+ self.assertEqual(keypairs[0].name, 'gsg-keypair')
+ self.assertEqual(keypairs[0].fingerprint, null_fingerprint)
+
+ # Test old deprecated method
keypairs = self.driver.ex_list_keypairs()
self.assertEqual(len(keypairs), 1)
self.assertEqual(keypairs[0]['keyName'], 'gsg-keypair')
self.assertEqual(keypairs[0]['keyFingerprint'], null_fingerprint)
+ def test_create_key_pair(self):
+ key_pair = self.driver.create_key_pair(name='test-keypair')
+
+ 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)
+
+ # Test old and deprecated method
+ key_pair = self.driver.ex_create_keypair(name='test-keypair')
+ self.assertEqual(key_pair['keyFingerprint'], fingerprint)
+ self.assertTrue(key_pair['keyMaterial'] is not None)
+
def test_ex_describe_all_keypairs(self):
keys = self.driver.ex_describe_all_keypairs()
self.assertEqual(keys, ['gsg-keypair'])
@@ -397,7 +419,11 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
self.assertEqual(keypair2['keyName'], 'gsg-keypair')
self.assertEqual(keypair2['keyFingerprint'], null_fingerprint)
- def ex_delete_keypair(self):
+ def ex_delete_key_pair(self):
+ success = self.driver.delete_key_pair('testkey')
+ self.assertTrue(success)
+
+ # Test old and deprecated method
resp = self.driver.ex_delete_keypair('testkey')
self.assertTrue(resp)
@@ -410,20 +436,33 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
self.assertTrue('owner' in tags)
self.assertTrue('stack' in tags)
- def test_ex_import_keypair_from_string(self):
+ def test_import_key_pair_from_string(self):
path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc',
'dummy_rsa.pub')
- with open(path, 'r') as fh:
- key = self.driver.ex_import_keypair_from_string(
- 'keypair', fh.read())
+ with open(path, 'r') as fp:
+ key_material = fp.read()
+
+ key = self.driver.import_key_pair_from_string(name='keypair',
+ key_material=key_material)
+ self.assertEqual(key.name, 'keypair')
+ self.assertEqual(key.fingerprint, null_fingerprint)
+ # Test old and deprecated method
+ key = self.driver.ex_import_keypair_from_string('keypair',
+ key_material)
self.assertEqual(key['keyName'], 'keypair')
self.assertEqual(key['keyFingerprint'], null_fingerprint)
- def test_ex_import_keypair(self):
+ def test_import_key_pair_from_file(self):
path = os.path.join(os.path.dirname(__file__), 'fixtures', 'misc',
'dummy_rsa.pub')
+
+ key = self.driver.import_key_pair_from_file('keypair', path)
+ self.assertEqual(key.name, 'keypair')
+ self.assertEqual(key.fingerprint, null_fingerprint)
+
+ # Test old and deprecated method
key = self.driver.ex_import_keypair('keypair', path)
self.assertEqual(key['keyName'], 'keypair')
self.assertEqual(key['keyFingerprint'], null_fingerprint)
@@ -803,6 +842,10 @@ class EC2MockHttp(MockHttpTestCase):
body = self.fixtures.load('describe_key_pairs.xml')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ def _CreateKeyPair(self, method, url, body, headers):
+ body = self.fixtures.load('create_key_pair.xml')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
def _ImportKeyPair(self, method, url, body, headers):
body = self.fixtures.load('import_key_pair.xml')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
http://git-wip-us.apache.org/repos/asf/libcloud/blob/b398aebd/libcloud/test/compute/test_openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_openstack.py b/libcloud/test/compute/test_openstack.py
index b0e1d2c..3c8377b 100644
--- a/libcloud/test/compute/test_openstack.py
+++ b/libcloud/test/compute/test_openstack.py
@@ -1327,8 +1327,8 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
result = self.driver.ex_delete_security_group_rule(security_group_rule)
self.assertTrue(result)
- def test_ex_list_keypairs(self):
- keypairs = self.driver.ex_list_keypairs()
+ def test_list_key_pairs(self):
+ keypairs = self.driver.list_key_pairs()
self.assertEqual(len(keypairs), 2, 'Wrong keypairs count')
keypair = keypairs[1]
self.assertEqual(keypair.name, 'key2')
@@ -1337,9 +1337,9 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
self.assertTrue(len(keypair.public_key) > 10)
self.assertEqual(keypair.private_key, None)
- def test_ex_create_keypair(self):
+ def test_create_key_pair(self):
name = 'key0'
- keypair = self.driver.ex_create_keypair(name)
+ keypair = self.driver.create_key_pair(name=name)
self.assertEqual(keypair.name, name)
self.assertEqual(keypair.fingerprint,
@@ -1347,34 +1347,36 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
self.assertTrue(len(keypair.public_key) > 10)
self.assertTrue(len(keypair.private_key) > 10)
- def test_ex_import_keypair(self):
+ def test_import_key_pair_from_file(self):
name = 'key3'
path = os.path.join(
- os.path.dirname(__file__), "fixtures", "misc", "dummy_rsa.pub")
+ os.path.dirname(__file__), 'fixtures', 'misc', 'dummy_rsa.pub')
pub_key = open(path, 'r').read()
- keypair = self.driver.ex_import_keypair(name, path)
+ keypair = self.driver.import_key_pair_from_file(name=name,
+ key_file_path=path)
self.assertEqual(keypair.name, name)
self.assertEqual(
keypair.fingerprint, '97:10:a6:e7:92:65:7e:69:fe:e6:81:8f:39:3c:8f:5a')
self.assertEqual(keypair.public_key, pub_key)
self.assertEqual(keypair.private_key, None)
- def test_ex_import_keypair_from_string(self):
+ def test_import_key_pair_from_string(self):
name = 'key3'
path = os.path.join(
- os.path.dirname(__file__), "fixtures", "misc", "dummy_rsa.pub")
+ os.path.dirname(__file__), 'fixtures', 'misc', 'dummy_rsa.pub')
pub_key = open(path, 'r').read()
- keypair = self.driver.ex_import_keypair_from_string(name, pub_key)
+ keypair = self.driver.import_key_pair_from_string(name=name,
+ key_material=pub_key)
self.assertEqual(keypair.name, name)
self.assertEqual(
keypair.fingerprint, '97:10:a6:e7:92:65:7e:69:fe:e6:81:8f:39:3c:8f:5a')
self.assertEqual(keypair.public_key, pub_key)
self.assertEqual(keypair.private_key, None)
- def test_ex_delete_keypair(self):
+ def test_delete_key_pair(self):
keypair = OpenStackKeyPair(
name='key1', fingerprint=None, public_key=None, driver=self.driver)
- result = self.driver.ex_delete_keypair(keypair)
+ result = self.driver.delete_key_pair(key_pair=keypair)
self.assertTrue(result)
def test_ex_list_floating_ip_pools(self):