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/09/26 10:42:40 UTC
git commit: Cloudstack - Added VPC support and Egress Firewall rule
support
Repository: libcloud
Updated Branches:
refs/heads/trunk 69f84e61a -> d608085e3
Cloudstack - Added VPC support and Egress Firewall rule support
Signed-off-by: Sebastien Goasguen <ru...@gmail.com>
This closes: #364
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d608085e
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d608085e
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d608085e
Branch: refs/heads/trunk
Commit: d608085e3da79240b2b56709ef6adb58bd9c9dab
Parents: 69f84e6
Author: Jeroen de Korte <jd...@schubergphilis.com>
Authored: Thu Sep 25 15:27:20 2014 +0200
Committer: Sebastien Goasguen <ru...@gmail.com>
Committed: Fri Sep 26 04:41:32 2014 -0400
----------------------------------------------------------------------
CHANGES.rst | 4 +
libcloud/compute/drivers/cloudstack.py | 350 ++++++++++++++++++-
.../createEgressFirewallRule_default.json | 1 +
.../fixtures/cloudstack/createVPC_default.json | 1 +
.../deleteEgressFirewallRule_default.json | 1 +
.../fixtures/cloudstack/deleteVPC_default.json | 1 +
.../listEgressFirewallRules_default.json | 1 +
.../cloudstack/listVPCOfferings_default.json | 1 +
.../fixtures/cloudstack/listVPCs_default.json | 1 +
.../queryAsyncJobResult_deleteVPC.json | 1 +
libcloud/test/compute/test_cloudstack.py | 90 +++++
11 files changed, 451 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d608085e/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index 372d271..fba5f48 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -122,6 +122,10 @@ Compute
(GITHUB-363, LIBCLOUD-616)
[Oleg Suharev]
+- Added VPC support and Egress Firewall rule support fo CloudStack
+ (GITHUB-363)
+ [Jeroen de Korte]
+
Storage
~~~~~~~
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d608085e/libcloud/compute/drivers/cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/cloudstack.py b/libcloud/compute/drivers/cloudstack.py
index 858553d..0129e07 100644
--- a/libcloud/compute/drivers/cloudstack.py
+++ b/libcloud/compute/drivers/cloudstack.py
@@ -217,6 +217,40 @@ RESOURCE_EXTRA_ATTRIBUTES_MAP = {
'transform_func': str
}
},
+ 'vpc': {
+ 'created': {
+ 'key_name': 'created',
+ 'transform_func': str
+ },
+ 'domain': {
+ 'key_name': 'domain',
+ 'transform_func': str
+ },
+ 'domain_id': {
+ 'key_name': 'domainid',
+ 'transform_func': int
+ },
+ 'network_domain': {
+ 'key_name': 'networkdomain',
+ 'transform_func': str
+ },
+ 'state': {
+ 'key_name': 'state',
+ 'transform_func': str
+ },
+ 'vpc_offering_id': {
+ 'key_name': 'vpcofferingid',
+ 'transform_func': str
+ },
+ 'zone_name': {
+ 'key_name': 'zonename',
+ 'transform_func': str
+ },
+ 'zone_id': {
+ 'key_name': 'zoneid',
+ 'transform_func': str
+ }
+ },
'project': {
'account': {'key_name': 'account', 'transform_func': str},
'cpuavailable': {'key_name': 'cpuavailable', 'transform_func': int},
@@ -426,6 +460,62 @@ class CloudStackFirewallRule(object):
return self.__class__ is other.__class__ and self.id == other.id
+class CloudStackEgressFirewallRule(object):
+ """
+ A egress firewall rule.
+ """
+
+ def __init__(self, id, network_id, cidr_list, protocol,
+ icmp_code=None, icmp_type=None,
+ start_port=None, end_port=None):
+
+ """
+ A egress firewall rule.
+
+ @note: This is a non-standard extension API, and only works for
+ CloudStack.
+
+ :param id: Firewall Rule ID
+ :type id: ``int``
+
+ :param network_id: the id network network for the egress firwall
+ services
+ :type network_id: ``str``
+
+ :param protocol: TCP/IP Protocol (TCP, UDP)
+ :type protocol: ``str``
+
+ :param cidr_list: cidr list
+ :type cidr_list: ``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:`CloudStackEgressFirewallRule`
+ """
+
+ self.id = id
+ self.network_id = network_id
+ 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.
@@ -564,6 +654,51 @@ class CloudStackNetworkOffering(object):
self.driver.name))
+class CloudStackVPC(object):
+ """
+ Class representing a CloudStack VPC.
+ """
+
+ def __init__(self, display_text, name, vpc_offering_id, id, zone_id, cidr,
+ driver, extra=None):
+ self.display_text = display_text
+ self.name = name
+ self.vpc_offering_id = vpc_offering_id
+ self.id = id
+ self.zone_id = zone_id
+ self.cidr = cidr
+ self.driver = driver
+ self.extra = extra or {}
+
+ def __repr__(self):
+ return (('<CloudStackVPC: id=%s, displaytext=%s, name=%s, '
+ 'vpc_offering_id=%s, zoneid=%s, cidr=%s, driver%s>')
+ % (self.id, self.displaytext, self.name,
+ self.vpc_offering_id, self.zoneid, self.cidr,
+ self.driver.name))
+
+
+class CloudStackVPCOffering(object):
+ """
+ Class representing a CloudStack VPC Offering.
+ """
+
+ def __init__(self, name, display_text, id,
+ driver, extra=None):
+ self.name = name
+ self.display_text = display_text
+ self.id = id
+ self.driver = driver
+ self.extra = extra or {}
+
+ def __repr__(self):
+ return (('<CloudStackVPCOffering: id=%s, name=%s, '
+ 'display_text=%s, '
+ 'driver%s>')
+ % (self.id, self.name, self.display_text,
+ self.driver.name))
+
+
class CloudStackProject(object):
"""
Class representing a CloudStack Project.
@@ -1132,6 +1267,125 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
method='GET')
return True
+ def ex_list_vpc_offerings(self):
+ """
+ List the available vpc offerings
+
+ :rtype ``list`` of :class:`CloudStackVPCOffering`
+ """
+ res = self._sync_request(command='listVPCOfferings',
+ method='GET')
+ vpcoffers = res.get('vpcoffering', [])
+
+ vpcofferings = []
+
+ for vpcoffer in vpcoffers:
+ vpcofferings.append(CloudStackVPCOffering(
+ vpcoffer['name'],
+ vpcoffer['displaytext'],
+ vpcoffer['id'],
+ self))
+
+ return vpcofferings
+
+ def ex_list_vpcs(self):
+ """
+ List the available VPCs
+
+ :rtype ``list`` of :class:`CloudStackVPC`
+ """
+
+ res = self._sync_request(command='listVPCs',
+ method='GET')
+ vpcs = res.get('vpc', [])
+
+ networks = []
+ for vpc in vpcs:
+
+ networks.append(CloudStackVPC(
+ vpc['displaytext'],
+ vpc['name'],
+ vpc['vpcofferingid'],
+ vpc['id'],
+ vpc['zoneid'],
+ vpc['cidr'],
+ self))
+
+ return networks
+
+ def ex_create_vpc(self, cidr, display_text, name, vpc_offering,
+ zoneid):
+ """
+
+ Creates a VPC, only available in advanced zones.
+
+ :param cidr: the cidr of the VPC. All VPC guest networks' cidrs
+ should be within this CIDR
+
+ :type display_text: ``str``
+
+ :param display_text: the display text of the VPC
+ :type display_text: ``str``
+
+ :param name: the name of the VPC
+ :type name: ``str``
+
+ :param vpc_offering: the ID of the VPC offering
+ :type vpc_offering: :class:'CloudStackVPCOffering`
+
+ :param zoneid: the ID of the availability zone
+ :type zoneid: ``str``
+
+ :rtype: :class:`CloudStackVPC`
+
+ """
+
+ extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['vpc']
+
+ args = {
+ 'cidr': cidr,
+ 'displaytext': display_text,
+ 'name': name,
+ 'vpcofferingid': vpc_offering.id,
+ 'zoneid': zoneid,
+ }
+
+ result = self._sync_request(command='createVPC',
+ params=args,
+ method='GET')
+
+ extra = self._get_extra_dict(result, extra_map)
+
+ vpc = CloudStackVPC(display_text,
+ name,
+ vpc_offering.id,
+ result['id'],
+ zoneid,
+ cidr,
+ self,
+ extra=extra)
+
+ return vpc
+
+ def ex_delete_vpc(self, vpc):
+ """
+
+ Deletes a VPC, only available in advanced zones.
+
+ :param vpc: The VPC
+ :type vpc: :class: 'CloudStackVPC'
+
+ :rtype: ``bool``
+
+ """
+
+ args = {'id': vpc.id}
+
+ self._async_request(command='deleteVPC',
+ params=args,
+ method='GET')
+ return True
+
def ex_list_projects(self):
"""
List the available projects
@@ -1431,7 +1685,8 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
ips.append(CloudStackAddress(ip['id'],
ip['ipaddress'],
self,
- ip['associatednetworkid']))
+ ip.get('associatednetworkid', [])))
+
return ips
def ex_allocate_public_ip(self, location=None):
@@ -1562,6 +1817,99 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
method='GET')
return res['success']
+ def ex_list_egress_firewall_rules(self):
+ """
+ Lists all agress Firewall Rules
+
+ :rtype: ``list`` of :class:`CloudStackEgressFirewallRule`
+ """
+ rules = []
+ result = self._sync_request(command='listEgressFirewallRules',
+ method='GET')
+ for rule in result['firewallrule']:
+ rules.append(CloudStackEgressFirewallRule(rule['id'],
+ rule['networkid'],
+ rule['cidrlist'],
+ rule['protocol'],
+ rule.get('icmpcode'),
+ rule.get('icmptype'),
+ rule.get('startport'),
+ rule.get('endport')))
+
+ return rules
+
+ def ex_create_egress_firewall_rule(self, network_id, cidr_list, protocol,
+ icmp_code=None, icmp_type=None,
+ start_port=None, end_port=None):
+ """
+ Creates a Firewalle Rule
+
+ :param network_id: the id network network for the egress firwall
+ services
+ :type network_id: ``str``
+
+ :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:`CloudStackEgressFirewallRule`
+ """
+ args = {
+ 'networkid': network_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='createEgressFirewallRule',
+ params=args,
+ method='GET')
+
+ rule = CloudStackEgressFirewallRule(result['firewallrule']['id'],
+ network_id,
+ cidr_list,
+ protocol,
+ icmp_code,
+ icmp_type,
+ start_port,
+ end_port)
+ return rule
+
+ def ex_delete_egress_firewall_rule(self, firewall_rule):
+ """
+ Remove a Firewall rule.
+
+ :param egress_firewall_rule: Firewall rule which should be used
+ :type egress_firewall_rule: :class:`CloudStackEgressFirewallRule`
+
+ :rtype: ``bool``
+ """
+ res = self._async_request(command='deleteEgressFirewallRule',
+ 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/d608085e/libcloud/test/compute/fixtures/cloudstack/createEgressFirewallRule_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/createEgressFirewallRule_default.json b/libcloud/test/compute/fixtures/cloudstack/createEgressFirewallRule_default.json
new file mode 100644
index 0000000..104b80a
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/createEgressFirewallRule_default.json
@@ -0,0 +1 @@
+{ "createegressfirewallruleresponse" : {"jobid":1149341,"id":172465} }
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d608085e/libcloud/test/compute/fixtures/cloudstack/createVPC_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/createVPC_default.json b/libcloud/test/compute/fixtures/cloudstack/createVPC_default.json
new file mode 100644
index 0000000..e1c2bed
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/createVPC_default.json
@@ -0,0 +1 @@
+{ "createvpcresponse" : {"id":"c78499e1-b3a2-4a2a-9759-c2bcb1b79cd4","jobid":"f618f672-c714-4031-8c79-bb1300a2163c"} }
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d608085e/libcloud/test/compute/fixtures/cloudstack/deleteEgressFirewallRule_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/deleteEgressFirewallRule_default.json b/libcloud/test/compute/fixtures/cloudstack/deleteEgressFirewallRule_default.json
new file mode 100644
index 0000000..3283e55
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/deleteEgressFirewallRule_default.json
@@ -0,0 +1 @@
+{ "deleteegressfirewallruleresponse" : {"jobid":1149342} }
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d608085e/libcloud/test/compute/fixtures/cloudstack/deleteVPC_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/deleteVPC_default.json b/libcloud/test/compute/fixtures/cloudstack/deleteVPC_default.json
new file mode 100644
index 0000000..300c113
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/deleteVPC_default.json
@@ -0,0 +1 @@
+{ "deletevpcresponse" : {"jobid":"deleteVPC"} }
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d608085e/libcloud/test/compute/fixtures/cloudstack/listEgressFirewallRules_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/listEgressFirewallRules_default.json b/libcloud/test/compute/fixtures/cloudstack/listEgressFirewallRules_default.json
new file mode 100644
index 0000000..d51bba7
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/listEgressFirewallRules_default.json
@@ -0,0 +1 @@
+{ "listegressfirewallrulesresponse" : { "count":1 ,"firewallrule" : [ {"id":"7d4e2924-49b6-4a5a-9a98-69f2f0f73c69","protocol":"tcp","startport":"80","endport":"80","networkid":"874be2ca-20a7-4360-80e9-7356c0018c0b","state":"Active","cidrlist":"192.168.0.0/16","tags":[]} ] } }
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d608085e/libcloud/test/compute/fixtures/cloudstack/listVPCOfferings_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/listVPCOfferings_default.json b/libcloud/test/compute/fixtures/cloudstack/listVPCOfferings_default.json
new file mode 100644
index 0000000..368a143
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/listVPCOfferings_default.json
@@ -0,0 +1 @@
+{ "listvpcofferingsresponse" : { "count":1 ,"vpcoffering" : [ {"id":"cd7dbd68-4333-4507-b80d-9840cab32841","name":"Default VPC offering with Netscaler","displaytext":"Default VPC offering with Netscaler","isdefault":false,"state":"Enabled","service":[{"name":"Vpn","provider":[{"name":"VpcVirtualRouter"}]},{"name":"NetworkACL","provider":[{"name":"VpcVirtualRouter"}]},{"name":"PortForwarding","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Dns","provider":[{"name":"VpcVirtualRouter"}]},{"name":"UserData","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Lb","provider":[{"name":"Netscaler"},{"name":"InternalLbVm"}]},{"name":"SourceNat","provider":[{"name":"VpcVirtualRouter"}]},{"name":"StaticNat","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Dhcp","provider":[{"name":"VpcVirtualRouter"}]}]} ] } }
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d608085e/libcloud/test/compute/fixtures/cloudstack/listVPCs_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/listVPCs_default.json b/libcloud/test/compute/fixtures/cloudstack/listVPCs_default.json
new file mode 100644
index 0000000..d349e18
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/listVPCs_default.json
@@ -0,0 +1 @@
+{ "listvpcsresponse" : { "count":1 ,"vpc" : [ {"id":"6adc8ad1-a8a1-4a4e-af75-2c3643297041","name":"test","displaytext":"test","state":"Enabled","zoneid":"2","zonename":"TEST-DC-1","service":[{"name":"Vpn","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Connectivity","provider":[{"name":"NiciraNvp"}]},{"name":"NetworkACL","provider":[{"name":"VpcVirtualRouter"}]},{"name":"PortForwarding","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Dns","provider":[{"name":"VpcVirtualRouter"}]},{"name":"UserData","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Lb","provider":[{"name":"VpcVirtualRouter"},{"name":"InternalLbVm"}]},{"name":"SourceNat","provider":[{"name":"VpcVirtualRouter"}]},{"name":"StaticNat","provider":[{"name":"VpcVirtualRouter"}]},{"name":"Dhcp","provider":[{"name":"VpcVirtualRouter"}]}],"cidr":"10.1.1.0/16","vpcofferingid":"ef58092b-8547-4d41-8dc3-cdaa471e12b1","account":"test_admin","domainid":"ee90435a-bba8-427f-90f9-02f9bf9e03aa","domain":"test","network":[],"rest
artrequired":false,"networkdomain":"test.local","tags":[]} ] } }
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d608085e/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVPC.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVPC.json b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVPC.json
new file mode 100644
index 0000000..b4a3041
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_deleteVPC.json
@@ -0,0 +1 @@
+{ "queryasyncjobresultresponse" : {"accountid":"5d7d4c5e-7e0b-4ac2-8550-713180d8a342","userid":"5fb4b286-ac58-44a7-acae-d47dbbac78d1","cmd":"org.apache.cloudstack.api.command.user.vpc.DeleteVPCCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"success":true},"created":"2014-09-25T00:11:31+0200","jobid":"cfa5c4f5-d312-4b18-9197-385ef169726e"} }
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/libcloud/blob/d608085e/libcloud/test/compute/test_cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudstack.py b/libcloud/test/compute/test_cloudstack.py
index 00ba306..cd72b2b 100644
--- a/libcloud/test/compute/test_cloudstack.py
+++ b/libcloud/test/compute/test_cloudstack.py
@@ -295,6 +295,58 @@ class CloudStackCommonTestCase(TestCaseMixin):
result = self.driver.ex_delete_network(network=network)
self.assertTrue(result)
+ def test_ex_list_vpc_offerings(self):
+ _, fixture = CloudStackMockHttp()._load_fixture(
+ 'listVPCOfferings_default.json')
+ fixture_vpcoffers = \
+ fixture['listvpcofferingsresponse']['vpcoffering']
+
+ vpcoffers = self.driver.ex_list_vpc_offerings()
+
+ for i, vpcoffer in enumerate(vpcoffers):
+ self.assertEqual(vpcoffer.id, fixture_vpcoffers[i]['id'])
+ self.assertEqual(vpcoffer.name,
+ fixture_vpcoffers[i]['name'])
+ self.assertEqual(vpcoffer.display_text,
+ fixture_vpcoffers[i]['displaytext'])
+
+ def test_ex_list_vpcs(self):
+ _, fixture = CloudStackMockHttp()._load_fixture(
+ 'listVPCs_default.json')
+ fixture_vpcs = fixture['listvpcsresponse']['vpc']
+
+ vpcs = self.driver.ex_list_vpcs()
+
+ for i, vpc in enumerate(vpcs):
+ self.assertEqual(vpc.id, fixture_vpcs[i]['id'])
+ self.assertEqual(vpc.display_text, fixture_vpcs[i]['displaytext'])
+ self.assertEqual(vpc.name, fixture_vpcs[i]['name'])
+ self.assertEqual(vpc.vpc_offering_id,
+ fixture_vpcs[i]['vpcofferingid'])
+ self.assertEqual(vpc.zone_id, fixture_vpcs[i]['zoneid'])
+
+ def test_ex_create_vpc(self):
+ _, fixture = CloudStackMockHttp()._load_fixture(
+ 'createVPC_default.json')
+
+ fixture_vpc = fixture['createvpcresponse']
+
+ vpcoffer = self.driver.ex_list_vpc_offerings()[0]
+ vpc = self.driver.ex_create_vpc(cidr='10.1.1.0/16',
+ display_text='cloud.local',
+ name='cloud.local',
+ vpc_offering=vpcoffer,
+ zoneid="2")
+
+ self.assertEqual(vpc.id, fixture_vpc['id'])
+
+ def test_ex_delete_vpc(self):
+
+ vpc = self.driver.ex_list_vpcs()[0]
+
+ result = self.driver.ex_delete_vpc(vpc=vpc)
+ self.assertTrue(result)
+
def test_ex_list_projects(self):
_, fixture = CloudStackMockHttp()._load_fixture(
'listProjects_default.json')
@@ -634,6 +686,44 @@ class CloudStackCommonTestCase(TestCaseMixin):
self.assertIsNone(rule.start_port)
self.assertIsNone(rule.end_port)
+ def test_ex_list_egress_firewall_rules(self):
+ rules = self.driver.ex_list_egress_firewall_rules()
+ self.assertEqual(len(rules), 1)
+ rule = rules[0]
+ self.assertEqual(rule.network_id, '874be2ca-20a7-4360-80e9-7356c0018c0b')
+ self.assertEqual(rule.cidr_list, '192.168.0.0/16')
+ self.assertEqual(rule.protocol, 'tcp')
+ self.assertIsNone(rule.icmp_code)
+ self.assertIsNone(rule.icmp_type)
+ self.assertEqual(rule.start_port, '80')
+ self.assertEqual(rule.end_port, '80')
+
+ def test_ex_delete_egress_firewall_rule(self):
+ rules = self.driver.ex_list_egress_firewall_rules()
+ res = self.driver.ex_delete_egress_firewall_rule(rules[0])
+ self.assertTrue(res)
+
+ def test_ex_create_egress_firewall_rule(self):
+ network_id = '874be2ca-20a7-4360-80e9-7356c0018c0b'
+ cidr_list = '192.168.0.0/16'
+ protocol = 'TCP'
+ start_port = 33
+ end_port = 34
+ rule = self.driver.ex_create_egress_firewall_rule(
+ network_id,
+ cidr_list,
+ protocol,
+ start_port=start_port,
+ end_port=end_port)
+
+ self.assertEqual(rule.network_id, network_id)
+ self.assertEqual(rule.cidr_list, cidr_list)
+ 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_list_port_forwarding_rules(self):
rules = self.driver.ex_list_port_forwarding_rules()
self.assertEqual(len(rules), 1)