Return-Path: X-Original-To: apmail-libcloud-notifications-archive@www.apache.org Delivered-To: apmail-libcloud-notifications-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 4CBE9115DE for ; Sun, 13 Jul 2014 15:11:00 +0000 (UTC) Received: (qmail 45799 invoked by uid 500); 13 Jul 2014 15:11:00 -0000 Delivered-To: apmail-libcloud-notifications-archive@libcloud.apache.org Received: (qmail 45758 invoked by uid 500); 13 Jul 2014 15:11:00 -0000 Mailing-List: contact notifications-help@libcloud.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@libcloud.apache.org Delivered-To: mailing list notifications@libcloud.apache.org Received: (qmail 45749 invoked by uid 500); 13 Jul 2014 15:10:59 -0000 Delivered-To: apmail-libcloud-commits@libcloud.apache.org Received: (qmail 45745 invoked by uid 99); 13 Jul 2014 15:10:59 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 13 Jul 2014 15:10:59 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 7DA2B919BD4; Sun, 13 Jul 2014 15:10:59 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sebgoa@apache.org To: commits@libcloud.apache.org Message-Id: <10635edbb4084f289b0c43ffb1521942@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: git commit: LIBCLOUD-594: Add firewall rule support for CloudStack driver Date: Sun, 13 Jul 2014 15:10:59 +0000 (UTC) Repository: libcloud Updated Branches: refs/heads/trunk 784e7beb0 -> fde249581 LIBCLOUD-594: Add firewall rule support for CloudStack driver Closes #337 Signed-off-by: Sebastien Goasguen Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/fde24958 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/fde24958 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/fde24958 Branch: refs/heads/trunk Commit: fde24958140d45e2bc9cc7d985124646fd6bf2c3 Parents: 784e7be Author: Atsushi Sasaki Authored: Sun Jul 6 14:32:20 2014 +0900 Committer: Sebastien Goasguen Committed: Sun Jul 13 11:10:21 2014 -0400 ---------------------------------------------------------------------- libcloud/compute/drivers/cloudstack.py | 150 +++++++++++++++++++ .../cloudstack/createFirewallRule_default.json | 1 + .../createFirewallRule_firewallicmp.json | 1 + .../cloudstack/deleteFirewallRule_default.json | 1 + .../cloudstack/listFirewallRules_default.json | 1 + .../listFirewallRules_firewallicmp.json | 1 + .../listPublicIpAddresses_firewallicmp.json | 1 + .../cloudstack/queryAsyncJobResult_1149341.json | 1 + .../cloudstack/queryAsyncJobResult_1149342.json | 1 + .../cloudstack/queryAsyncJobResult_1149343.json | 1 + libcloud/test/compute/test_cloudstack.py | 66 ++++++++ 11 files changed, 225 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/fde24958/libcloud/compute/drivers/cloudstack.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/cloudstack.py b/libcloud/compute/drivers/cloudstack.py index 6f60afe..81b8cb4 100644 --- a/libcloud/compute/drivers/cloudstack.py +++ b/libcloud/compute/drivers/cloudstack.py @@ -367,6 +367,61 @@ class CloudStackAddress(object): return self.__class__ is other.__class__ and self.id == other.id +class CloudStackFirewallRule(object): + """ + A firewall rule. + """ + + def __init__(self, id, address, cidr_list, protocol, + icmp_code=None, icmp_type=None, + start_port=None, end_port=None): + + """ + A Firewall rule. + + @note: This is a non-standard extension API, and only works for + CloudStack. + + :param id: Firewall Rule ID + :type id: ``int`` + + :param address: External IP address + :type address: :class:`CloudStackAddress` + + :param cidr_list: cidr list + :type cidr_list: ``str`` + + :param protocol: TCP/IP Protocol (TCP, UDP) + :type protocol: ``str`` + + :param icmp_code: Error code for this icmp message + :type icmp_code: ``int`` + + :param icmp_type: Type of the icmp message being sent + :type icmp_type: ``int`` + + :param start_port: start of port range + :type start_port: ``int`` + + :param end_port: end of port range + :type end_port: ``int`` + + :rtype: :class:`CloudStackFirewallRule` + """ + + self.id = id + self.address = address + self.cidr_list = cidr_list + self.protocol = protocol + self.icmp_code = icmp_code + self.icmp_type = icmp_type + self.start_port = start_port + self.end_port = end_port + + def __eq__(self, other): + return self.__class__ is other.__class__ and self.id == other.id + + class CloudStackIPForwardingRule(object): """ A NAT/firewall forwarding rule. @@ -1401,6 +1456,101 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver): method='GET') return res['success'] + def ex_list_firewall_rules(self): + """ + Lists all Firewall Rules + + :rtype: ``list`` of :class:`CloudStackFirewallRule` + """ + rules = [] + result = self._sync_request(command='listFirewallRules', + method='GET') + if result != {}: + public_ips = self.ex_list_public_ips() + for rule in result['firewallrule']: + addr = [a for a in public_ips if + a.address == rule['ipaddress']] + + rules.append(CloudStackFirewallRule(rule['id'], + addr[0], + rule['cidrlist'], + rule['protocol'], + rule.get('icmpcode'), + rule.get('icmptype'), + rule.get('startport'), + rule.get('endport'))) + + return rules + + def ex_create_firewall_rule(self, address, cidr_list, protocol, + icmp_code=None, icmp_type=None, + start_port=None, end_port=None): + """ + Creates a Firewalle Rule + + :param address: External IP address + :type address: :class:`CloudStackAddress` + + :param cidr_list: cidr list + :type cidr_list: ``str`` + + :param protocol: TCP/IP Protocol (TCP, UDP) + :type protocol: ``str`` + + :param icmp_code: Error code for this icmp message + :type icmp_code: ``int`` + + :param icmp_type: Type of the icmp message being sent + :type icmp_type: ``int`` + + :param start_port: start of port range + :type start_port: ``int`` + + :param end_port: end of port range + :type end_port: ``int`` + + :rtype: :class:`CloudStackFirewallRule` + """ + args = { + 'ipaddressid': address.id, + 'cidrlist': cidr_list, + 'protocol': protocol + } + if icmp_code is not None: + args['icmpcode'] = int(icmp_code) + if icmp_type is not None: + args['icmptype'] = int(icmp_type) + if start_port is not None: + args['startport'] = int(start_port) + if end_port is not None: + args['endport'] = int(end_port) + result = self._async_request(command='createFirewallRule', + params=args, + method='GET') + rule = CloudStackFirewallRule(result['firewallrule']['id'], + address, + cidr_list, + protocol, + icmp_code, + icmp_type, + start_port, + end_port) + return rule + + def ex_delete_firewall_rule(self, firewall_rule): + """ + Remove a Firewall rule. + + :param firewall_rule: Firewall rule which should be used + :type firewall_rule: :class:`CloudStackFirewallRule` + + :rtype: ``bool`` + """ + res = self._async_request(command='deleteFirewallRule', + params={'id': firewall_rule.id}, + method='GET') + return res['success'] + def ex_list_port_forwarding_rules(self): """ Lists all Port Forwarding Rules http://git-wip-us.apache.org/repos/asf/libcloud/blob/fde24958/libcloud/test/compute/fixtures/cloudstack/createFirewallRule_default.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/cloudstack/createFirewallRule_default.json b/libcloud/test/compute/fixtures/cloudstack/createFirewallRule_default.json new file mode 100644 index 0000000..aa9dadd --- /dev/null +++ b/libcloud/test/compute/fixtures/cloudstack/createFirewallRule_default.json @@ -0,0 +1 @@ +{ "createfirewallruleresponse" : {"jobid":1149341,"id":172465} } http://git-wip-us.apache.org/repos/asf/libcloud/blob/fde24958/libcloud/test/compute/fixtures/cloudstack/createFirewallRule_firewallicmp.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/cloudstack/createFirewallRule_firewallicmp.json b/libcloud/test/compute/fixtures/cloudstack/createFirewallRule_firewallicmp.json new file mode 100644 index 0000000..6f7a63e --- /dev/null +++ b/libcloud/test/compute/fixtures/cloudstack/createFirewallRule_firewallicmp.json @@ -0,0 +1 @@ +{ "createfirewallruleresponse" : {"jobid":1149343,"id":172466} } http://git-wip-us.apache.org/repos/asf/libcloud/blob/fde24958/libcloud/test/compute/fixtures/cloudstack/deleteFirewallRule_default.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/cloudstack/deleteFirewallRule_default.json b/libcloud/test/compute/fixtures/cloudstack/deleteFirewallRule_default.json new file mode 100644 index 0000000..719d96b --- /dev/null +++ b/libcloud/test/compute/fixtures/cloudstack/deleteFirewallRule_default.json @@ -0,0 +1 @@ +{ "deletefirewallruleresponse" : {"jobid":1149342} } http://git-wip-us.apache.org/repos/asf/libcloud/blob/fde24958/libcloud/test/compute/fixtures/cloudstack/listFirewallRules_default.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/cloudstack/listFirewallRules_default.json b/libcloud/test/compute/fixtures/cloudstack/listFirewallRules_default.json new file mode 100644 index 0000000..7834d9d --- /dev/null +++ b/libcloud/test/compute/fixtures/cloudstack/listFirewallRules_default.json @@ -0,0 +1 @@ +{"listfirewallrulesresponse": {"count": 1, "firewallrule": [ { "cidrlist": "192.168.0.0/16", "id": 171597, "ipaddress": "1.1.1.116", "protocol": "tcp", "startport": "33", "endport": "34", "ipaddressid": 34000, "state": "Active" }]}} http://git-wip-us.apache.org/repos/asf/libcloud/blob/fde24958/libcloud/test/compute/fixtures/cloudstack/listFirewallRules_firewallicmp.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/cloudstack/listFirewallRules_firewallicmp.json b/libcloud/test/compute/fixtures/cloudstack/listFirewallRules_firewallicmp.json new file mode 100644 index 0000000..36ec78b --- /dev/null +++ b/libcloud/test/compute/fixtures/cloudstack/listFirewallRules_firewallicmp.json @@ -0,0 +1 @@ +{"listfirewallrulesresponse": {"count": 1, "firewallrule": [ { "cidrlist": "192.168.0.0/16", "icmpcode": 0, "icmptype": 8, "id": 52394, "ipaddress": "1.1.1.116", "ipaddressid": 34000, "protocol": "icmp", "state": "Active" } ]}} http://git-wip-us.apache.org/repos/asf/libcloud/blob/fde24958/libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_firewallicmp.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_firewallicmp.json b/libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_firewallicmp.json new file mode 100644 index 0000000..ca80e12 --- /dev/null +++ b/libcloud/test/compute/fixtures/cloudstack/listPublicIpAddresses_firewallicmp.json @@ -0,0 +1 @@ +{ "listpublicipaddressesresponse" : { "publicipaddress" : [ {"id":34000,"ipaddress":"1.1.1.116","virtualmachineid":"2600","allocated":"2011-06-23T05:20:39+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33999,"ipaddress":"1.1.1.48","allocated":"2011-06-23T05:20:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"}, {"id":33998,"ipaddress":"1.1.1.47","allocated":"2011-06-23T05:20:30+0000","zoneid":1,"zonename":"Sydney","issourcenat":false,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allo cated"}, {"id":33970,"ipaddress":"1.1.1.19","allocated":"2011-06-20T04:08:34+0000","zoneid":1,"zonename":"Sydney","issourcenat":true,"account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","forvirtualnetwork":true,"isstaticnat":false,"associatednetworkid":860,"networkid":200,"state":"Allocated"} ] } } http://git-wip-us.apache.org/repos/asf/libcloud/blob/fde24958/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149341.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149341.json b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149341.json new file mode 100644 index 0000000..607bdb7 --- /dev/null +++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149341.json @@ -0,0 +1 @@ +{ "queryasyncjobresultresponse" : {"jobid":1149341,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"firewallrule":{"id":172465,"protocol":"tcp","startport":"33","endport":"34","ipaddressid":34000,"ipaddress":"1.1.1.116","state":"Active","cidrlist":"192.168.0.0/16"}}} } http://git-wip-us.apache.org/repos/asf/libcloud/blob/fde24958/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149342.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149342.json b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149342.json new file mode 100644 index 0000000..9b35f8a --- /dev/null +++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149342.json @@ -0,0 +1 @@ +{ "queryasyncjobresultresponse" : {"jobid":1149342,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true}} } http://git-wip-us.apache.org/repos/asf/libcloud/blob/fde24958/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149343.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149343.json b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149343.json new file mode 100644 index 0000000..5c1a7f8 --- /dev/null +++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_1149343.json @@ -0,0 +1 @@ +{ "queryasyncjobresultresponse" : {"jobid":1149343,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"firewallrule":{"id":172466,"protocol":"icmp","ipaddressid":34000,"ipaddress":"1.1.1.116","state":"Active","cidrlist":"192.168.0.0/16","icmptype":8,"icmpcode":0}}} } http://git-wip-us.apache.org/repos/asf/libcloud/blob/fde24958/libcloud/test/compute/test_cloudstack.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_cloudstack.py b/libcloud/test/compute/test_cloudstack.py index b8bb279..aade378 100644 --- a/libcloud/test/compute/test_cloudstack.py +++ b/libcloud/test/compute/test_cloudstack.py @@ -546,6 +546,72 @@ class CloudStackCommonTestCase(TestCaseMixin): self.assertEqual(rule.private_port, private_port) self.assertEqual(rule.private_end_port, private_end_port) + def test_ex_list_firewall_rules(self): + rules = self.driver.ex_list_firewall_rules() + self.assertEqual(len(rules), 1) + rule = rules[0] + self.assertEqual(rule.address.address, '1.1.1.116') + self.assertEqual(rule.protocol, 'tcp') + self.assertEqual(rule.cidr_list, '192.168.0.0/16') + self.assertIsNone(rule.icmp_code) + self.assertIsNone(rule.icmp_type) + self.assertEqual(rule.start_port, '33') + self.assertEqual(rule.end_port, '34') + + def test_ex_list_firewall_rules_icmp(self): + CloudStackMockHttp.fixture_tag = 'firewallicmp' + rules = self.driver.ex_list_firewall_rules() + self.assertEqual(len(rules), 1) + rule = rules[0] + self.assertEqual(rule.address.address, '1.1.1.116') + self.assertEqual(rule.protocol, 'icmp') + self.assertEqual(rule.cidr_list, '192.168.0.0/16') + self.assertEqual(rule.icmp_code, 0) + self.assertEqual(rule.icmp_type, 8) + self.assertIsNone(rule.start_port) + self.assertIsNone(rule.end_port) + + def test_ex_delete_firewall_rule(self): + rules = self.driver.ex_list_firewall_rules() + res = self.driver.ex_delete_firewall_rule(rules[0]) + self.assertTrue(res) + + def test_ex_create_firewall_rule(self): + address = self.driver.ex_list_public_ips()[0] + cidr_list = '192.168.0.0/16' + protocol = 'TCP' + start_port = 33 + end_port = 34 + rule = self.driver.ex_create_firewall_rule(address, + cidr_list, + protocol, + start_port=start_port, + end_port=end_port) + self.assertEqual(rule.address, address) + self.assertEqual(rule.protocol, protocol) + self.assertIsNone(rule.icmp_code) + self.assertIsNone(rule.icmp_type) + self.assertEqual(rule.start_port, start_port) + self.assertEqual(rule.end_port, end_port) + + def test_ex_create_firewall_rule_icmp(self): + address = self.driver.ex_list_public_ips()[0] + cidr_list = '192.168.0.0/16' + protocol = 'icmp' + icmp_code = 0 + icmp_type = 8 + rule = self.driver.ex_create_firewall_rule(address, + cidr_list, + protocol, + icmp_code=icmp_code, + icmp_type=icmp_type) + self.assertEqual(rule.address, address) + self.assertEqual(rule.protocol, protocol) + self.assertEqual(rule.icmp_code, 0) + self.assertEqual(rule.icmp_type, 8) + self.assertIsNone(rule.start_port) + self.assertIsNone(rule.end_port) + def test_ex_list_port_forwarding_rules(self): rules = self.driver.ex_list_port_forwarding_rules() self.assertEqual(len(rules), 1)