Repository: libcloud Updated Branches: refs/heads/trunk 5f0ccc1a5 -> f7025a95e
Add support for placement groups to the EC2 driver. Closes #418 Signed-off-by: Tomaz Muraus <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/f7025a95 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/f7025a95 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/f7025a95 Branch: refs/heads/trunk Commit: f7025a95ef18e85ad35967224c75bed71e85b21d Parents: 5f0ccc1 Author: Mikhail Ovsyannikov <[email protected]> Authored: Thu Dec 18 13:40:15 2014 +0300 Committer: Tomaz Muraus <[email protected]> Committed: Sun Jan 4 19:03:49 2015 +0100 ---------------------------------------------------------------------- CHANGES.rst | 4 + libcloud/compute/drivers/ec2.py | 89 ++++++++++++++++++++ .../fixtures/ec2/create_placement_groups.xml | 4 + .../fixtures/ec2/delete_placement_groups.xml | 4 + .../fixtures/ec2/describe_placement_groups.xml | 15 ++++ libcloud/test/compute/test_ec2.py | 29 +++++++ 6 files changed, 145 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/f7025a95/CHANGES.rst ---------------------------------------------------------------------- diff --git a/CHANGES.rst b/CHANGES.rst index 47a1ab6..80c0fd0 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -107,6 +107,10 @@ Compute (GITHUB-421) [ZuluPro] +- Add support for placement group management to the EC2 driver. + (GITHUB-418) + [Mikhail Ovsyannikov] + Storage ~~~~~~~ http://git-wip-us.apache.org/repos/asf/libcloud/blob/f7025a95/libcloud/compute/drivers/ec2.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py index 32b578f..c070d79 100644 --- a/libcloud/compute/drivers/ec2.py +++ b/libcloud/compute/drivers/ec2.py @@ -65,6 +65,7 @@ __all__ = [ 'EC2NodeLocation', 'EC2ReservedNode', 'EC2SecurityGroup', + 'EC2PlacementGroup', 'EC2Network', 'EC2NetworkSubnet', 'EC2NetworkInterface', @@ -1730,6 +1731,22 @@ class EC2SecurityGroup(object): % (self.id, self.name)) +class EC2PlacementGroup(object): + """ + Represents information about a Placement Grous + + Note: This class is EC2 specific. + """ + def __init__(self, name, state, strategy='cluster', extra=None): + self.name = name + self.strategy = strategy + self.extra = extra or {} + + def __repr__(self): + return '<EC2PlacementGroup: name=%s, state=%s>' % (self.name, + self.strategy) + + class EC2Network(object): """ Represents information about a VPC (Virtual Private Cloud) network @@ -2166,6 +2183,10 @@ class BaseEC2NodeDriver(NodeDriver): :keyword ex_subnet: The subnet to launch the instance into. :type ex_subnet: :class:`.EC2Subnet` + + :keyword ex_placement_group: The name of the placement group to + launch the instance into. + :type ex_placement_group: ``str`` """ image = kwargs["image"] size = kwargs["size"] @@ -2254,6 +2275,9 @@ class BaseEC2NodeDriver(NodeDriver): if 'ex_subnet' in kwargs: params['SubnetId'] = kwargs['ex_subnet'].id + if 'ex_placement_group' in kwargs and kwargs['ex_placement_group']: + params['Placement.GroupName'] = kwargs['ex_placement_group'] + object = self.connection.request(self.path, params=params).object nodes = self._to_nodes(object, 'instancesSet/item') @@ -2591,6 +2615,53 @@ class BaseEC2NodeDriver(NodeDriver): response = self.connection.request(self.path, params=params).object return self._get_boolean(response) + def ex_create_placement_group(self, name): + """ + Creates new Placement Group + + :param name: Name for new placement Group + :type name: ``str`` + + :rtype: ``bool`` + """ + params = {'Action': 'CreatePlacementGroup', + 'Strategy': 'cluster', + 'GroupName': name} + response = self.connection.request(self.path, params=params).object + return self._get_boolean(response) + + def ex_delete_placement_group(self, name): + """ + Deletes Placement Group + + :param name: Placement Group name + :type name: ``str`` + + :rtype: ``bool`` + """ + params = {'Action': 'DeletePlacementGroup', + 'GroupName': name} + response = self.connection.request(self.path, params=params).object + return self._get_boolean(response) + + def ex_list_placement_groups(self, names=None): + """ + List Placement Groups + + :param names: Placement Group names + :type names: ``list`` of ``str`` + + :rtype: ``list`` of :class:`.EC2PlacementGroup` + """ + names = names or [] + params = {'Action': 'DescribePlacementGroups'} + + for index, name in enumerate(names): + params['GroupName.%s' % index + 1] = name + + response = self.connection.request(self.path, params=params).object + return self._to_placement_groups(response) + def ex_register_image(self, name, description=None, architecture=None, image_location=None, root_device_name=None, block_device_mapping=None, kernel_id=None, @@ -4832,6 +4903,24 @@ class BaseEC2NodeDriver(NodeDriver): return ElasticIP(public_ip, domain, instance_id, extra=extra) + def _to_placement_groups(self, response): + return [self._to_placement_group(el) + for el in response.findall( + fixxpath(xpath='placementGroupSet/item', + namespace=NAMESPACE))] + + def _to_placement_group(self, element): + name = findtext(element=element, + xpath='groupName', + namespace=NAMESPACE) + state = findtext(element=element, + xpath='state', + namespace=NAMESPACE) + strategy = findtext(element=element, + xpath='strategy', + namespace=NAMESPACE) + return EC2PlacementGroup(name, state, strategy) + def _to_subnets(self, response): return [self._to_subnet(el) for el in response.findall( fixxpath(xpath='subnetSet/item', namespace=NAMESPACE)) http://git-wip-us.apache.org/repos/asf/libcloud/blob/f7025a95/libcloud/test/compute/fixtures/ec2/create_placement_groups.xml ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/ec2/create_placement_groups.xml b/libcloud/test/compute/fixtures/ec2/create_placement_groups.xml new file mode 100644 index 0000000..ca83b7f --- /dev/null +++ b/libcloud/test/compute/fixtures/ec2/create_placement_groups.xml @@ -0,0 +1,4 @@ +<CreatePlacementGroupResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/"> + <requestId>d4904fd9-82c2-4ea5-adfe-a9cc3EXAMPLE</requestId> + <return>true</return> +</CreatePlacementGroupResponse> http://git-wip-us.apache.org/repos/asf/libcloud/blob/f7025a95/libcloud/test/compute/fixtures/ec2/delete_placement_groups.xml ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/ec2/delete_placement_groups.xml b/libcloud/test/compute/fixtures/ec2/delete_placement_groups.xml new file mode 100644 index 0000000..69091a3 --- /dev/null +++ b/libcloud/test/compute/fixtures/ec2/delete_placement_groups.xml @@ -0,0 +1,4 @@ +<DeletePlacementGroupResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/"> + <requestId>d4904fd9-82c2-4ea5-adfe-a9cc3EXAMPLE</requestId> + <return>true</return> +</DeletePlacementGroupResponse> http://git-wip-us.apache.org/repos/asf/libcloud/blob/f7025a95/libcloud/test/compute/fixtures/ec2/describe_placement_groups.xml ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/ec2/describe_placement_groups.xml b/libcloud/test/compute/fixtures/ec2/describe_placement_groups.xml new file mode 100644 index 0000000..787eb67 --- /dev/null +++ b/libcloud/test/compute/fixtures/ec2/describe_placement_groups.xml @@ -0,0 +1,15 @@ +<DescribePlacementGroupsResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/"> + <requestID>d4904fd9-82c2-4ea5-adfe-a9cc3EXAMPLE</requestID> + <placementGroupSet> + <item> + <groupName>XYZ-cluster</groupName> + <strategy>cluster</strategy> + <state>available</state> + </item> + <item> + <groupName>XYZ-cluster2</groupName> + <strategy>cluster</strategy> + <state>available</state> + </item> + </placementGroupSet> +</DescribePlacementGroupsResponse> http://git-wip-us.apache.org/repos/asf/libcloud/blob/f7025a95/libcloud/test/compute/test_ec2.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_ec2.py b/libcloud/test/compute/test_ec2.py index ce84912..e156565 100644 --- a/libcloud/test/compute/test_ec2.py +++ b/libcloud/test/compute/test_ec2.py @@ -29,6 +29,7 @@ from libcloud.compute.drivers.ec2 import EC2APSENodeDriver from libcloud.compute.drivers.ec2 import EC2APNENodeDriver from libcloud.compute.drivers.ec2 import EC2APSESydneyNodeDriver from libcloud.compute.drivers.ec2 import EC2SAEastNodeDriver +from libcloud.compute.drivers.ec2 import EC2PlacementGroup from libcloud.compute.drivers.ec2 import NimbusNodeDriver, EucNodeDriver from libcloud.compute.drivers.ec2 import OutscaleSASNodeDriver from libcloud.compute.drivers.ec2 import IdempotentParamError @@ -928,6 +929,22 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin): self.assertEqual(group["group_id"], "sg-52e2f530") + def test_ex_create_placement_groups(self): + resp = self.driver.ex_create_placement_group("NewPG") + self.assertTrue(resp) + + def test_ex_delete_placement_groups(self): + pgs = self.driver.ex_list_placement_groups() + pg = pgs[0] + + resp = self.driver.ex_delete_placement_group(pg.name) + self.assertTrue(resp) + + def test_ex_list_placement_groups(self): + pgs = self.driver.ex_list_placement_groups() + self.assertEqual(len(pgs), 2) + self.assertIsInstance(pgs[0], EC2PlacementGroup) + def test_ex_list_networks(self): vpcs = self.driver.ex_list_networks() @@ -1494,6 +1511,18 @@ class EC2MockHttp(MockHttpTestCase): body = self.fixtures.load('detach_internet_gateway.xml') return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + def _CreatePlacementGroup(self, method, url, body, headers): + body = self.fixtures.load('create_placement_groups.xml') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _DeletePlacementGroup(self, method, url, body, headers): + body = self.fixtures.load('delete_placement_groups.xml') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + + def _DescribePlacementGroups(self, method, url, body, headers): + body = self.fixtures.load('describe_placement_groups.xml') + return (httplib.OK, body, {}, httplib.responses[httplib.OK]) + class EucMockHttp(EC2MockHttp): fixtures = ComputeFileFixtures('ec2')
