You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ts...@apache.org on 2013/10/02 18:42:04 UTC
[34/50] [abbrv] git commit: updated refs/heads/marvin-refactor to
bbaf354
marvin_refactor: New firewall rule test
Firewall entities were mixed up with multiple __init__'s. This is now
resolved by ensuring only one creator exists per enitity. Only entities
affected by this are template, sshkeypair and firewall.
Introduced a new utils module for utitlity functions. Deprecate the old
utils in legacy package.
Signed-off-by: Prasanna Santhanam <ts...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/9afab985
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/9afab985
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/9afab985
Branch: refs/heads/marvin-refactor
Commit: 9afab985b8a53fa043eb35fa9876cff7561434be
Parents: 09621e5
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Tue Sep 17 16:59:36 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:55 2013 +0530
----------------------------------------------------------------------
pom.xml | 1 +
.../marvin/marvin/factory/data/firewallrule.py | 6 +-
tools/marvin/marvin/factory/data/vm.py | 6 +-
tools/marvin/marvin/generate/entity.py | 42 +++++++++-
tools/marvin/marvin/generate/linguist.py | 2 +
tools/marvin/marvin/test/test_factories.py | 57 +++++++++++++-
tools/marvin/marvin/util.py | 80 ++++++++++++++++++++
7 files changed, 183 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9afab985/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 75eae87..2880a35 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,6 +86,7 @@
<cs.target.dir>target</cs.target.dir>
<cs.daemon.version>1.0.10</cs.daemon.version>
<cs.jna.version>4.0.0</cs.jna.version>
+ <cs.maven.ant.version>1.7</cs.maven.ant.version>
</properties>
<distributionManagement>
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9afab985/tools/marvin/marvin/factory/data/firewallrule.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/firewallrule.py b/tools/marvin/marvin/factory/data/firewallrule.py
index da6284a..692450b 100644
--- a/tools/marvin/marvin/factory/data/firewallrule.py
+++ b/tools/marvin/marvin/factory/data/firewallrule.py
@@ -15,15 +15,15 @@
# specific language governing permissions and limitations
# under the License.
-from marvin.factory.firewallrule import FirewallRuleFactory
+from marvin.factory.firewall import FirewallFactory
-class SshFirewallRuleFactory(FirewallRuleFactory):
+class SshFirewallRuleFactory(FirewallFactory):
protocol = 'tcp'
startport = 22
endport = 22
cidrlist = '0.0.0.0/0'
-class HttpFirewallRuleFactory(FirewallRuleFactory):
+class HttpFirewallRuleFactory(FirewallFactory):
protocol = 'tcp'
startport = 80
endport = 80
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9afab985/tools/marvin/marvin/factory/data/vm.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/vm.py b/tools/marvin/marvin/factory/data/vm.py
index 0d7aac0..a09abe7 100644
--- a/tools/marvin/marvin/factory/data/vm.py
+++ b/tools/marvin/marvin/factory/data/vm.py
@@ -17,16 +17,16 @@
from marvin.factory.virtualmachine import VirtualMachineFactory
-
class VirtualMachineIsolatedNetwork(VirtualMachineFactory):
"""
- Create a virtualmachine in an isolated network typically in an advanced zone
+ Creates a virtualmachine in an isolated network typically in an advanced zone inside a user account
- Uses a serviceoffering of tinyInstance
+ Uses a serviceoffering of tinyInstance of the shared storage type
Uses a builtin template available
Deploys in the first zone available
"""
+ apiclient = None
serviceofferingid = None
templateid = None
zoneid = None
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9afab985/tools/marvin/marvin/generate/entity.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/entity.py b/tools/marvin/marvin/generate/entity.py
index b9f825b..2d7b627 100644
--- a/tools/marvin/marvin/generate/entity.py
+++ b/tools/marvin/marvin/generate/entity.py
@@ -57,13 +57,48 @@ class Entity(object):
update.body.append(self.tabspace + 'return self')
return update
+ def creators(self, apis):
+ _creator_list = ['create', 'register', 'deploy']
+ for c in _creator_list:
+ if filter(lambda a: a['apimodule'].startswith(c), apis):
+ return c
+ else:
+ return None
+
+ def special_creators(self, entity):
+ """Entities that do not conform to the regular creator rules
+ """
+ entity = entity.lower()
+ if entity == 'template':
+ return 'registerTemplate'
+ elif entity == 'iso':
+ return 'registerIso'
+ elif entity == 'firewall':
+ return 'createFirewallRule'
+ elif entity == 'ipaddress':
+ return 'associateIpAddress'
+ else:
+ return None
+
+ def find_creator(self, entity, actions):
+ c = self.special_creators(entity)
+ if c:
+ return c
+ c = self.creators(actions.values())
+ if c:
+ return c
+ else:
+ return None
+
def generate_entity(self, entity, actions):
self.imports.append('from cloudstackentity import CloudStackEntity')
self.name = entity
self.classname = 'class %s(CloudStackEntity):' % entity
+ self.creator = self.find_creator(entity, actions)
for action, details in actions.iteritems():
self.imports.append('from marvin.cloudstackAPI import %s' % details['apimodule'])
m = Method(action)
+ m.creator = self.creator and details['apimodule'].startswith(self.creator)
self.methods.append(m)
#TODO: doc to explain what possible args go into **kwargs
m.docstring = 'Placeholder for docstring\n' + 'optional arguments (**kwargs): [%s]"""' % ', '.join(
@@ -96,7 +131,7 @@ class Entity(object):
m.signature = 'def __init__(self, apiclient=None, %s, factory=None, **kwargs):' % (
', '.join(map(lambda arg: arg + '=None', list(set(details['args'])))))
else:
- m.signature = 'def %s(cls, apiclient, factory=None, **kwargs):' % action
+ m.signature = 'def __init__(self, apiclient=None, factory=None, **kwargs):'
m.body.append(self.tabspace + 'self.__update__(kwargs)')
m.body.append(self.tabspace + 'if not apiclient:')
@@ -126,6 +161,7 @@ class Method(object):
self.action = action
self.docstring = None
self.signature = None
+ self.creator = False
self.body = []
def is_creator(self):
@@ -135,9 +171,7 @@ class Method(object):
@param action: action verb
@return: True if creator False otherwise
"""
- if self.action.startswith('create') \
- or self.action.startswith('register') \
- or self.action.startswith('deploy'):
+ if self.creator:
return True
return False
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9afab985/tools/marvin/marvin/generate/linguist.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/linguist.py b/tools/marvin/marvin/generate/linguist.py
index fd2729e..ec1f693 100644
--- a/tools/marvin/marvin/generate/linguist.py
+++ b/tools/marvin/marvin/generate/linguist.py
@@ -87,6 +87,8 @@ def entity_adjust(entity):
#Cloudstack returns Register entity for registerUserKeys
elif entity == 'Register':
return 'UserKeys'
+ elif entity == 'FirewallRule':
+ return 'Firewall'
#Cloudstack maintains Template/ISO/Volume as single Image type
#elif entity in ['Template', 'Volume']:
# return 'Image'
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9afab985/tools/marvin/marvin/test/test_factories.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/test/test_factories.py b/tools/marvin/marvin/test/test_factories.py
index c2c823c..89d67fb 100644
--- a/tools/marvin/marvin/test/test_factories.py
+++ b/tools/marvin/marvin/test/test_factories.py
@@ -28,9 +28,12 @@ from marvin.factory.data.template import *
from marvin.factory.data.user import *
from marvin.factory.data.networkoffering import *
from marvin.factory.data.network import *
+from marvin.factory.data.vm import *
+from marvin.factory.data.firewallrule import *
from marvin.factory.virtualmachine import *
+from marvin.entity.firewall import Firewall
from marvin.entity.serviceoffering import ServiceOffering
from marvin.entity.networkoffering import NetworkOffering
from marvin.entity.zone import Zone
@@ -40,6 +43,8 @@ from marvin.entity.user import User
from marvin.entity.network import Network
from marvin.entity.ipaddress import IpAddress
+from marvin.util import *
+
class BuildVsCreateStrategyTest(unittest.TestCase):
def setUp(self):
@@ -228,4 +233,54 @@ class IpAddressFactoryTest(unittest.TestCase):
firstip = all_ips[0]
networks = Network.list(apiclient=self.apiClient,
account = accnt.name, domainid = accnt.domainid)
- firstip.associate(apiclient=self.apiClient, networkid = networks[0].id)
\ No newline at end of file
+ firstip.associate(apiclient=self.apiClient, networkid = networks[0].id)
+
+
+class FirewallRuleFactoryTest(unittest.TestCase):
+ def setUp(self):
+ self.apiClient = cloudstackTestClient(mgtSvr='localhost',
+ logging=logging.getLogger('factory.cloudstack')).getApiClient()
+
+ def tearDown(self):
+ self.account.delete(apiclient=self.apiClient)
+
+ @attr(tags='firewall')
+ def test_firewallRuleFactoryTest(self):
+ self.account = UserAccountFactory(apiclient=self.apiClient)
+ domainid = get_domain(self.apiClient).id
+ self.account |should| be_instance_of(Account)
+ vm = VirtualMachineFactory(
+ apiclient=self.apiClient,
+ account=self.account.name,
+ domainid=domainid,
+ templateid=get_template(self.apiClient).id,
+ serviceofferingid=get_service_offering(self.apiClient).id,
+ zoneid=get_zone(self.apiClient).id
+ )
+ vm |should| be_instance_of(VirtualMachine)
+ vm.state |should| equal_to('Running')
+ vm.nic |should_not| equal_to(None)
+ vm.nic |should| be_instance_of(list)
+
+ ipaddresses = IpAddress.listPublic(
+ apiclient=self.apiClient,
+ networkid=vm.nic[0].networkid
+ )
+ ipaddresses |should_not| equal_to(None)
+ ipaddresses |should| be_instance_of(list)
+
+ ipaddress = IpAddress(
+ apiclient=self.apiClient,
+ account=self.account.name,
+ domainid=domainid,
+ zoneid=get_zone(self.apiClient).id
+ )
+ ipaddress |should_not| be(None)
+ ipaddress |should| be_instance_of(IpAddress)
+
+ fwrule = SshFirewallRuleFactory(
+ apiclient=self.apiClient,
+ ipaddressid=ipaddress.ipaddress.id
+ )
+ fwrule |should_not| be(None)
+ fwrule |should| be_instance_of(Firewall)
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9afab985/tools/marvin/marvin/util.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/util.py b/tools/marvin/marvin/util.py
new file mode 100644
index 0000000..9a97c9d
--- /dev/null
+++ b/tools/marvin/marvin/util.py
@@ -0,0 +1,80 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from marvin.entity.template import Template
+from marvin.entity.zone import Zone
+from marvin.entity.serviceoffering import ServiceOffering
+from marvin.entity.domain import Domain
+from marvin.entity.guestos import GuestOS
+
+def get_domain(apiclient):
+ "Returns a default `ROOT` domain"
+
+ domains = Domain.list(
+ apiclient=apiclient,
+ )
+ if isinstance(domains, list) and len(domains) > 0:
+ return domains[0]
+ else:
+ raise Exception("Failed to find any domains")
+
+def get_zone(apiclient):
+ "Returns the default enabled zone"
+
+ zones = Zone.list(
+ apiclient=apiclient,
+ )
+ if isinstance(zones, list) and len(zones) > 0:
+ for zone in zones:
+ if zone.allocationstate == 'Enabled':
+ return zone
+ else:
+ raise Exception("No active zones found for deployment")
+ else:
+ raise Exception("Failed to find specified zone.")
+
+def get_service_offering(apiclient, storagetype='shared', scope=None):
+ """Returns the service offering that is available in the zone
+
+ @param: `storagetype` is assumed to be `shared storage`
+ @param: `scope` zone-wide or cluster-wide. defaults to cluster
+ """
+ serviceofferings = ServiceOffering.list(
+ apiclient=apiclient,
+ name='Small Instance'
+ )
+ if isinstance(serviceofferings, list) and len(serviceofferings) > 0:
+ for service in serviceofferings:
+ if service.storagetype == storagetype:
+ return service
+ raise Exception("No service offering for storagetype %s available")
+
+def get_template(apiclient, description=None):
+ "Returns a featured template with a specific description"
+ templates = Template.list(
+ apiclient=apiclient,
+ templatefilter='featured'
+ )
+
+ if isinstance(templates, list) and len(templates) > 0:
+ for template in templates:
+ if template.isready:
+ return template
+ else:
+ raise Exception("None of the templates are ready in your deployment")
+ else:
+ raise Exception("Failed to find ready and featured template of : %s" % description)