Hello community, here is the log from the commit of package python-apache-libcloud for openSUSE:Factory checked in at 2014-07-23 22:06:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-apache-libcloud (Old) and /work/SRC/openSUSE:Factory/.python-apache-libcloud.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-apache-libcloud" Changes: -------- --- /work/SRC/openSUSE:Factory/python-apache-libcloud/python-apache-libcloud.changes 2014-06-30 21:50:27.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-apache-libcloud.new/python-apache-libcloud.changes 2014-07-24 01:16:12.000000000 +0200 @@ -1,0 +2,21 @@ +Mon Jul 21 21:21:48 UTC 2014 - aboe76@gmail.com +- Updated to Apache Libcloud 0.15.1 +- Compute: + - Allow user to limit a list of subnets which are returned by passing subnet_ids and filters argument to the ex_list_subnets + method in the EC2 driver. (LIBCLOUD-571, GITHUB-306) [Lior Goikhburg] + - Allow user to limit a list of internet gateways which are returned by passing gateway_ids and filters argument to the + ex_list_internet_gateways method in the EC2 driver. (LIBCLOUD-572, GITHUB-307) [Lior Goikhburg] + - Allow user to filter which nodes are returned by passing ex_filters argument to the list_nodes method in the EC2 driver. + (LIBCLOUD-580, GITHUB-320) [Lior Goikhburg] + - Add network_association_id to ex_list_public_ips and CloudstackAddress object (GITHUB-327) [Roeland Kuipers] + - Allow user to specify admin password by passing ex_admin_pass argument to the create_node method in the Openstack driver. + (GITHUB-315) [Marcus Devich] + - Fix a possible race condition in deploy_node which would occur if node is online and can be accessed via SSH, but the + SSH key we want to use hasn’t been installed yet. + Previously, we would immediately throw if we can connect, but the SSH key hasn’t been installed yet. (GITHUB-331) [David Gay] + Propagate an exception in deploy_node method if user specified an invalid path to the private key file. Previously + this exception was silently swallowed and ignored. [Tomaz Muraus] +- DNS: + - Include a better message in the exception which is thrown when a request in the Rackspace driver ends up in an ERROR state. [Tomaz Muraus] + +------------------------------------------------------------------- Old: ---- apache-libcloud-0.15.0.tar.bz2 New: ---- apache-libcloud-0.15.1.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-apache-libcloud.spec ++++++ --- /var/tmp/diff_new_pack.lsBId1/_old 2014-07-24 01:16:13.000000000 +0200 +++ /var/tmp/diff_new_pack.lsBId1/_new 2014-07-24 01:16:13.000000000 +0200 @@ -17,7 +17,7 @@ Name: python-apache-libcloud -Version: 0.15.0 +Version: 0.15.1 Release: 0 Summary: Abstract away differences among multiple cloud provider APIs License: Apache-2.0 ++++++ apache-libcloud-0.15.0.tar.bz2 -> apache-libcloud-0.15.1.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/CHANGES.rst new/apache-libcloud-0.15.1/CHANGES.rst --- old/apache-libcloud-0.15.0/CHANGES.rst 2014-06-22 20:20:19.000000000 +0200 +++ new/apache-libcloud-0.15.1/CHANGES.rst 2014-07-02 22:54:10.000000000 +0200 @@ -1,6 +1,59 @@ Changelog ========= +Changes with Apache Libcloud 0.15.1 +----------------------------------- + +Compute +~~~~~~~ + +- Allow user to limit a list of subnets which are returned by passing + ``subnet_ids`` and ``filters`` argument to the ``ex_list_subnets`` + method in the EC2 driver. + (LIBCLOUD-571, GITHUB-306) + [Lior Goikhburg] + +- Allow user to limit a list of internet gateways which are returned by + passing ``gateway_ids`` and ``filters`` argument to the + ``ex_list_internet_gateways`` method in the EC2 driver. + (LIBCLOUD-572, GITHUB-307) + [Lior Goikhburg] + +- Allow user to filter which nodes are returned by passing ``ex_filters`` + argument to the ``list_nodes`` method in the EC2 driver. + (LIBCLOUD-580, GITHUB-320) + [Lior Goikhburg] + +- Add network_association_id to ex_list_public_ips and CloudstackAddress object + (GITHUB-327) + [Roeland Kuipers] + +- Allow user to specify admin password by passing ``ex_admin_pass`` argument + to the ``create_node`` method in the Openstack driver. + (GITHUB-315) + [Marcus Devich] + +- Fix a possible race condition in deploy_node which would occur if node + is online and can be accessed via SSH, but the SSH key we want to use hasn't + been installed yet. + + Previously, we would immediately throw if we can connect, but the SSH key + hasn't been installed yet. + (GITHUB-331) + [David Gay] + +- Propagate an exception in ``deploy_node`` method if user specified an invalid + path to the private key file. Previously this exception was silently swallowed + and ignored. + [Tomaz Muraus] + +DNS +~~~ + +- Include a better message in the exception which is thrown when a request + in the Rackspace driver ends up in an ``ERROR`` state. + [Tomaz Muraus] + Changes with Apache Libcloud 0.15.0 ----------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/PKG-INFO new/apache-libcloud-0.15.1/PKG-INFO --- old/apache-libcloud-0.15.0/PKG-INFO 2014-06-22 20:28:42.000000000 +0200 +++ new/apache-libcloud-0.15.1/PKG-INFO 2014-07-02 23:19:07.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: apache-libcloud -Version: 0.15.0 +Version: 0.15.1 Summary: A standard Python library that abstracts away differences among multiple cloud provider APIs. For more information and documentation, please see http://libcloud.apache.org Home-page: http://libcloud.apache.org/ Author: Apache Software Foundation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/apache_libcloud.egg-info/PKG-INFO new/apache-libcloud-0.15.1/apache_libcloud.egg-info/PKG-INFO --- old/apache-libcloud-0.15.0/apache_libcloud.egg-info/PKG-INFO 2014-06-22 20:28:42.000000000 +0200 +++ new/apache-libcloud-0.15.1/apache_libcloud.egg-info/PKG-INFO 2014-07-02 23:19:06.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: apache-libcloud -Version: 0.15.0 +Version: 0.15.1 Summary: A standard Python library that abstracts away differences among multiple cloud provider APIs. For more information and documentation, please see http://libcloud.apache.org Home-page: http://libcloud.apache.org/ Author: Apache Software Foundation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/apache_libcloud.egg-info/SOURCES.txt new/apache-libcloud-0.15.1/apache_libcloud.egg-info/SOURCES.txt --- old/apache-libcloud-0.15.0/apache_libcloud.egg-info/SOURCES.txt 2014-06-22 20:28:42.000000000 +0200 +++ new/apache-libcloud-0.15.1/apache_libcloud.egg-info/SOURCES.txt 2014-07-02 23:19:06.000000000 +0200 @@ -307,6 +307,7 @@ libcloud/test/compute/fixtures/cloudsigma_2_0/unknown_error.json libcloud/test/compute/fixtures/cloudstack/associateIpAddress_default.json libcloud/test/compute/fixtures/cloudstack/attachVolume_default.json +libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupEgress_default.json libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupIngress_default.json libcloud/test/compute/fixtures/cloudstack/createNetwork_default.json libcloud/test/compute/fixtures/cloudstack/createPortForwardingRule_default.json @@ -370,6 +371,9 @@ libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17188.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17199.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17200.json +libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17201.json +libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17202.json +libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17203.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_attachvolumejob.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createtagsjob.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_createvolumejob.json @@ -379,6 +383,8 @@ libcloud/test/compute/fixtures/cloudstack/rebootVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_default.json libcloud/test/compute/fixtures/cloudstack/registerSSHKeyPair_error.json +libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupEgress_default.json +libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupIngress_default.json libcloud/test/compute/fixtures/cloudstack/startVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/stopVirtualMachine_default.json libcloud/test/compute/fixtures/digitalocean/create_node.json diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/__init__.py new/apache-libcloud-0.15.1/libcloud/__init__.py --- old/apache-libcloud-0.15.0/libcloud/__init__.py 2014-06-22 20:20:26.000000000 +0200 +++ new/apache-libcloud-0.15.1/libcloud/__init__.py 2014-07-02 22:50:11.000000000 +0200 @@ -20,7 +20,7 @@ """ __all__ = ['__version__', 'enable_debug'] -__version__ = '0.15.0' +__version__ = '0.15.1' import os diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/compute/base.py new/apache-libcloud-0.15.1/libcloud/compute/base.py --- old/apache-libcloud-0.15.0/libcloud/compute/base.py 2014-06-18 08:57:59.000000000 +0200 +++ new/apache-libcloud-0.15.1/libcloud/compute/base.py 2014-07-02 22:45:28.000000000 +0200 @@ -35,10 +35,17 @@ from libcloud.common.base import ConnectionKey from libcloud.common.base import BaseDriver from libcloud.common.types import LibcloudError +from libcloud.compute.ssh import have_paramiko from libcloud.utils.networking import is_private_subnet from libcloud.utils.networking import is_valid_ip_address +if have_paramiko: + from paramiko.ssh_exception import SSHException + SSH_TIMEOUT_EXCEPTION_CLASSES = (SSHException, IOError, socket.gaierror, + socket.error) +else: + SSH_TIMEOUT_EXCEPTION_CLASSES = (IOError, socket.gaierror, socket.error) # How long to wait for the node to come online after creating it NODE_ONLINE_WAIT_TIMEOUT = 10 * 60 @@ -1372,9 +1379,17 @@ while time.time() < end: try: ssh_client.connect() - except (IOError, socket.gaierror, socket.error): - # Retry if a connection is refused or timeout - # occurred + except SSH_TIMEOUT_EXCEPTION_CLASSES: + e = sys.exc_info()[1] + message = str(e).lower() + expected_msg = 'no such file or directory' + + if isinstance(e, IOError) and expected_msg in message: + # Propagate (key) file doesn't exist errors + raise e + + # Retry if a connection is refused, timeout occurred, + # or the connection fails due to failed authentication. ssh_client.close() time.sleep(wait_period) continue @@ -1401,7 +1416,6 @@ key_files=ssh_key_file, timeout=ssh_timeout) - # Connect to the SSH server running on the node ssh_client = self._ssh_client_connect(ssh_client=ssh_client, timeout=timeout) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/compute/drivers/abiquo.py new/apache-libcloud-0.15.1/libcloud/compute/drivers/abiquo.py --- old/apache-libcloud-0.15.0/libcloud/compute/drivers/abiquo.py 2014-06-11 09:57:32.000000000 +0200 +++ new/apache-libcloud-0.15.1/libcloud/compute/drivers/abiquo.py 2014-07-02 20:47:55.000000000 +0200 @@ -274,8 +274,8 @@ You can specify the location as well. - :param name: name of the group (required) - :type name: ``str`` + :param group: name of the group (required) + :type group: ``str`` :param location: location were to create the group :type location: :class:`NodeLocation` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/compute/drivers/brightbox.py new/apache-libcloud-0.15.1/libcloud/compute/drivers/brightbox.py --- old/apache-libcloud-0.15.0/libcloud/compute/drivers/brightbox.py 2014-03-21 10:08:08.000000000 +0100 +++ new/apache-libcloud-0.15.1/libcloud/compute/drivers/brightbox.py 2014-07-02 20:47:55.000000000 +0200 @@ -121,12 +121,15 @@ ) def _to_location(self, data): - return NodeLocation( - id=data['id'], - name=data['handle'], - country='GB', - driver=self - ) + if data: + return NodeLocation( + id=data['id'], + name=data['handle'], + country='GB', + driver=self + ) + else: + return None def _post(self, path, data={}): headers = {'Content-Type': 'application/json'} @@ -183,7 +186,7 @@ data = self.connection.request('/%s/servers' % self.api_version).object return list(map(self._to_node, data)) - def list_images(self): + def list_images(self, location=None): data = self.connection.request('/%s/images' % self.api_version).object return list(map(self._to_image, data)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/compute/drivers/cloudsigma.py new/apache-libcloud-0.15.1/libcloud/compute/drivers/cloudsigma.py --- old/apache-libcloud-0.15.0/libcloud/compute/drivers/cloudsigma.py 2014-06-03 22:18:20.000000000 +0200 +++ new/apache-libcloud-0.15.1/libcloud/compute/drivers/cloudsigma.py 2014-07-02 20:47:55.000000000 +0200 @@ -1611,8 +1611,8 @@ """ Retrieve a single tag. - :param id: ID of the tag to retrieve. - :type id: ``str`` + :param tag_id: ID of the tag to retrieve. + :type tag_id: ``str`` :rtype: ``list`` of :class:`.CloudSigmaTag` objects """ @@ -1674,8 +1674,8 @@ """ Associate tag with the provided resources. - :param resource: Resources to associate a tag with. - :type resource: ``list`` of :class:`libcloud.compute.base.Node` or + :param resources: Resources to associate a tag with. + :type resources: ``list`` of :class:`libcloud.compute.base.Node` or :class:`.CloudSigmaDrive` :param tag: Tag to associate with the resources. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/compute/drivers/cloudstack.py new/apache-libcloud-0.15.1/libcloud/compute/drivers/cloudstack.py --- old/apache-libcloud-0.15.0/libcloud/compute/drivers/cloudstack.py 2014-06-12 20:31:04.000000000 +0200 +++ new/apache-libcloud-0.15.1/libcloud/compute/drivers/cloudstack.py 2014-07-02 20:47:55.000000000 +0200 @@ -339,12 +339,23 @@ class CloudStackAddress(object): """ A public IP address. + + :param id: UUID of the Public IP + :type id: ``str`` + + :param address: The public IP address + :type address: ``str`` + + :param associated_network_id: The ID of the network where this address + has been associated with + :type associated_network_id: ``str`` """ - def __init__(self, id, address, driver): + def __init__(self, id, address, driver, associated_network_id=None): self.id = id self.address = address self.driver = driver + self.associated_network_id = associated_network_id def release(self): self.driver.ex_release_public_ip(address=self) @@ -1351,7 +1362,10 @@ return ips for ip in res['publicipaddress']: - ips.append(CloudStackAddress(ip['id'], ip['ipaddress'], self)) + ips.append(CloudStackAddress(ip['id'], + ip['ipaddress'], + self, + ip['associatednetworkid'])) return ips def ex_allocate_public_ip(self, location=None): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/compute/drivers/ec2.py new/apache-libcloud-0.15.1/libcloud/compute/drivers/ec2.py --- old/apache-libcloud-0.15.0/libcloud/compute/drivers/ec2.py 2014-06-22 20:10:09.000000000 +0200 +++ new/apache-libcloud-0.15.1/libcloud/compute/drivers/ec2.py 2014-07-02 20:47:55.000000000 +0200 @@ -1746,12 +1746,15 @@ Note: This class is VPC specific. """ - def __init__(self, id, routes, subnet_associations, + def __init__(self, id, name, routes, subnet_associations, propagating_gateway_ids, extra=None): """ :param id: The ID of the route table. :type id: ``str`` + :param name: The name of the route table. + :type name: ``str`` + :param routes: A list of routes in the route table. :type routes: ``list`` of :class:`EC2Route` @@ -1767,6 +1770,7 @@ """ self.id = id + self.name = name self.routes = routes self.subnet_associations = subnet_associations self.propagating_gateway_ids = propagating_gateway_ids @@ -1875,7 +1879,7 @@ 'terminated': NodeState.TERMINATED } - def list_nodes(self, ex_node_ids=None): + def list_nodes(self, ex_node_ids=None, ex_filters=None): """ List all nodes @@ -1886,21 +1890,34 @@ :param ex_node_ids: List of ``node.id`` :type ex_node_ids: ``list`` of ``str`` + :param ex_filters: The filters so that the response includes + information for only certain nodes. + :type ex_filters: ``dict`` + :rtype: ``list`` of :class:`Node` """ + params = {'Action': 'DescribeInstances'} + if ex_node_ids: params.update(self._pathlist('InstanceId', ex_node_ids)) + + if ex_filters: + params.update(self._build_filters(ex_filters)) + elem = self.connection.request(self.path, params=params).object + nodes = [] for rs in findall(element=elem, xpath='reservationSet/item', namespace=NAMESPACE): nodes += self._to_nodes(rs, 'instancesSet/item') nodes_elastic_ips_mappings = self.ex_describe_addresses(nodes) + for node in nodes: ips = nodes_elastic_ips_mappings[node.id] node.public_ips.extend(ips) + return nodes def list_sizes(self, location=None): @@ -1998,10 +2015,9 @@ 'Action': 'DescribeVolumes', } if node: - params.update({ - 'Filter.1.Name': 'attachment.instance-id', - 'Filter.1.Value': node.id, - }) + filters = {'attachment.instance-id': node.id} + params.update(self._build_filters(filters)) + response = self.connection.request(self.path, params=params).object volumes = [self._to_volume(el) for el in response.findall( fixxpath(xpath='volumeSet/item', namespace=NAMESPACE)) @@ -2193,7 +2209,10 @@ volume = self._to_volume( self.connection.request(self.path, params=params).object, name=name) - self.ex_create_tags(volume, {'Name': name}) + + if self.ex_create_tags(volume, {'Name': name}): + volume.extra['tags']['Name'] = name + return volume def attach_volume(self, node, volume, device): @@ -2245,8 +2264,8 @@ response = self.connection.request(self.path, params=params).object snapshot = self._to_snapshot(response, name) - if name: - self.ex_create_tags(snapshot, {'Name': name}) + if name and self.ex_create_tags(snapshot, {'Name': name}): + snapshot.extra['tags']['Name'] = name return snapshot @@ -2345,10 +2364,9 @@ 'Action': 'DeleteKeyPair', 'KeyName': key_pair.name } - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) - return element == 'true' + res = self.connection.request(self.path, params=params).object + + return self._get_boolean(res) def copy_image(self, image, source_region, name=None, description=None): """ @@ -2586,10 +2604,10 @@ element = response.findall(fixxpath(xpath='vpc', namespace=NAMESPACE))[0] - network = self._to_network(element) + network = self._to_network(element, name) - if name is not None: - self.ex_create_tags(network, {'Name': name}) + if name and self.ex_create_tags(network, {'Name': name}): + network.extra['tags']['Name'] = name return network @@ -2604,21 +2622,35 @@ """ params = {'Action': 'DeleteVpc', 'VpcId': vpc.id} - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) - def ex_list_subnets(self): + def ex_list_subnets(self, subnet_ids=None, filters=None): """ Return a list of :class:`EC2NetworkSubnet` objects for the current region. + :param subnet_ids: Return only subnets matching the provided + subnet IDs. If not specified, a list of all + the subnets in the corresponding region + is returned. + :type subnet_ids: ``list`` + + :param filters: The filters so that the response includes + information for only certain subnets. + :type filters: ``dict`` + :rtype: ``list`` of :class:`EC2NetworkSubnet` """ params = {'Action': 'DescribeSubnets'} + if subnet_ids: + params.update(self._pathlist('SubnetId', subnet_ids)) + + if filters: + params.update(self._build_filters(filters)) + return self._to_subnets( self.connection.request(self.path, params=params).object ) @@ -2653,10 +2685,10 @@ element = response.findall(fixxpath(xpath='subnet', namespace=NAMESPACE))[0] - subnet = self._to_subnet(element) + subnet = self._to_subnet(element, name) - if name is not None: - self.ex_create_tags(subnet, {'Name': name}) + if name and self.ex_create_tags(subnet, {'Name': name}): + subnet.extra['tags']['Name'] = name return subnet @@ -2671,12 +2703,9 @@ """ params = {'Action': 'DeleteSubnet', 'SubnetId': subnet.id} - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, - xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_list_security_groups(self): """ @@ -2778,11 +2807,9 @@ """ params = {'Action': 'DeleteSecurityGroup', 'GroupId': group_id} - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_delete_security_group_by_name(self, group_name): """ @@ -2795,11 +2822,9 @@ """ params = {'Action': 'DeleteSecurityGroup', 'GroupName': group_name} - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_delete_security_group(self, name): """ @@ -2844,10 +2869,9 @@ 'ToPort': str(to_port), 'CidrIp': cidr_ip} try: - resp = self.connection.request( + res = self.connection.request( self.path, params=params.copy()).object - return bool(findtext(element=resp, xpath='return', - namespace=NAMESPACE)) + return self._get_boolean(res) except Exception: e = sys.exc_info()[1] if e.args[0].find('InvalidPermission.Duplicate') == -1: @@ -2901,11 +2925,9 @@ params["Action"] = 'AuthorizeSecurityGroupIngress' - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_authorize_security_group_egress(self, id, from_port, to_port, cidr_ips, group_pairs=None, @@ -2957,11 +2979,9 @@ params["Action"] = 'AuthorizeSecurityGroupEgress' - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_revoke_security_group_ingress(self, id, from_port, to_port, cidr_ips=None, group_pairs=None, @@ -3011,11 +3031,9 @@ params["Action"] = 'RevokeSecurityGroupIngress' - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_revoke_security_group_egress(self, id, from_port, to_port, cidr_ips=None, group_pairs=None, @@ -3067,11 +3085,9 @@ params['Action'] = 'RevokeSecurityGroupEgress' - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_authorize_security_group_permissive(self, name): """ @@ -3140,12 +3156,11 @@ """ params = {'Action': 'DescribeAvailabilityZones'} + filters = {'region-name': self.region_name} if only_available: - params.update({'Filter.0.Name': 'state'}) - params.update({'Filter.0.Value.0': 'available'}) + filters['state'] = 'available' - params.update({'Filter.1.Name': 'region-name'}) - params.update({'Filter.1.Value.0': self.region_name}) + params.update(self._build_filters(filters)) result = self.connection.request(self.path, params=params.copy()).object @@ -3180,12 +3195,14 @@ :return: dict Node tags :rtype: ``dict`` """ - params = {'Action': 'DescribeTags', - 'Filter.0.Name': 'resource-id', - 'Filter.0.Value.0': resource.id, - 'Filter.1.Name': 'resource-type', - 'Filter.1.Value.0': 'instance', - } + params = {'Action': 'DescribeTags'} + + filters = { + 'resource-id': resource.id, + 'resource-type': 'instance' + } + + params.update(self._build_filters(filters)) result = self.connection.request(self.path, params=params).object @@ -3213,11 +3230,10 @@ params['Tag.%d.Key' % i] = key params['Tag.%d.Value' % i] = tags[key] - result = self.connection.request(self.path, - params=params.copy()).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) - return element == 'true' + res = self.connection.request(self.path, + params=params.copy()).object + + return self._get_boolean(res) def ex_delete_tags(self, resource, tags): """ @@ -3241,11 +3257,10 @@ params['Tag.%d.Key' % i] = key params['Tag.%d.Value' % i] = tags[key] - result = self.connection.request(self.path, - params=params.copy()).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) - return element == 'true' + res = self.connection.request(self.path, + params=params.copy()).object + + return self._get_boolean(res) def ex_get_metadata_for_node(self, node): """ @@ -3475,8 +3490,8 @@ """ Create a network interface within a VPC subnet. - :param node: EC2NetworkSubnet instance - :type node: :class:`EC2NetworkSubnet` + :param subnet: EC2NetworkSubnet instance + :type subnet: :class:`EC2NetworkSubnet` :param name: Optional name of the interface :type name: ``str`` @@ -3512,9 +3527,8 @@ interface = self._to_interface(element, name) - if name is not None: - tags = {'Name': name} - self.ex_create_tags(resource=interface, tags=tags) + if name and self.ex_create_tags(interface, {'Name': name}): + interface.extra['tags']['Name'] = name return interface @@ -3530,11 +3544,9 @@ params = {'Action': 'DeleteNetworkInterface', 'NetworkInterfaceId': network_interface.id} - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_attach_network_interface_to_node(self, network_interface, node, device_index): @@ -3585,11 +3597,9 @@ if force: params['Force'] = True - result = self.connection.request(self.path, params=params).object + res = self.connection.request(self.path, params=params).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) - return element == 'true' + return self._get_boolean(res) def ex_modify_instance_attribute(self, node, attributes): """ @@ -3611,18 +3621,17 @@ params = {'Action': 'ModifyInstanceAttribute'} params.update(attributes) - result = self.connection.request(self.path, - params=params.copy()).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) - return element == 'true' + res = self.connection.request(self.path, + params=params.copy()).object + + return self._get_boolean(res) def ex_modify_image_attribute(self, image, attributes): """ Modify image attributes. - :param node: Node instance - :type node: :class:`Node` + :param image: NodeImage instance + :type image: :class:`NodeImage` :param attributes: Dictionary with node attributes :type attributes: ``dict`` @@ -3636,11 +3645,10 @@ params = {'Action': 'ModifyImageAttribute'} params.update(attributes) - result = self.connection.request(self.path, - params=params.copy()).object - element = findtext(element=result, xpath='return', - namespace=NAMESPACE) - return element == 'true' + res = self.connection.request(self.path, + params=params.copy()).object + + return self._get_boolean(res) def ex_change_node_size(self, node, new_size): """ @@ -3976,16 +3984,33 @@ return result - def ex_list_internet_gateways(self): + def ex_list_internet_gateways(self, gateway_ids=None, filters=None): """ Describes available Internet gateways and whether or not they are attached to a VPC. These are required for VPC nodes to communicate over the Internet. + :param gateway_ids: Return only intenet gateways matching the + provided internet gateway IDs. If not + specified, a list of all the internet + gateways in the corresponding region is + returned. + :type gateway_ids: ``list`` + + :param filters: The filters so that the response includes + information for only certain gateways. + :type filters: ``dict`` + :rtype: ``list`` of :class:`.VPCInternetGateway` """ params = {'Action': 'DescribeInternetGateways'} + if gateway_ids: + params.update(self._pathlist('InternetGatewayId', gateway_ids)) + + if filters: + params.update(self._build_filters(filters)) + response = self.connection.request(self.path, params=params).object return self._to_internet_gateways(response, 'internetGatewaySet/item') @@ -4005,8 +4030,8 @@ gateway = self._to_internet_gateway(element[0], name) - if name is not None: - self.ex_create_tags(gateway, {'Name': name}) + if name and self.ex_create_tags(gateway, {'Name': name}): + gateway.extra['tags']['Name'] = name return gateway @@ -4022,12 +4047,9 @@ params = {'Action': 'DeleteInternetGateway', 'InternetGatewayId': gateway.id} - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, - xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_attach_internet_gateway(self, gateway, network): """ @@ -4045,12 +4067,9 @@ 'InternetGatewayId': gateway.id, 'VpcId': network.id} - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, - xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_detach_internet_gateway(self, gateway, network): """ @@ -4068,12 +4087,9 @@ 'InternetGatewayId': gateway.id, 'VpcId': network.id} - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, - xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_list_route_tables(self, route_table_ids=None, filters=None): """ @@ -4120,10 +4136,10 @@ element = response.findall(fixxpath(xpath='routeTable', namespace=NAMESPACE))[0] - route_table = self._to_route_table(element) + route_table = self._to_route_table(element, name=name) - if name: - self.ex_create_tags(route_table, {'Name': name}) + if name and self.ex_create_tags(route_table, {'Name': name}): + route_table.extra['tags']['Name'] = name return route_table @@ -4140,12 +4156,9 @@ params = {'Action': 'DeleteRouteTable', 'RouteTableId': route_table.id} - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, - xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_associate_route_table(self, route_table, subnet): """ @@ -4194,12 +4207,9 @@ params = {'Action': 'DisassociateRouteTable', 'AssociationId': subnet_association_id} - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, - xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_replace_route_table_association(self, subnet_association, route_table): @@ -4286,12 +4296,9 @@ if vpc_peering_connection: params['VpcPeeringConnectionId'] = vpc_peering_connection.id - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, - xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_delete_route(self, route_table, cidr): """ @@ -4310,12 +4317,9 @@ 'RouteTableId': route_table.id, 'DestinationCidrBlock': cidr} - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, - xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def ex_replace_route(self, route_table, cidr, internet_gateway=None, node=None, @@ -4365,12 +4369,9 @@ if vpc_peering_connection: params['VpcPeeringConnectionId'] = vpc_peering_connection.id - result = self.connection.request(self.path, params=params).object - element = findtext(element=result, - xpath='return', - namespace=NAMESPACE) + res = self.connection.request(self.path, params=params).object - return element == 'true' + return self._get_boolean(res) def _to_nodes(self, object, xpath): return [self._to_node(el) @@ -4472,6 +4473,8 @@ extra = self._get_extra_dict( element, RESOURCE_EXTRA_ATTRIBUTES_MAP['volume']) + extra['tags'] = tags + return StorageVolume(id=volId, name=name, size=int(size), @@ -4634,7 +4637,7 @@ fixxpath(xpath='vpcSet/item', namespace=NAMESPACE)) ] - def _to_network(self, element): + def _to_network(self, element, name=None): # Get the network id vpc_id = findtext(element=element, xpath='vpcId', @@ -4645,7 +4648,7 @@ # Set our name if the Name key/value if available # If we don't get anything back then use the vpc_id - name = tags.get('Name', vpc_id) + name = name if name else tags.get('Name', vpc_id) cidr_block = findtext(element=element, xpath='cidrBlock', @@ -4707,7 +4710,7 @@ fixxpath(xpath='subnetSet/item', namespace=NAMESPACE)) ] - def _to_subnet(self, element): + def _to_subnet(self, element, name=None): # Get the subnet ID subnet_id = findtext(element=element, xpath='subnetId', @@ -4717,7 +4720,7 @@ tags = self._get_resource_tags(element) # If we don't get anything back then use the subnet_id - name = tags.get('Name', subnet_id) + name = name if name else tags.get('Name', subnet_id) state = findtext(element=element, xpath='state', @@ -4901,7 +4904,7 @@ fixxpath(xpath='routeTableSet/item', namespace=NAMESPACE)) ] - def _to_route_table(self, element): + def _to_route_table(self, element, name=None): # route table id route_table_id = findtext(element=element, xpath='routeTableId', @@ -4932,7 +4935,9 @@ xpath='gatewayId', namespace=NAMESPACE)) - return EC2RouteTable(route_table_id, routes, subnet_associations, + name = name if name else tags.get('Name', id) + + return EC2RouteTable(route_table_id, name, routes, subnet_associations, propagating_gateway_ids, extra=extra) def _to_routes(self, element, xpath): @@ -5042,10 +5047,8 @@ """ Add instance filter to the provided params dictionary. """ - params.update({ - 'Filter.0.Name': 'instance-id', - 'Filter.0.Value.0': node.id - }) + filters = {'instance-id': node.id} + params.update(self._build_filters(filters)) return params diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/compute/drivers/gogrid.py new/apache-libcloud-0.15.1/libcloud/compute/drivers/gogrid.py --- old/apache-libcloud-0.15.0/libcloud/compute/drivers/gogrid.py 2014-06-03 22:18:20.000000000 +0200 +++ new/apache-libcloud-0.15.1/libcloud/compute/drivers/gogrid.py 2014-07-02 20:47:55.000000000 +0200 @@ -403,7 +403,7 @@ :type ex_description: ``str`` :keyword name: name of the image - :type name ``str`` + :type name: ``str`` :rtype: :class:`NodeImage` """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/compute/drivers/libvirt_driver.py new/apache-libcloud-0.15.1/libcloud/compute/drivers/libvirt_driver.py --- old/apache-libcloud-0.15.0/libcloud/compute/drivers/libvirt_driver.py 2014-06-03 22:18:20.000000000 +0200 +++ new/apache-libcloud-0.15.1/libcloud/compute/drivers/libvirt_driver.py 2014-07-02 20:47:55.000000000 +0200 @@ -12,6 +12,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import with_statement import re import os diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/compute/drivers/opennebula.py new/apache-libcloud-0.15.1/libcloud/compute/drivers/opennebula.py --- old/apache-libcloud-0.15.0/libcloud/compute/drivers/opennebula.py 2014-06-03 22:18:20.000000000 +0200 +++ new/apache-libcloud-0.15.1/libcloud/compute/drivers/opennebula.py 2014-07-02 20:47:55.000000000 +0200 @@ -415,9 +415,9 @@ """ List virtual networks on a provider. - :type location: :class:`NodeLocation` :param location: Location from which to request a list of virtual networks. (optional) + :type location: :class:`NodeLocation` :return: List of virtual networks available to be connected to a compute node. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/compute/drivers/openstack.py new/apache-libcloud-0.15.1/libcloud/compute/drivers/openstack.py --- old/apache-libcloud-0.15.0/libcloud/compute/drivers/openstack.py 2014-06-21 14:03:58.000000000 +0200 +++ new/apache-libcloud-0.15.1/libcloud/compute/drivers/openstack.py 2014-07-02 20:47:55.000000000 +0200 @@ -1083,7 +1083,7 @@ :type description: ``str`` :keyword rules: Rules associated with this group. - :type description: ``list`` of + :type rules: ``list`` of :class:`OpenStackSecurityGroupRule` :keyword extra: Extra attributes associated with this group. @@ -1259,6 +1259,9 @@ Can be either ``AUTO`` or ``MANUAL``. :type ex_disk_config: ``str`` + :keyword ex_admin_pass: The root password for the node + :type ex_admin_pass: ``str`` + :keyword ex_availability_zone: Nova availability zone for the node :type ex_availability_zone: ``str`` """ @@ -1345,6 +1348,9 @@ if 'ex_disk_config' in kwargs: server_params['OS-DCF:diskConfig'] = kwargs['ex_disk_config'] + if 'ex_admin_pass' in kwargs: + server_params['adminPass'] = kwargs['ex_admin_pass'] + if 'networks' in kwargs: networks = kwargs['networks'] networks = [{'uuid': network.id} for network in networks] @@ -1653,8 +1659,8 @@ """ Create a snapshot based off of a volume. - :param node: volume - :type node: :class:`StorageVolume` + :param volume: volume + :type volume: :class:`StorageVolume` :keyword name: New name for the volume snapshot :type name: ``str`` @@ -1680,8 +1686,8 @@ """ Delete a VolumeSnapshot - :param node: snapshot - :type node: :class:`VolumeSnapshot` + :param snapshot: snapshot + :type snapshot: :class:`VolumeSnapshot` :rtype: ``bool`` """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/dns/drivers/rackspace.py new/apache-libcloud-0.15.1/libcloud/dns/drivers/rackspace.py --- old/apache-libcloud-0.15.0/libcloud/dns/drivers/rackspace.py 2014-06-03 22:18:20.000000000 +0200 +++ new/apache-libcloud-0.15.1/libcloud/dns/drivers/rackspace.py 2014-07-02 20:47:55.000000000 +0200 @@ -93,7 +93,15 @@ def has_completed(self, response): status = response.object['status'] if status == 'ERROR': - raise LibcloudError(response.object['error']['message'], + data = response.object['error'] + + if 'code' and 'message' in data: + message = '%s - %s (%s)' % (data['code'], data['message'], + data['details']) + else: + message = data['message'] + + raise LibcloudError(message, driver=self.driver) return status == 'COMPLETED' @@ -318,6 +326,7 @@ updated_record = get_new_obj(obj=record, klass=Record, attributes={'type': type, 'data': data, + 'driver': self, 'extra': merged}) return updated_record diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupEgress_default.json new/apache-libcloud-0.15.1/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupEgress_default.json --- old/apache-libcloud-0.15.0/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupEgress_default.json 1970-01-01 01:00:00.000000000 +0100 +++ new/apache-libcloud-0.15.1/libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupEgress_default.json 2013-09-17 11:15:58.000000000 +0200 @@ -0,0 +1,2 @@ +{ "authorizesecuritygroupegressresponse" : {"jobid":17202} } + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupEgress_default.json new/apache-libcloud-0.15.1/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupEgress_default.json --- old/apache-libcloud-0.15.0/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupEgress_default.json 1970-01-01 01:00:00.000000000 +0100 +++ new/apache-libcloud-0.15.1/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupEgress_default.json 2013-09-17 11:18:07.000000000 +0200 @@ -0,0 +1,2 @@ +{ "revokesecuritygroupegressresponse" : {"jobid":17203} } + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/apache-libcloud-0.15.0/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupIngress_default.json new/apache-libcloud-0.15.1/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupIngress_default.json --- old/apache-libcloud-0.15.0/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupIngress_default.json 1970-01-01 01:00:00.000000000 +0100 +++ new/apache-libcloud-0.15.1/libcloud/test/compute/fixtures/cloudstack/revokeSecurityGroupIngress_default.json 2013-09-17 11:15:06.000000000 +0200 @@ -0,0 +1,2 @@ +{ "revokesecuritygroupingressresponse" : {"jobid":17201} } + -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org