def ex_limits(self): """ Extra call to get account's limits, such as rates (for example amount of POST requests per day) and absolute limits like total amount of available RAM to be used by servers. @return: C{dict} with keys 'rate' and 'absolute' """ def _to_rate(el): rate = {} for item in el.items(): rate[item[0]] = item[1] return rate def _to_absolute(el): return {el.get('name'): el.get('value')} limits = self.connection.request("/limits").object rate = [_to_rate(el) for el in findall(limits, 'rate/limit', self.XML_NAMESPACE)] absolute = {} for item in findall(limits, 'absolute/limit', self.XML_NAMESPACE): absolute.update(_to_absolute(item)) return {"rate": rate, "absolute": absolute}
def _to_node(self, el): def get_ips(el): return [ip.get('addr') for ip in el] def get_meta_dict(el): d = {} for meta in el: d[meta.get('key')] = meta.text return d public_ip = get_ips(findall(el, 'addresses/public/ip', self.XML_NAMESPACE)) private_ip = get_ips(findall(el, 'addresses/private/ip', self.XML_NAMESPACE)) metadata = get_meta_dict(findall(el, 'metadata/meta', self.XML_NAMESPACE)) n = Node(id=el.get('id'), name=el.get('name'), state=self.NODE_STATE_MAP.get( el.get('status'), NodeState.UNKNOWN), public_ips=public_ip, private_ips=private_ip, driver=self.connection.driver, extra={ 'password': el.get('adminPass'), 'hostId': el.get('hostId'), 'imageId': el.get('imageId'), 'flavorId': el.get('flavorId'), 'uri': "https://%s%s/servers/%s" % ( self.connection.host, self.connection.request_path, el.get('id')), 'metadata': metadata, }) return n
def _to_ip_addresses(self, el): return OpenStack_1_0_NodeIpAddresses( [ip.get('addr') for ip in findall(findall(el, 'public', self.XML_NAMESPACE)[0], 'ip', self.XML_NAMESPACE)], [ip.get('addr') for ip in findall(findall(el, 'private', self.XML_NAMESPACE)[0], 'ip', self.XML_NAMESPACE)])
def _to_shared_ip_group(self, el): servers_el = findall(el, 'servers', self.XML_NAMESPACE) if servers_el: servers = [s.get('id') for s in findall(servers_el[0], 'server', self.XML_NAMESPACE)] else: servers = None return OpenStack_1_0_SharedIpGroup(id=el.get('id'), name=el.get('name'), servers=servers)
def ex_describe_tags(self, node): """ Return a dictionary of tags for this instance. @type node: C{Node} @param node: Node instance @return dict Node tags """ params = {'Action': 'DescribeTags', 'Filter.0.Name': 'resource-id', 'Filter.0.Value.0': node.id, 'Filter.1.Name': 'resource-type', 'Filter.1.Value.0': 'instance', } result = self.connection.request(self.path, params=params.copy()).object tags = {} for element in findall(element=result, xpath='tagSet/item', namespace=NAMESPACE): key = findtext(element=element, xpath='key', namespace=NAMESPACE) value = findtext(element=element, xpath='value', namespace=NAMESPACE) tags[key] = value return tags
def ex_list_ip_groups(self, details=False): uri = '/shared_ip_groups/detail' if details else '/shared_ip_groups' resp = self.connection.request(uri, method='GET') groups = findall(resp.object, 'sharedIpGroup', self.XML_NAMESPACE) return [self._to_shared_ip_group(el) for el in groups]
def parse_error(self): status = int(self.status) if status == 401: if not self.body: raise InvalidCredsError(str(self.status) + ': ' + self.error) else: raise InvalidCredsError(self.body) elif status == 404: context = self.connection.context if context['resource'] == 'zone': raise ZoneDoesNotExistError(value='', driver=self, zone_id=context['id']) elif context['resource'] == 'record': raise RecordDoesNotExistError(value='', driver=self, record_id=context['id']) elif status != 503: try: body = ET.XML(self.body) except: raise MalformedResponseError('Failed to parse XML', body=self.body) errors = [] for error in findall(element=body, xpath='error'): errors.append(error.text) raise ZerigoError(code=status, errors=errors) return self.body
def list_nodes(self): params = {'Action': 'DescribeInstances'} elem = self.connection.request(self.path, params=params).object nodes = [] for rs in findall(element=elem, xpath='reservationSet/item', namespace=NAMESPACE): groups = [g.findtext('') for g in findall(element=rs, xpath='groupSet/item/groupId', namespace=NAMESPACE)] nodes += self._to_nodes(rs, 'instancesSet/item', groups) nodes_elastic_ips_mappings = self.ex_describe_addresses(nodes) for node in nodes: node.public_ip.extend(nodes_elastic_ips_mappings[node.id]) return nodes
def ex_describe_all_addresses(self, only_allocated=False): """ Return all the Elastic IP addresses for this account optionally, return only the allocated addresses @keyword only_allocated: If true, return only those addresses that are associated with an instance @type only_allocated: C{string} @return list list of elastic ips for this particular account. """ params = {'Action': 'DescribeAddresses'} result = self.connection.request(self.path, params=params.copy()).object # the list which we return elastic_ip_addresses = [] for element in findall(element=result, xpath='addressesSet/item', namespace=NAMESPACE): instance_id = findtext(element=element, xpath='instanceId', namespace=NAMESPACE) # if only allocated addresses are requested if only_allocated and not instance_id: continue ip_address = findtext(element=element, xpath='publicIp', namespace=NAMESPACE) elastic_ip_addresses.append(ip_address) return elastic_ip_addresses
def list_nodes(self): params = {'Action': 'DescribeInstances'} elem = self.connection.request(self.path, params=params).object nodes = [] for rs in findall(element=elem, xpath='reservationSet/item', namespace=NAMESPACE): groups = [g.findtext('') for g in findall(element=rs, xpath='groupSet/item/groupId', namespace=NAMESPACE)] nodes += self._to_nodes(rs, 'instancesSet/item', groups) 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 _to_records(self, elem, zone): records = [] for item in findall(element=elem, xpath='host'): record = self._to_record(elem=item, zone=zone) records.append(record) return records
def _to_zones(self, elem): zones = [] for item in findall(element=elem, xpath='zone'): zone = self._to_zone(elem=item) zones.append(zone) return zones
def _to_images(self, object, ex_only_active): images = [] for image in findall(object, 'image', self.XML_NAMESPACE): if ex_only_active and image.get('status') != 'ACTIVE': continue images.append(self._to_image(image)) return images
def _get_state_boolean(self, element): """ Checks for the instances's state """ state = findall(element=element, xpath='instancesSet/item/currentState/name', namespace=NAMESPACE)[0].text return state in ('stopping', 'pending', 'starting')
def ex_describe_addresses(self, nodes): """ Return Elastic IP addresses for all the nodes in the provided list. @type nodes: C{list} @param nodes: List of C{Node} instances @return dict Dictionary where a key is a node ID and the value is a list with the Elastic IP addresses associated with this node. """ if not nodes: return {} params = {'Action': 'DescribeAddresses'} if len(nodes) == 1: params.update({ 'Filter.0.Name': 'instance-id', 'Filter.0.Value.0': nodes[0].id }) result = self.connection.request(self.path, params=params.copy()).object node_instance_ids = [node.id for node in nodes] nodes_elastic_ip_mappings = {} for node_id in node_instance_ids: nodes_elastic_ip_mappings.setdefault(node_id, []) for element in findall(element=result, xpath='addressesSet/item', namespace=NAMESPACE): instance_id = findtext(element=element, xpath='instanceId', namespace=NAMESPACE) ip_address = findtext(element=element, xpath='publicIp', namespace=NAMESPACE) if instance_id not in node_instance_ids: continue nodes_elastic_ip_mappings[instance_id].append(ip_address) return nodes_elastic_ip_mappings
def ex_list_availability_zones(self, only_available=True): """ Return a list of L{ExEC2AvailabilityZone} objects for the current region. Note: This is an extension method and is only available for EC2 driver. @keyword only_available: If true, return only availability zones with state 'available' @type only_available: C{string} """ params = {'Action': 'DescribeAvailabilityZones'} if only_available: params.update({'Filter.0.Name': 'state'}) params.update({'Filter.0.Value.0': 'available'}) params.update({'Filter.1.Name': 'region-name'}) params.update({'Filter.1.Value.0': self.region_name}) result = self.connection.request(self.path, params=params.copy()).object availability_zones = [] for element in findall(element=result, xpath='availabilityZoneInfo/item', namespace=NAMESPACE): name = findtext(element=element, xpath='zoneName', namespace=NAMESPACE) zone_state = findtext(element=element, xpath='zoneState', namespace=NAMESPACE) region_name = findtext(element=element, xpath='regionName', namespace=NAMESPACE) availability_zone = ExEC2AvailabilityZone(name=name, zone_state=zone_state, region_name=region_name) availability_zones.append(availability_zone) return availability_zones
def ex_list_availability_zones(self, only_available=True): """ Return a list of L{ExEC2AvailabilityZone} objects for the current region. Note: This is an extension method and is only available for EC2 driver. @keyword only_available: If true, return only availability zones with state 'available' @type only_available: C{string} """ params = {'Action': 'DescribeAvailabilityZones'} if only_available: params.update({'Filter.0.Name': 'state'}) params.update({'Filter.0.Value.0': 'available'}) params.update({'Filter.1.Name': 'region-name'}) params.update({'Filter.1.Value.0': self.region_name}) result = self.connection.request(self.path, params=params.copy()).object availability_zones = [] for element in findall(element=result, xpath='availabilityZoneInfo/item', namespace=NAMESPACE): name = findtext(element=element, xpath='zoneName', namespace=NAMESPACE) zone_state = findtext(element=element, xpath='zoneState', namespace=NAMESPACE) region_name = findtext(element=element, xpath='regionName', namespace=NAMESPACE) availability_zone = ExEC2AvailabilityZone( name=name, zone_state=zone_state, region_name=region_name ) availability_zones.append(availability_zone) return availability_zones
def ex_describe_addresses(self, nodes): """ Return Elastic IP addresses for all the nodes in the provided list. @type nodes: C{list} @param nodes: List of C{Node} instances @return dict Dictionary where a key is a node ID and the value is a list with the Elastic IP addresses associated with this node. """ if not nodes: return {} params = {'Action': 'DescribeAddresses'} if len(nodes) == 1: self._add_instance_filter(params, nodes[0]) result = self.connection.request(self.path, params=params.copy()).object node_instance_ids = [node.id for node in nodes] nodes_elastic_ip_mappings = {} for node_id in node_instance_ids: nodes_elastic_ip_mappings.setdefault(node_id, []) for element in findall(element=result, xpath='addressesSet/item', namespace=NAMESPACE): instance_id = findtext(element=element, xpath='instanceId', namespace=NAMESPACE) ip_address = findtext(element=element, xpath='publicIp', namespace=NAMESPACE) if instance_id not in node_instance_ids: continue nodes_elastic_ip_mappings[instance_id].append(ip_address) return nodes_elastic_ip_mappings
def _to_node(self, element, groups=None): try: state = self.NODE_STATE_MAP[ findattr(element=element, xpath="instanceState/name", namespace=NAMESPACE) ] except KeyError: state = NodeState.UNKNOWN instance_id = findtext(element=element, xpath='instanceId', namespace=NAMESPACE) tags = dict((findtext(element=item, xpath='key', namespace=NAMESPACE), findtext(element=item, xpath='value', namespace=NAMESPACE)) for item in findall(element=element, xpath='tagSet/item', namespace=NAMESPACE)) name = tags.get('Name', instance_id) n = Node( id=findtext(element=element, xpath='instanceId', namespace=NAMESPACE), name=name, state=state, public_ip=[findtext(element=element, xpath='ipAddress', namespace=NAMESPACE)], private_ip=[findtext(element=element, xpath='privateIpAddress', namespace=NAMESPACE)], driver=self.connection.driver, extra={ 'dns_name': findattr(element=element, xpath="dnsName", namespace=NAMESPACE), 'instanceId': findattr(element=element, xpath="instanceId", namespace=NAMESPACE), 'imageId': findattr(element=element, xpath="imageId", namespace=NAMESPACE), 'private_dns': findattr(element=element, xpath="privateDnsName", namespace=NAMESPACE), 'status': findattr(element=element, xpath="instanceState/name", namespace=NAMESPACE), 'keyname': findattr(element=element, xpath="keyName", namespace=NAMESPACE), 'launchindex': findattr(element=element, xpath="amiLaunchIndex", namespace=NAMESPACE), 'productcode': [p.text for p in findall(element=element, xpath="productCodesSet/item/productCode", namespace=NAMESPACE )], 'instancetype': findattr(element=element, xpath="instanceType", namespace=NAMESPACE), 'launchdatetime': findattr(element=element, xpath="launchTime", namespace=NAMESPACE), 'availability': findattr(element, xpath="placement/availabilityZone", namespace=NAMESPACE), 'kernelid': findattr(element=element, xpath="kernelId", namespace=NAMESPACE), 'ramdiskid': findattr(element=element, xpath="ramdiskId", namespace=NAMESPACE), 'clienttoken': findattr(element=element, xpath="clientToken", namespace=NAMESPACE), 'groups': groups, 'tags': tags } ) return n
def _to_networks(self, object): networks = [] for element in findall(object, 'network', NETWORK_NS): networks.append(self._to_network(element)) return networks
def _to_networks(self, object): node_elements = findall(object, 'network', NETWORK_NS) return [self._to_network(el) for el in node_elements]
def _to_sizes(self, object): elements = findall(object, 'flavor', self.XML_NAMESPACE) return [self._to_size(el) for el in elements]
def _to_node_from_obj(self, obj): return self._to_node(findall(obj, 'server', self.XML_NAMESPACE)[0])
def _to_nodes(self, object): node_elements = findall(object, 'server', self.XML_NAMESPACE) return [self._to_node(el) for el in node_elements]
def _to_node(self, element, groups=None): try: state = self.NODE_STATE_MAP[ findattr(element=element, xpath="instanceState/name", namespace=NAMESPACE) ] except KeyError: state = NodeState.UNKNOWN instance_id = findtext(element=element, xpath='instanceId', namespace=NAMESPACE) tags = dict((findtext(element=item, xpath='key', namespace=NAMESPACE), findtext(element=item, xpath='value', namespace=NAMESPACE)) for item in findall(element=element, xpath='tagSet/item', namespace=NAMESPACE)) name = tags.get('Name', instance_id) public_ip = findtext(element=element, xpath='ipAddress', namespace=NAMESPACE) public_ips = [public_ip] if public_ip else [] private_ip = findtext(element=element, xpath='privateIpAddress', namespace=NAMESPACE) private_ips = [private_ip] if private_ip else [] n = Node( id=findtext(element=element, xpath='instanceId', namespace=NAMESPACE), name=name, state=state, public_ips=public_ips, private_ips=private_ips, driver=self.connection.driver, extra={ 'dns_name': findattr(element=element, xpath="dnsName", namespace=NAMESPACE), 'instanceId': findattr(element=element, xpath="instanceId", namespace=NAMESPACE), 'imageId': findattr(element=element, xpath="imageId", namespace=NAMESPACE), 'private_dns': findattr(element=element, xpath="privateDnsName", namespace=NAMESPACE), 'status': findattr(element=element, xpath="instanceState/name", namespace=NAMESPACE), 'keyname': findattr(element=element, xpath="keyName", namespace=NAMESPACE), 'launchindex': findattr(element=element, xpath="amiLaunchIndex", namespace=NAMESPACE), 'productcode': [p.text for p in findall(element=element, xpath="productCodesSet/item/productCode", namespace=NAMESPACE )], 'instancetype': findattr(element=element, xpath="instanceType", namespace=NAMESPACE), 'launchdatetime': findattr(element=element, xpath="launchTime", namespace=NAMESPACE), 'availability': findattr(element, xpath="placement/availabilityZone", namespace=NAMESPACE), 'kernelid': findattr(element=element, xpath="kernelId", namespace=NAMESPACE), 'ramdiskid': findattr(element=element, xpath="ramdiskId", namespace=NAMESPACE), 'clienttoken': findattr(element=element, xpath="clientToken", namespace=NAMESPACE), 'groups': groups, 'tags': tags } ) return n