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)