diff --git a/libcloud/compute/drivers/cloudstack.py b/libcloud/compute/drivers/cloudstack.py index fb1961ee63..70284772f0 100644 --- a/libcloud/compute/drivers/cloudstack.py +++ b/libcloud/compute/drivers/cloudstack.py @@ -611,6 +611,32 @@ class CloudStackIPForwardingRule(object): """ def __init__(self, node, id, address, protocol, start_port, end_port=None): + """ + A NAT/firewall forwarding rule. + + @note: This is a non-standard extension API, and only works for + CloudStack. + + :param node: Node for rule + :type node: :class:`Node` + + :param id: Rule ID + :type id: ``int`` + + :param address: External IP address + :type address: :class:`CloudStackAddress` + + :param protocol: TCP/IP Protocol (TCP, UDP) + :type protocol: ``str`` + + :param start_port: Start port for the rule + :type start_port: ``int`` + + :param end_port: End port for the rule + :type end_port: ``int`` + + :rtype: :class:`CloudStackIPForwardingRule` + """ self.node = node self.id = id self.address = address @@ -2557,6 +2583,118 @@ def ex_delete_port_forwarding_rule(self, node, rule): method='GET') return res['success'] + def ex_list_ip_forwarding_rules(self, account=None, domain_id=None, + id=None, ipaddress_id=None, + is_recursive=None, keyword=None, + list_all=None, page=None, page_size=None, + project_id=None, virtualmachine_id=None): + """ + Lists all NAT/firewall forwarding rules + + :param account: List resources by account. + Must be used with the domainId parameter + :type account: ``str`` + + :param domain_id: List only resources belonging to + the domain specified + :type domain_id: ``str`` + + :param id: Lists rule with the specified ID + :type id: ``str`` + + :param ipaddress_id: list the rule belonging to + this public ip address + :type ipaddress_id: ``str`` + + :param is_recursive: Defaults to false, but if true, + lists all resources from + the parent specified by the + domainId till leaves. + :type is_recursive: ``bool`` + + :param keyword: List by keyword + :type keyword: ``str`` + + :param list_all: 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 list_all: ``bool`` + + :param page: The page to list the keypairs from + :type page: ``int`` + + :param page_size: The number of results per page + :type page_size: ``int`` + + :param project_id: list objects by project + :type project_id: ``str`` + + :param virtualmachine_id: Lists all rules applied to + the specified Vm + :type virtualmachine_id: ``str`` + + :rtype: ``list`` of :class:`CloudStackIPForwardingRule` + """ + + args = {} + + if account is not None: + args['account'] = account + + if domain_id is not None: + args['domainid'] = domain_id + + if id is not None: + args['id'] = id + + if ipaddress_id is not None: + args['ipaddressid'] = ipaddress_id + + if is_recursive is not None: + args['isrecursive'] = is_recursive + + if keyword is not None: + args['keyword'] = keyword + + if list_all is not None: + args['listall'] = list_all + + if page is not None: + args['page'] = page + + if page_size is not None: + args['pagesize'] = page_size + + if project_id is not None: + args['projectid'] = project_id + + if virtualmachine_id is not None: + args['virtualmachineid'] = virtualmachine_id + + result = self._sync_request(command='listIpForwardingRules', + params=args, + method='GET') + + rules = [] + if result != {}: + public_ips = self.ex_list_public_ips() + nodes = self.list_nodes() + for rule in result['ipforwardingrule']: + node = [n for n in nodes + if n.id == str(rule['virtualmachineid'])] + addr = [a for a in public_ips if + a.address == rule['ipaddress']] + rules.append(CloudStackIPForwardingRule + (node[0], + rule['id'], + addr[0], + rule['protocol'], + rule['startport'], + rule['endport'])) + return rules + def ex_create_ip_forwarding_rule(self, node, address, protocol, start_port, end_port=None): """ diff --git a/libcloud/test/compute/fixtures/cloudstack/listIpForwardingRules_default.json b/libcloud/test/compute/fixtures/cloudstack/listIpForwardingRules_default.json new file mode 100644 index 0000000000..20fbc42d3d --- /dev/null +++ b/libcloud/test/compute/fixtures/cloudstack/listIpForwardingRules_default.json @@ -0,0 +1 @@ +{ "listipforwardingrulesresponse" : { "count":1 ,"ipforwardingrule" : [ {"id":"772fd410-6649-43ed-befa-77be986b8906","protocol":"tcp","virtualmachineid":"2600","virtualmachinename":"test","virtualmachinedisplayname":"test","ipaddressid":34000,"ipaddress":"1.1.1.116","startport":33,"endport":34,"state":"Active"} ] } } diff --git a/libcloud/test/compute/test_cloudstack.py b/libcloud/test/compute/test_cloudstack.py index 38f01b8772..2e4930fb1a 100644 --- a/libcloud/test/compute/test_cloudstack.py +++ b/libcloud/test/compute/test_cloudstack.py @@ -962,6 +962,16 @@ def test_node_ex_create_port_forwarding_rule(self): self.assertEqual(rule.private_end_port, private_end_port) self.assertEqual(len(node.extra['port_forwarding_rules']), 2) + def test_ex_list_ip_forwarding_rules(self): + rules = self.driver.ex_list_ip_forwarding_rules() + self.assertEqual(len(rules), 1) + rule = rules[0] + self.assertTrue(rule.node) + self.assertEqual(rule.protocol, 'tcp') + self.assertEqual(rule.start_port, 33) + self.assertEqual(rule.end_port, 34) + self.assertEqual(rule.address.address, '1.1.1.116') + def test_ex_limits(self): limits = self.driver.ex_limits() self.assertEqual(limits['max_images'], 20)