You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by se...@apache.org on 2014/07/13 17:10:59 UTC

git commit: LIBCLOUD-594: Add firewall rule support for CloudStack driver

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 <ru...@gmail.com>


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 <at...@gmail.com>
Authored: Sun Jul 6 14:32:20 2014 +0900
Committer: Sebastien Goasguen <ru...@gmail.com>
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)