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:41:31 UTC

[01/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Updated Branches:
  refs/heads/marvin-refactor [created] bbaf35468


marvin_refactor: multiple fixes to entity gen.

1. extend the namespace using execfile for getting cmdlets. Don't expect
existing marvin installations
2. additional entity adjustments for registerUserkeys and template
related APIs
3. optional **kwargs are explained in docstring

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/291a35dd
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/291a35dd
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/291a35dd

Branch: refs/heads/marvin-refactor
Commit: 291a35dd762a6ae26fafac082d8c47f6b535dc0c
Parents: da1421d
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Tue Sep 3 16:53:08 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:03 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/cs_entity_generator.py | 127 ++++++++++++++----------
 1 file changed, 72 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/291a35dd/tools/marvin/marvin/cs_entity_generator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cs_entity_generator.py b/tools/marvin/marvin/cs_entity_generator.py
index d13a409..b2cf3c5 100644
--- a/tools/marvin/marvin/cs_entity_generator.py
+++ b/tools/marvin/marvin/cs_entity_generator.py
@@ -16,7 +16,11 @@
 # under the License.
 
 import os
-import inflect
+try:
+    import inflect
+except ImportError:
+    raise Exception("inflect installation not found. use pip install inflect to continue")
+
 grammar = ['create', 'list', 'delete', 'update', 'ldap', 'login', 'logout',
            'enable', 'activate', 'disable', 'add', 'remove',
            'attach', 'detach', 'associate', 'generate', 'assign',
@@ -46,15 +50,15 @@ LICENSE = """# Licensed to the Apache Software Foundation (ASF) under one
 # under the License.
 """
 
-def get_api_cmds(path=None):
+def get_api_cmds():
     """ Returns the API cmdlet instances
-    @param path: path where the api modules are found. defaults to pythonpath
+
     @return: instances of all the API commands exposed by CloudStack
     """
-    if path:
-        api_classes = __import__('cloudstackAPI', fromlist=['*'], level=2)
-    else:
-        api_classes = __import__('marvin.cloudstackAPI')
+    namespace = {}
+    execfile('cloudstackAPI/__init__.py', namespace)
+    api_classes = __import__('cloudstackAPI', globals().update(namespace), fromlist=['*'], level=-1)
+
 
     cmdlist = map(
         lambda f: getattr(api_classes, f),
@@ -77,7 +81,6 @@ def get_api_cmds(path=None):
     cmdlets = map(lambda t: t(), clslist)
     return cmdlets
 
-
 def singularize(word, num=0):
     """Use the inflect engine to make singular nouns of the entities
     @return: singular of `word`
@@ -85,7 +88,6 @@ def singularize(word, num=0):
     inflector = inflect.engine()
     return inflector.singular_noun(word)
 
-
 def transform_api(api):
     """Brute-force transform for entities that don't match other transform rules
     """
@@ -110,7 +112,6 @@ def verb_adjust(api, entity):
     else:
         return api
 
-
 def entity_adjust(entity):
     """
     Some entities are managed within CloudStack where they don't bear any resemblance to the API.
@@ -143,14 +144,17 @@ def entity_adjust(entity):
         return 'VpnGateway'
     elif entity == 'Site2SiteCustomerGateway':
         return 'VpnCustomerGateway'
+    #Cloudstack returns Register entity for registerUserKeys
+    elif entity == 'Register':
+        return 'UserKeys'
     #Cloudstack maintains Template/ISO/Volume as single Image type
+    #elif entity in ['Template', 'Volume']:
+    #    return 'Image'
+    #extractImage returns an Extract response but is a property of Image
     elif entity == 'Extract':
-        return 'Image'
-    elif entity == 'Template':
-        return 'Image'
+        return 'Template'
     return entity
 
-
 def prepositon_transformer(preposition=None):
     """Returns a transformer for the entity if it has a doXPrepositionY style API
 
@@ -164,12 +168,10 @@ def prepositon_transformer(preposition=None):
         return api, None
     return transform_api_with_preposition
 
-
 def skip_list():
     """APIs that we will not auto-generate
     """
-    return []
-
+    return ['cleanVMReservationsCmd']
 
 def get_transformers():
     """ List of transform rules as lambdas
@@ -182,7 +184,6 @@ def get_transformers():
                     transform_api]
     return transformers
 
-
 def get_verb_and_entity(cmd):
     """Break down the API cmd instance in to `verb` and `Entity`
     @return: verb, Entity tuple
@@ -211,27 +212,25 @@ def get_verb_and_entity(cmd):
                 entity = singularize(entity) if singularize(entity) else entity
             entity = entity_adjust(entity)
             verb = verb_adjust(api, entity)
-        print "%s => (verb, entity) = (%s, %s)" % (api, verb, entity)
+        #print "%s => (verb, entity) = (%s, %s)" % (api, verb, entity)
         return verb, entity
     else:
         print "No matching verb, entity breakdown for api %s" % api
 
-
-def get_actionable_entities(path=None):
+def get_actionable_entities():
     """
     Inspect all entities and return a map of the Entity against the actions
     along with the required arguments to satisfy the action
-    @param path: path where the api modules are found. defaults to pythonpath
+
     @return: Dictionary of Entity { "verb" : [required] }
     """
-    cmdlets = sorted(filter(lambda api: api.__class__.__name__ not in skip_list(), get_api_cmds(path)),
+    cmdlets = sorted(filter(lambda api: api.__class__.__name__ not in skip_list(), get_api_cmds()),
         key=lambda k: get_verb_and_entity(k)[1])
 
-
     entities = {}
     for cmd in cmdlets:
         requireds = getattr(cmd, 'required')
-        optionals = filter(lambda x: '__' not in x and 'required' not in x and 'isAsync' not in x, dir(cmd))
+        optionals = filter(lambda x: '__' not in x and x not in ['required', 'isAsync', 'entity'], dir(cmd))
         api = cmd.__class__.__name__
         if api in skip_list():
             continue
@@ -240,6 +239,7 @@ def get_actionable_entities(path=None):
             entities[entity] = {}
         entities[entity][verb] = {}
         entities[entity][verb]['args'] = requireds
+        entities[entity][verb]['optionals'] = optionals
         entities[entity][verb]['apimodule'] = cmd.__class__.__module__.split('.')[-1]
         entities[entity][verb]['apicmd'] = api
     print "Transformed %s APIs to %s entities successfully" % (len(cmdlets), len(entities)) \
@@ -251,6 +251,7 @@ def get_actionable_entities(path=None):
 def write_entity_classes(entities, module=None):
     """
     Writes the collected entity classes into `path`
+
     @param entities: dictionary of entities and the verbs acting on them
     @param module: top level module to the generated classes
     @return:
@@ -260,7 +261,7 @@ def write_entity_classes(entities, module=None):
     for entity, actions in entities.iteritems():
         body = []
         imports = []
-        imports.append('from %s.CloudStackEntity import CloudStackEntity' % module)
+        imports.append('from CloudStackEntity import CloudStackEntity')
         body.append('class %s(CloudStackEntity):' % entity)
         #TODO: Add docs for entity
         body.append('\n\n')
@@ -269,7 +270,8 @@ def write_entity_classes(entities, module=None):
         body.append('\n')
         for action, details in actions.iteritems():
             imports.append('from marvin.cloudstackAPI import %s' % details['apimodule'])
-            if action.startswith('create') or action.startswith('list') or action.startswith('deploy'):
+            if action.startswith('create') or action.startswith('list') or action.startswith(
+                'register') or action.startswith('deploy'):
                 body.append(tabspace + '@classmethod')
             if action not in ['create', 'deploy']:
                 no_id_args = filter(lambda arg: arg!= 'id', details['args'])
@@ -278,6 +280,10 @@ def write_entity_classes(entities, module=None):
                         action, ', '.join(list(set(no_id_args)))))
                 else:
                     body.append(tabspace + 'def %s(self, apiclient, **kwargs):' % (action))
+                # doc to explain what possible args go into **kwargs
+                body.append(tabspace * 2 + '"""Placeholder for docstring')
+                body.append(tabspace * 2 + 'optional arguments (**kwargs): [%s]"""' % ', '.join(details['optionals']))
+
                 body.append(tabspace * 2 + 'cmd = %(module)s.%(command)s()' % {"module": details["apimodule"],
                                                                                "command": details["apicmd"]})
                 if 'id' in details['args']:
@@ -286,7 +292,7 @@ def write_entity_classes(entities, module=None):
                     body.append(tabspace * 2 + 'cmd.%s = %s' % (arg, arg))
                 body.append(tabspace * 2 + '[setattr(cmd, key, value) for key,value in kwargs.iteritems()]')
                 body.append(tabspace * 2 + '%s = apiclient.%s(cmd)' % (entity.lower(), details['apimodule']))
-                if action in ['list']:
+                if action.startswith('list'):
                     body.append(
                         tabspace * 2 + 'return map(lambda e: %s(e.__dict__), %s) if %s and len(%s) > 0 else None' % (
                             entity, entity.lower(), entity.lower(), entity.lower()))
@@ -299,6 +305,10 @@ def write_entity_classes(entities, module=None):
                 else:
                     body.append(tabspace + 'def %s(cls, apiclient, factory=None, **kwargs):' % action)
                     #TODO: Add docs for actions
+                # doc to explain what possible args go into **kwargs
+                body.append(tabspace * 2 + '"""Placeholder for docstring')
+                body.append(tabspace * 2 + 'optional arguments (**kwargs): [%s]"""' % ', '.join(details['optionals']))
+
                 body.append(tabspace * 2 + 'cmd = %(module)s.%(command)s()' % {"module": details["apimodule"],
                                                                                "command": details["apicmd"]})
                 body.append(tabspace * 2 + 'if factory:')
@@ -319,18 +329,16 @@ def write_entity_classes(entities, module=None):
         code = imports + '\n\n' + body
 
         entitydict[entity] = code
-        write_entity_factory(entity, actions, 'factory2')
-        if module.find('.') > 0:
-            module_path = '/'.join(module.split('.'))[1:]
-        else:
-            module_path = '/' + module
-        if not os.path.exists(".%s" % module_path):
-            os.mkdir(".%s" % module_path)
-        with open(".%s/%s.py" % (module_path, entity), "w") as writer:
+        write_entity_factory(entity, actions, module='factory')
+        module_path = './' + '/'.join(module.split('.'))
+        if not os.path.exists("%s" % module_path):
+            os.makedirs("%s" % module_path)
+        with open("%s/__init__.py" % (module_path), "w") as writer:
+            writer.write(LICENSE)
+        with open("%s/%s.py" % (module_path, entity), "w") as writer:
             writer.write(LICENSE)
             writer.write(code)
 
-
 def write_entity_factory(entity, actions, module=None):
     """Data factories for each entity
     """
@@ -338,41 +346,50 @@ def write_entity_factory(entity, actions, module=None):
     tabspace = '    '
     code = ''
     factory_defaults = []
-    if 'create' in actions:
-        factory_defaults.extend(actions['create']['args'])
-    elif 'deploy' in actions:
-        factory_defaults.extend(actions['deploy']['args'])
-    elif 'associate' in actions:
-        factory_defaults.extend(actions['associate']['args'])
-    elif 'register' in actions:
-        factory_defaults.extend(actions['register']['args'])
-    else:
-        return
+    keys = actions.keys()
+    for key in keys:
+        if key.startswith('create'):
+            factory_defaults.extend(actions[key]['args'])
+        elif key.startswith('deploy'):
+            factory_defaults.extend(actions[key]['args'])
+        elif key.startswith('associate'):
+            factory_defaults.extend(actions[key]['args'])
+        elif key.startswith('register'):
+            factory_defaults.extend(actions[key]['args'])
+        else:
+            continue
+            #print '%s is not suitable for factory creation for entity %s' %(key, entity)
 
-    if not os.path.exists("./factory2"):
-            os.mkdir("./factory2")
+    factory_defaults = set(factory_defaults)
+    module_path = './' + '/'.join(module.split('.'))
+    if not os.path.exists(module_path):
+        os.makedirs(module_path)
 
-    if os.path.exists("./factory2/%sFactory.py" % entity):
+    if os.path.exists("%s/%sFactory.py" % (module_path, entity)):
         for arg in factory_defaults:
             code += tabspace + '%s = None\n' % arg
-        with open("./factory2/%sFactory.py" % entity, "r") as reader:
+        with open("%s/%sFactory.py" % (module_path, entity), "r") as reader:
             rcode = reader.read()
             if rcode.find(code) > 0:
                 return
-        with open("./factory2/%sFactory.py" % entity, "a") as writer:
+        with open("%s/%sFactory.py" % (module_path, entity), "a") as writer:
             writer.write(code)
     else:
         code += 'import factory\n'
         code += 'from marvin.base import %s\n' % entity
-        code += 'class %sFactory(factory.Factory):' % entity
+        code += 'from CloudStackBaseFactory import CloudStackBaseFactory'
+        code += '\n'
+        code += 'class %sFactory(CloudStackBaseFactory):' % entity
         code += '\n\n'
         code += tabspace + 'FACTORY_FOR = %s.%s\n\n' % (entity, entity)
         for arg in factory_defaults:
             code += tabspace + '%s = None\n' % arg
-        with open("./factory2/%sFactory.py" % entity, "w") as writer:
+        with open("%s/__init__.py" % (module_path), "w") as writer:
+            writer.write(LICENSE)
+        with open("%s/%sFactory.py" % (module_path, entity), "w") as writer:
             writer.write(LICENSE)
             writer.write(code)
 
 if __name__ == '__main__':
     entities = get_actionable_entities()
-    write_entity_classes(entities, 'base2')
+    write_entity_classes(entities, 'base')


[38/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: improve unittests for additional data factoreis

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/45afa942
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/45afa942
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/45afa942

Branch: refs/heads/marvin-refactor
Commit: 45afa9422a1f2b98753bd825e05076ed87603f1c
Parents: 9f759a8
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Mon Sep 30 09:54:22 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:01 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/test/test_factories.py | 229 ++++++++++++++++++++----
 1 file changed, 193 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/45afa942/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 6a09303..b3ea0ac 100644
--- a/tools/marvin/marvin/test/test_factories.py
+++ b/tools/marvin/marvin/test/test_factories.py
@@ -22,19 +22,22 @@ from should_dsl import should, should_not
 
 from marvin.cloudstackTestClient import cloudstackTestClient
 
-from marvin.factory.data.account import UserAccountFactory, AdminAccountFactory, DomainAdminFactory
+from marvin.factory.data.account import UserAccount, AdminAccount, DomainAdmin
 from marvin.factory.data.serviceoffering import *
+from marvin.factory.data.diskoffering import *
 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.data.firewallrule import SshFirewallRule
+from marvin.factory.data.vpc import DefaultVpc
 
 from marvin.factory.virtualmachine import *
 
 from marvin.entity.firewall import Firewall
 from marvin.entity.serviceoffering import ServiceOffering
+from marvin.entity.diskoffering import DiskOffering
 from marvin.entity.networkoffering import NetworkOffering
 from marvin.entity.zone import Zone
 from marvin.entity.account import Account
@@ -54,11 +57,11 @@ class BuildVsCreateStrategyTest(unittest.TestCase):
         pass
 
     def test_buildUserAccountFactory(self):
-        af = UserAccountFactory.build()
+        af = UserAccount.build()
         self.assert_(af is not None, msg="Account factory didn't initialize")
 
     def test_createAccountFactory(self):
-        af = UserAccountFactory(apiclient=self.apiClient)
+        af = UserAccount(apiclient=self.apiClient)
         self.assert_(isinstance(af, Account))
         self.assert_(af.id is not None, msg="Account creation failed")
         self.assert_(af.domain is not None, msg="Account belongs to no domain")
@@ -69,21 +72,21 @@ class AccountFactoryTest(unittest.TestCase):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def test_adminAccountFactory(self):
-        accnt = AdminAccountFactory(apiclient=self.apiClient)
+        accnt = AdminAccount(apiclient=self.apiClient)
         self.assert_(accnt is not None, msg="no account created by factory")
         self.assert_(accnt.name is not None)
 
     def test_userAccountFactoryCustomArgs(self):
-        accnt = UserAccountFactory(apiclient=self.apiClient, firstname='test', lastname='test')
+        accnt = UserAccount(apiclient=self.apiClient, firstname='test', lastname='test')
         a = accnt.list(apiclient=self.apiClient, account=accnt.name, domainid=accnt.domainid)
         self.assert_(accnt is not None, msg="no account created by factory")
         self.assert_(accnt.name is not None)
 
     def test_disableAccountPostFactoryGeneration(self):
-        domadmin = DomainAdminFactory(apiclient=self.apiClient)
+        domadmin = DomainAdmin(apiclient=self.apiClient)
         a = Account.list(apiclient=self.apiClient, id=domadmin.id)
         self.assert_(domadmin is not None, msg="no account was created")
-        domadmin.disable(self.apiClient, lock=True, account=domadmin.name, domainid=domadmin.domainid)
+        domadmin.disable(lock=True, account=domadmin.name, domainid=domadmin.domainid)
 
     def tearDown(self):
         pass
@@ -94,7 +97,7 @@ class ServiceOfferingFactoryTest(unittest.TestCase):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def test_serviceOfferingFactory(self):
-        soffering = SmallServiceOfferingFactory(apiclient=self.apiClient)
+        soffering = SmallServiceOffering(apiclient=self.apiClient)
         self.assert_(soffering is not None, msg="no service offering was created")
         self.assert_(soffering.name is not None, msg="error in service offering factory creation")
 
@@ -108,13 +111,13 @@ class NetworkOfferingFactoryTest(unittest.TestCase):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def test_defaultSourceNatOfferingFactory(self):
-        snatOffering = DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory(apiclient=self.apiClient)
+        snatOffering = DefaultIsolatedNetworkOfferingWithSourceNatService(apiclient=self.apiClient)
         self.assert_(snatOffering is not None, msg = "no network offering was created")
         self.assert_(snatOffering.name is not None, msg="error in network offering creation")
 
     @attr(tags='offering')
     def test_defaultSGOfferingEnable(self):
-        DefaultSharedNetworkOfferingWithSGServiceFactory(apiclient=self.apiClient)
+        DefaultSharedNetworkOfferingWithSGService(apiclient=self.apiClient)
 
     def tearDown(self):
         pass
@@ -137,7 +140,7 @@ class UserFactorySubFactoryTest(unittest.TestCase):
         caller is not to create the user before creating the account
         @return:
         """
-        uf = UserFactory(apiclient=self.apiClient)
+        uf = User(apiclient=self.apiClient)
         user = User.list(apiclient=self.apiClient, username=uf.username)
         self.assert_(uf.username == user[0].username, msg="Usernames don't match")
 
@@ -148,16 +151,13 @@ class NetworkFactoryTest(unittest.TestCase):
             logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def tearDown(self):
-        self.accnt.delete(apiclient=self.apiClient)
+        self.accnt.delete()
 
     @attr(tags='network')
     def test_isolatedGuestNetwork(self):
-        """Test to create a network within a guest account
-        @return:
-        """
-        self.accnt = UserAccountFactory(apiclient=self.apiClient)
+        self.accnt = UserAccount(apiclient=self.apiClient)
         zones = Zone.list(apiclient=self.apiClient)
-        network = GuestIsolatedNetworkFactory(
+        network = GuestIsolatedNetwork(
             apiclient=self.apiClient,
             zoneid=zones[0].id
             )
@@ -171,7 +171,7 @@ class NetworkOfferingFactoryWithMultiplePostHooksTest(unittest.TestCase):
 
     @attr(tags='post')
     def test_multiplePostHooksNetworkOffering(self):
-        sharedOffering = DefaultSharedNetworkOfferingFactory(apiclient=self.apiClient)
+        sharedOffering = DefaultSharedNetworkOffering(apiclient=self.apiClient)
         sharedOffering |should| be_instance_of(NetworkOffering)
         sharedOffering |should_not| equal_to(None)
         sharedOffering.state |should| equal_to('Enabled')
@@ -179,17 +179,17 @@ class NetworkOfferingFactoryWithMultiplePostHooksTest(unittest.TestCase):
                                                       %(sharedOffering.id, sharedOffering.name, sharedOffering.state))
 
 
-class VirtualMachineFactoryTest(unittest.TestCase):
+class VirtualMachineTest(unittest.TestCase):
     def setUp(self):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def tearDown(self):
-        self.vm.destroy(apiclient=self.apiClient)
+        self.vm.destroy()
 
     def test_virtualMachineDeploy(self):
-        accnt = UserAccountFactory(apiclient=self.apiClient)
-        service = SmallServiceOfferingFactory(apiclient=self.apiClient)
-        tf = DefaultBuiltInTemplateFactory.build()
+        accnt = UserAccount(apiclient=self.apiClient)
+        service = SmallServiceOffering(apiclient=self.apiClient)
+        tf = DefaultBuiltInTemplate.build()
         zones = Zone.list(apiclient=self.apiClient)
         template = Template.list(apiclient=self.apiClient,
                                  templatefilter="featured",
@@ -209,11 +209,11 @@ class IpAddressFactoryTest(unittest.TestCase):
             logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def tearDown(self):
-        self.vm.destroy(apiclient=self.apiClient)
+        self.vm.destroy()
 
     def test_associateIpAddressToNetwork(self):
         # user account where we run test
-        accnt = UserAccountFactory(apiclient=self.apiClient)
+        accnt = UserAccount(apiclient=self.apiClient)
         self.assert_(isinstance(accnt, Account))
 
         # get required arguments - templates, service offerings, zone
@@ -240,11 +240,11 @@ class FirewallRuleFactoryTest(unittest.TestCase):
             logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def tearDown(self):
-        self.account.delete(apiclient=self.apiClient)
+        self.account.delete()
 
     @attr(tags='firewall')
     def test_firewallRuleFactoryTest(self):
-        self.account = UserAccountFactory(apiclient=self.apiClient)
+        self.account = UserAccount(apiclient=self.apiClient)
         domainid = get_domain(self.apiClient).id
         self.account |should| be_instance_of(Account)
         vm = VirtualMachineFactory(
@@ -260,13 +260,6 @@ class FirewallRuleFactoryTest(unittest.TestCase):
         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,
@@ -276,9 +269,173 @@ class FirewallRuleFactoryTest(unittest.TestCase):
         ipaddress |should_not| be(None)
         ipaddress |should| be_instance_of(IpAddress)
 
-        fwrule = SshFirewallRuleFactory(
+        fwrule = SshFirewallRule(
             apiclient=self.apiClient,
             ipaddressid=ipaddress.id
         )
         fwrule |should_not| be(None)
         fwrule |should| be_instance_of(Firewall)
+
+
+@attr(tags='disk')
+class DiskOfferingFactoryTest(unittest.TestCase):
+
+    def setUp(self):
+        self.apiClient = cloudstackTestClient(mgtSvr='localhost',
+            logging=logging.getLogger('factory.cloudstack')).getApiClient()
+
+    def test_createSharedDiskOffering(self):
+        shared_disk_offering = SharedDiskOffering(apiclient=self.apiClient)
+        shared_disk_offering |should_not| be(None)
+        shared_disk_offering.name |should_not| equal_to(None)
+        shared_disk_offering.delete()
+
+    def test_createLocalDiskOffering(self):
+        local_disk_offering = LocalDiskOffering(apiclient=self.apiClient)
+        local_disk_offering | should_not | be(None)
+        local_disk_offering.name | should_not | equal_to(None)
+        local_disk_offering.delete()
+
+    def test_listDeletedDiskOfferings(self):
+        local_disk_offering = LocalDiskOffering(apiclient=self.apiClient)
+        local_disk_offering | should_not | be(None)
+        local_disk_offering.name | should_not | equal_to(None)
+        local_disk_offering.delete()
+
+        listed_offering = DiskOffering.list(apiclient=self.apiClient, name=local_disk_offering.name)
+        listed_offering | should | be(None)
+
+
+@attr(tags='gc')
+class DeleteAllNonAdminAccounts(unittest.TestCase):
+    def setUp(self):
+        self.apiClient = cloudstackTestClient(mgtSvr='localhost',
+            logging=logging.getLogger('factory.cloudstack')).getApiClient()
+
+    def test_deleteAllNonAdminAccounts(self):
+        accounts = Account.list(apiclient=self.apiClient, listall=True)
+        for account in accounts:
+            if account.accounttype == 0 or account.accounttype == 2 or account.accounttype == 1:
+                if account.name == 'admin':
+                    continue
+                account.delete(apiclient=self.apiClient)
+
+
+@attr(tags='post')
+class StaticNatPostVirtualMachineDeployHook(unittest.TestCase):
+    def setUp(self):
+        self.apiClient = cloudstackTestClient(mgtSvr='localhost',
+            logging=logging.getLogger('factory.cloudstack')).getApiClient()
+
+    def test_staticNatPostVmCreation(self):
+        self.account = UserAccount(apiclient=self.apiClient)
+        domainid = get_domain(self.apiClient).id
+        self.account |should| be_instance_of(Account)
+        vm = VirtualMachineWithStaticNat(
+            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)
+
+    def tearDown(self):
+        self.account.delete()
+
+class VpcCreationTest(unittest.TestCase):
+
+    def setUp(self):
+        self.apiClient = cloudstackTestClient(mgtSvr='localhost',
+            logging=logging.getLogger('factory.cloudstack')).getApiClient()
+
+    def test_vpcCreation(self):
+        self.account = UserAccount(apiclient=self.apiClient)
+        self.vpc = DefaultVpc(
+            apiclient=self.apiClient,
+            account=self.account.name,
+            domainid=get_domain(apiclient=self.apiClient).id,
+            zoneid=get_zone(apiclient=self.apiClient).id
+        )
+        self.vpc |should_not| be(None)
+        ntwk = DefaultVpcNetwork(
+            apiclient=self.apiClient,
+            account=self.account.name,
+            domainid=get_domain(apiclient=self.apiClient).id,
+            vpcid=self.vpc.id,
+            zoneid=get_zone(apiclient=self.apiClient).id
+        )
+        ntwk | should_not | be(None)
+        ntwk.state | should | equal_to('Allocated')
+        ntwk.delete()
+
+    def tearDown(self):
+        self.vpc.delete()
+        self.account.delete()
+
+@attr(tags='vpc')
+class VpcVmDeployTest(unittest.TestCase):
+
+    def setUp(self):
+        self.apiClient = cloudstackTestClient(mgtSvr='localhost',
+            logging=logging.getLogger('factory.cloudstack')).getApiClient()
+
+    def test_vpcVmDeploy(self):
+        self.account = UserAccount(apiclient=self.apiClient)
+        self.vpc = DefaultVpc(
+            apiclient=self.apiClient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            zoneid=get_zone(apiclient=self.apiClient).id
+        )
+        self.vpc |should_not| be(None)
+        ntwk = DefaultVpcNetwork(
+            apiclient=self.apiClient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            vpcid=self.vpc.id,
+            zoneid=get_zone(apiclient=self.apiClient).id
+        )
+        ntwk | should_not | be(None)
+        ntwk.state | should | equal_to('Allocated')
+        vm = VirtualMachineFactory(
+            apiclient=self.apiClient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            templateid=get_template(self.apiClient).id,
+            serviceofferingid=get_service_offering(self.apiClient).id,
+            networkid=ntwk.id,
+            zoneid=get_zone(self.apiClient).id
+        )
+        vm | should_not | be(None)
+        vm.state | should | equal_to("Running")
+
+    def tearDown(self):
+        self.account.delete()
+
+
+@attr(tags='single')
+class VpcVmFactoryTest(unittest.TestCase):
+    def setUp(self):
+        self.apiClient = cloudstackTestClient(mgtSvr='localhost',
+            logging=logging.getLogger('factory.cloudstack')).getApiClient()
+
+    def test_vpcVmDeployShort(self):
+        self.account = UserAccount(apiclient=self.apiClient)
+        vm = VpcVirtualMachine(
+            apiclient=self.apiClient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            templateid=get_template(self.apiClient).id,
+            serviceofferingid=get_service_offering(self.apiClient).id,
+            zoneid=get_zone(self.apiClient).id
+        )
+        vm | should_not | be(None)
+        vm.state | should | equal_to("Running")
+
+    def tearDown(self):
+        self.account.delete()


[05/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: include markdown docs


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/15d4d3ff
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/15d4d3ff
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/15d4d3ff

Branch: refs/heads/marvin-refactor
Commit: 15d4d3ff30058fe6c45aaf5d9ef31559b5e3bb8b
Parents: f57e109
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Tue Sep 3 22:15:14 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:11 2013 +0530

----------------------------------------------------------------------
 tools/marvin/MANIFEST.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15d4d3ff/tools/marvin/MANIFEST.in
----------------------------------------------------------------------
diff --git a/tools/marvin/MANIFEST.in b/tools/marvin/MANIFEST.in
index 3d37381..58c58ba 100644
--- a/tools/marvin/MANIFEST.in
+++ b/tools/marvin/MANIFEST.in
@@ -17,4 +17,4 @@
 
 
 include *.txt
-recursive-include docs *.txt
+recursive-include docs *.txt *.md


[26/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: PostGenerationMethodCall doesn't work in create strategy

For performing post-generation hooks after the generation during the
create strategy of a factory we need to use the post_generation hook
instead of a PostGenerationMethodCall. Also, the `apiclient` attribute
does not get passed to the postgenerator unless specified in the
kwargs using the extended args notation (ATTR__ARGS)

Also Correct the network creation test

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/94b203e7
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/94b203e7
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/94b203e7

Branch: refs/heads/marvin-refactor
Commit: 94b203e78bcbd59e21644e21be8b268aa3524fd3
Parents: 4d0e53d
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Tue Sep 10 16:46:35 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:43 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/factory/data/network.py     |  1 +
 .../marvin/factory/data/networkoffering.py      | 29 +++++++++++---------
 tools/marvin/marvin/test/test_factories.py      |  8 +++---
 3 files changed, 21 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/94b203e7/tools/marvin/marvin/factory/data/network.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/network.py b/tools/marvin/marvin/factory/data/network.py
index ad6101c..962d24f 100644
--- a/tools/marvin/marvin/factory/data/network.py
+++ b/tools/marvin/marvin/factory/data/network.py
@@ -30,6 +30,7 @@ class GuestIsolatedNetworkFactory(NetworkFactory):
         DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory,
         apiclient=factory.SelfAttribute('..apiclient'),
         name=factory.Sequence(lambda n: 'GuestIsolatedNetworkOffering-%s' % random_gen()),
+        enable__apiclient=factory.SelfAttribute('..apiclient')
     )
     networkofferingid = factory.LazyAttribute(lambda no: no.networkoffering.id if no.networkoffering else no.networkoffering)
     zoneid = None

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/94b203e7/tools/marvin/marvin/factory/data/networkoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/networkoffering.py b/tools/marvin/marvin/factory/data/networkoffering.py
index 829aee0..96f77cf 100644
--- a/tools/marvin/marvin/factory/data/networkoffering.py
+++ b/tools/marvin/marvin/factory/data/networkoffering.py
@@ -44,11 +44,11 @@ class DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory(NetworkOfferingF
             }
         )
     # enable the offering post generation
-    factory.PostGenerationMethodCall('update',
-        factory.SelfAttribute('..apiclient'),
-        id=factory.SelfAttribute('..id'),
-        state='Enabled')
-
+    @factory.post_generation
+    def enable(self, create, extracted, **kwargs):
+        if not create:
+            return
+        self.update(apiclient=kwargs['apiclient'], id=self.id, state='Enabled')
 
 
 class DefaultSharedNetworkOfferingWithSGServiceFactory(NetworkOfferingFactory):
@@ -79,10 +79,12 @@ class DefaultSharedNetworkOfferingWithSGServiceFactory(NetworkOfferingFactory):
         )
 
     # enable the offering post generation
-    factory.PostGenerationMethodCall('update',
-        factory.SelfAttribute('..apiclient'),
-        id=factory.SelfAttribute('..id'),
-        state='Enabled')
+    @factory.post_generation
+    def enable(self, create, extracted, **kwargs):
+        if not create:
+            return
+        self.update(apiclient=kwargs['apiclient'], id=self.id, state='Enabled')
+
 
 
 class DefaultSharedNetworkOfferingFactory(NetworkOfferingFactory):
@@ -109,7 +111,8 @@ class DefaultSharedNetworkOfferingFactory(NetworkOfferingFactory):
         )
 
     # enable the offering post generation
-    factory.PostGenerationMethodCall('update',
-        factory.SelfAttribute('..apiclient'),
-        id=factory.SelfAttribute('..id'),
-        state='Enabled')
+    @factory.post_generation
+    def enable(self, create, extracted, **kwargs):
+        if not create:
+            return
+        self.update(apiclient=kwargs['apiclient'], id=self.id, state='Enabled')

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/94b203e7/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 bf6f228..2dd5069 100644
--- a/tools/marvin/marvin/test/test_factories.py
+++ b/tools/marvin/marvin/test/test_factories.py
@@ -201,17 +201,17 @@ class NetworkFactoryTest(unittest.TestCase):
             logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def tearDown(self):
-        pass
+        self.accnt.delete()
 
     @attr(tags='network')
     def test_isolatedGuestNetwork(self):
         """Test to create a network within a guest account
         @return:
         """
-        accnt = UserAccountFactory(apiclient=self.apiClient)
+        self.accnt = UserAccountFactory(apiclient=self.apiClient)
         zones = Zone.list(apiclient=self.apiClient)
         network = GuestIsolatedNetworkFactory(
             apiclient=self.apiClient,
-            zoneid=zones[0].id,
+            zoneid=zones[0].id
             )
-        self.debug("network created with id, name" %(network.id, network.name))
\ No newline at end of file
+        logging.getLogger('factory.cloudstack').debug("network created with id %s, name %s" %(network.id, network.name))
\ No newline at end of file


[10/50] [abbrv] marvin-refactor: moving old integration libraries to legacy

Posted by ts...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/79a1591b/tools/marvin/marvin/oldbase.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/oldbase.py b/tools/marvin/marvin/oldbase.py
deleted file mode 100755
index d0cfc47..0000000
--- a/tools/marvin/marvin/oldbase.py
+++ /dev/null
@@ -1,3591 +0,0 @@
-# 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.
-
-""" Base class for all Cloudstack resources
-    -Virtual machine, Volume, Snapshot etc
-"""
-
-from marvin.utils import is_server_ssh_ready, random_gen
-from marvin.cloudstackAPI import *
-# Import System modules
-import time
-import hashlib
-import base64
-
-
-class Domain:
-    """ Domain Life Cycle """
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, name=None, networkdomain=None,
-               parentdomainid=None):
-        """Creates an domain"""
-
-        cmd = createDomain.createDomainCmd()
-
-        if "domainUUID" in services:
-            cmd.domainid = "-".join([services["domainUUID"], random_gen()])
-
-        if name:
-            cmd.name = "-".join([name, random_gen()])
-        elif "name" in services:
-            cmd.name = "-".join([services["name"], random_gen()])
-
-        if networkdomain:
-            cmd.networkdomain = networkdomain
-        elif "networkdomain" in services:
-            cmd.networkdomain = services["networkdomain"]
-
-        if parentdomainid:
-            cmd.parentdomainid = parentdomainid
-        elif "parentdomainid" in services:
-            cmd.parentdomainid = services["parentdomainid"]
-        try:
-            domain = apiclient.createDomain(cmd)
-            if domain is not None:
-                return Domain(domain.__dict__)
-        except Exception as e:
-            raise e
-
-    def delete(self, apiclient, cleanup=None):
-        """Delete an domain"""
-        cmd = deleteDomain.deleteDomainCmd()
-        cmd.id = self.id
-        if cleanup:
-            cmd.cleanup = cleanup
-        apiclient.deleteDomain(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists domains"""
-        cmd = listDomains.listDomainsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listDomains(cmd))
-
-
-class Account:
-    """ Account Life Cycle """
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, admin=False, domainid=None):
-        """Creates an account"""
-        cmd = createAccount.createAccountCmd()
-
-        # 0 - User, 1 - Root Admin, 2 - Domain Admin
-        cmd.accounttype = 2 if (admin and domainid) else int(admin)
-
-        cmd.email = services["email"]
-        cmd.firstname = services["firstname"]
-        cmd.lastname = services["lastname"]
-
-        cmd.password = services["password"]
-        cmd.username = "-".join([services["username"], random_gen(id=apiclient.id)])
-
-        if "accountUUID" in services:
-            cmd.accountid =  "-".join([services["accountUUID"],random_gen()])
-
-        if "userUUID" in services:
-            cmd.userid = "-".join([services["userUUID"],random_gen()])
-
-
-        if domainid:
-            cmd.domainid = domainid
-        account = apiclient.createAccount(cmd)
-
-        return Account(account.__dict__)
-
-    def delete(self, apiclient):
-        """Delete an account"""
-        cmd = deleteAccount.deleteAccountCmd()
-        cmd.id = self.id
-        apiclient.deleteAccount(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists accounts and provides detailed account information for
-        listed accounts"""
-
-        cmd = listAccounts.listAccountsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listAccounts(cmd))
-
-
-class User:
-    """ User Life Cycle """
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, account, domainid):
-        cmd = createUser.createUserCmd()
-        """Creates an user"""
-
-        cmd.account = account
-        cmd.domainid = domainid
-        cmd.email = services["email"]
-        cmd.firstname = services["firstname"]
-        cmd.lastname = services["lastname"]
-
-        if "userUUID" in services:
-            cmd.userid = "-".join([services["userUUID"],random_gen()])
-
-        cmd.password = services["password"]
-        cmd.username = "-".join([services["username"], random_gen()])
-        user = apiclient.createUser(cmd)
-
-        return User(user.__dict__)
-
-    def delete(self, apiclient):
-        """Delete an account"""
-        cmd = deleteUser.deleteUserCmd()
-        cmd.id = self.id
-        apiclient.deleteUser(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists users and provides detailed account information for
-        listed users"""
-
-        cmd = listUsers.listUsersCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listUsers(cmd))
-
-    @classmethod
-    def registerUserKeys(cls, apiclient, userid):
-        cmd = registerUserKeys.registerUserKeysCmd()
-        cmd.id = userid
-        return apiclient.registerUserKeys(cmd)
-
-    def update(self, apiclient, **kwargs):
-        """Updates the user details"""
-
-        cmd = updateUser.updateUserCmd()
-        cmd.id = self.id
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return (apiclient.updateUser(cmd))
-
-    @classmethod
-    def update(cls, apiclient, id, **kwargs):
-        """Updates the user details (class method)"""
-
-        cmd = updateUser.updateUserCmd()
-        cmd.id = id
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return (apiclient.updateUser(cmd))
-
-    @classmethod
-    def login(cls, apiclient, username, password, domain=None, domainid=None):
-        """Logins to the CloudStack"""
-
-        cmd = login.loginCmd()
-        cmd.username = username
-        cmd.password = password
-        if domain:
-            cmd.domain = domain
-        if domainid:
-            cmd.domainId = domainid
-        return apiclient.login(cmd)
-
-
-class VirtualMachine:
-    """Manage virtual machine lifecycle"""
-
-    def __init__(self, items, services):
-        self.__dict__.update(items)
-        if "username" in services:
-            self.username = services["username"]
-        else:
-            self.username = 'root'
-        if "password" in services:
-            self.password = services["password"]
-        else:
-            self.password = 'password'
-        if "ssh_port" in services:
-            self.ssh_port = services["ssh_port"]
-        else:
-            self.ssh_port = 22
-        self.ssh_client = None
-        # extract out the ipaddress
-        self.ipaddress = self.nic[0].ipaddress
-
-    @classmethod
-    def ssh_access_group(cls, apiclient, cmd):
-        """
-        Programs the security group with SSH access before deploying virtualmachine
-        @return:
-        """
-        zone_list = Zone.list(
-            apiclient,
-            id=cmd.zoneid if cmd.zoneid else None,
-            domainid=cmd.domainid if cmd.domainid else None
-        )
-        zone = zone_list[0]
-        #check if security groups settings is enabled for the zone
-        if zone.securitygroupsenabled:
-            list_security_groups = SecurityGroup.list(
-                apiclient,
-                securitygroupname="basic_sec_grp"
-            )
-
-            if not isinstance(list_security_groups, list):
-                basic_mode_security_group = SecurityGroup.create(
-                    apiclient,
-                    {"name": "basic_sec_grp"}
-                )
-                sec_grp_services = {
-                    "protocol": "TCP",
-                    "startport": 22,
-                    "endport": 22,
-                    "cidrlist": "0.0.0.0/0"
-                }
-                #Authorize security group for above ingress rule
-                basic_mode_security_group.authorize(apiclient, sec_grp_services, account=cmd.account,
-                    domainid=cmd.domainid)
-            else:
-                basic_mode_security_group = list_security_groups[0]
-
-            if isinstance(cmd.securitygroupids, list):
-                cmd.securitygroupids.append(basic_mode_security_group.id)
-            else:
-                cmd.securitygroupids = [basic_mode_security_group.id]
-
-    @classmethod
-    def access_ssh_over_nat(cls, apiclient, services, virtual_machine, allow_egress=False):
-        """
-        Program NAT and PF rules to open up ssh access to deployed guest
-        @return:
-        """
-        public_ip = PublicIPAddress.create(
-            apiclient=apiclient,
-            accountid=virtual_machine.account,
-            zoneid=virtual_machine.zoneid,
-            domainid=virtual_machine.domainid,
-            services=services
-        )
-        FireWallRule.create(
-            apiclient=apiclient,
-            ipaddressid=public_ip.ipaddress.id,
-            protocol='TCP',
-            cidrlist=['0.0.0.0/0'],
-            startport=22,
-            endport=22
-        )
-        nat_rule = NATRule.create(
-            apiclient=apiclient,
-            virtual_machine=virtual_machine,
-            services=services,
-            ipaddressid=public_ip.ipaddress.id
-        )
-        if allow_egress:
-            EgressFireWallRule.create(
-                apiclient=apiclient,
-                networkid=virtual_machine.nic[0].networkid,
-                protocol='All',
-                cidrlist='0.0.0.0/0'
-            )
-        virtual_machine.ssh_ip = nat_rule.ipaddress
-        virtual_machine.public_ip = nat_rule.ipaddress
-
-    @classmethod
-    def create(cls, apiclient, services, templateid=None, accountid=None,
-                    domainid=None, zoneid=None, networkids=None, serviceofferingid=None,
-                    securitygroupids=None, projectid=None, startvm=None,
-                    diskofferingid=None, affinitygroupnames=None, affinitygroupids=None, group=None,
-                    hostid=None, keypair=None, ipaddress=None, mode='default', method='GET'):
-        """Create the instance"""
-
-        cmd = deployVirtualMachine.deployVirtualMachineCmd()
-
-        if serviceofferingid:
-            cmd.serviceofferingid = serviceofferingid
-        elif "serviceoffering" in services:
-            cmd.serviceofferingid = services["serviceoffering"]
-
-        if zoneid:
-            cmd.zoneid = zoneid
-        elif "zoneid" in services:
-            cmd.zoneid = services["zoneid"]
-        cmd.hypervisor = apiclient.hypervisor
-
-        if "displayname" in services:
-            cmd.displayname = services["displayname"]
-
-        if "name" in services:
-            cmd.name = services["name"]
-
-        if accountid:
-            cmd.account = accountid
-        elif "account" in services:
-            cmd.account = services["account"]
-
-        if domainid:
-            cmd.domainid = domainid
-        elif "domainid" in services:
-            cmd.domainid = services["domainid"]
-
-        if networkids:
-            cmd.networkids = networkids
-            allow_egress = False
-        elif "networkids" in services:
-            cmd.networkids = services["networkids"]
-            allow_egress = False
-        else:
-            # When no networkids are passed, network
-            # is created using the "defaultOfferingWithSourceNAT"
-            # which has an egress policy of DENY. But guests in tests
-            # need access to test network connectivity
-            allow_egress = True
-
-        if templateid:
-            cmd.templateid = templateid
-        elif "template" in services:
-            cmd.templateid = services["template"]
-
-        if diskofferingid:
-            cmd.diskofferingid = diskofferingid
-        elif "diskoffering" in services:
-            cmd.diskofferingid = services["diskoffering"]
-
-        if keypair:
-            cmd.keypair = keypair
-        elif "keypair" in services:
-            cmd.keypair = services["keypair"]
-
-        if ipaddress:
-            cmd.ipaddress = ipaddress
-        elif ipaddress in services:
-            cmd.ipaddress = services["ipaddress"]
-
-        if securitygroupids:
-            cmd.securitygroupids = [str(sg_id) for sg_id in securitygroupids]
-
-        if "affinitygroupnames" in services:
-            cmd.affinitygroupnames  = services["affinitygroupnames"]
-        elif affinitygroupnames:
-            cmd.affinitygroupnames  = affinitygroupnames
-
-        if affinitygroupids:
-            cmd.affinitygroupids  = affinitygroupids
-
-        if projectid:
-            cmd.projectid = projectid
-
-        if startvm is not None:
-            cmd.startvm = startvm
-
-        if hostid:
-            cmd.hostid = hostid
-
-        if "userdata" in services:
-            cmd.userdata = base64.urlsafe_b64encode(services["userdata"])
-
-        if group:
-            cmd.group = group
-
-        #program default access to ssh
-        if mode.lower() == 'basic':
-            cls.ssh_access_group(apiclient, cmd)
-
-        virtual_machine = apiclient.deployVirtualMachine(cmd, method=method)
-
-        virtual_machine.ssh_ip = virtual_machine.nic[0].ipaddress
-        if startvm == False:
-            virtual_machine.public_ip = virtual_machine.nic[0].ipaddress
-            return VirtualMachine(virtual_machine.__dict__, services)
-
-        #program ssh access over NAT via PF
-        if mode.lower() == 'advanced':
-            cls.access_ssh_over_nat(apiclient, services, virtual_machine, allow_egress=allow_egress)
-        elif mode.lower() == 'basic':
-            if virtual_machine.publicip is not None:
-                vm_ssh_ip = virtual_machine.publicip #EIP/ELB (netscaler) enabled zone
-            else:
-                vm_ssh_ip = virtual_machine.nic[0].ipaddress #regular basic zone with security group
-            virtual_machine.ssh_ip = vm_ssh_ip
-            virtual_machine.public_ip = vm_ssh_ip
-
-        return VirtualMachine(virtual_machine.__dict__, services)
-
-    def start(self, apiclient):
-        """Start the instance"""
-        cmd = startVirtualMachine.startVirtualMachineCmd()
-        cmd.id = self.id
-        apiclient.startVirtualMachine(cmd)
-
-    def stop(self, apiclient):
-        """Stop the instance"""
-        cmd = stopVirtualMachine.stopVirtualMachineCmd()
-        cmd.id = self.id
-        apiclient.stopVirtualMachine(cmd)
-
-    def reboot(self, apiclient):
-        """Reboot the instance"""
-        cmd = rebootVirtualMachine.rebootVirtualMachineCmd()
-        cmd.id = self.id
-        apiclient.rebootVirtualMachine(cmd)
-
-    def recover(self, apiclient):
-        """Recover the instance"""
-        cmd = recoverVirtualMachine.recoverVirtualMachineCmd()
-        cmd.id = self.id
-        apiclient.recoverVirtualMachine(cmd)
-
-    def get_ssh_client(self, ipaddress=None, reconnect=False, port=None, keyPairFileLocation=None):
-        """Get SSH object of VM"""
-
-        # If NAT Rules are not created while VM deployment in Advanced mode
-        # then, IP address must be passed
-        if ipaddress != None:
-            self.ssh_ip = ipaddress
-        if port:
-            self.ssh_port = port
-
-        if keyPairFileLocation is not None:
-            self.password = None
-
-        if reconnect:
-            self.ssh_client = is_server_ssh_ready(
-                                                    self.ssh_ip,
-                                                    self.ssh_port,
-                                                    self.username,
-                                                    self.password,
-                                                    keyPairFileLocation=keyPairFileLocation
-                                                )
-        self.ssh_client = self.ssh_client or is_server_ssh_ready(
-                                                    self.ssh_ip,
-                                                    self.ssh_port,
-                                                    self.username,
-                                                    self.password,
-                                                    keyPairFileLocation=keyPairFileLocation
-                                                )
-        return self.ssh_client
-
-    def resetSshKey(self, apiclient, **kwargs):
-        """Resets SSH key"""
-
-        cmd = resetSSHKeyForVirtualMachine.resetSSHKeyForVirtualMachineCmd()
-        cmd.id = self.id
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.resetSSHKeyForVirtualMachine(cmd))
-
-    def update(self, apiclient, **kwargs):
-        """Updates the VM data"""
-
-        cmd = updateVirtualMachine.updateVirtualMachineCmd()
-        cmd.id = self.id
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.updateVirtualMachine(cmd))
-
-    def delete(self, apiclient):
-        """Destroy an Instance"""
-        cmd = destroyVirtualMachine.destroyVirtualMachineCmd()
-        cmd.id = self.id
-        apiclient.destroyVirtualMachine(cmd)
-
-    def migrate(self, apiclient, hostid=None):
-        """migrate an Instance"""
-        cmd = migrateVirtualMachine.migrateVirtualMachineCmd()
-        cmd.virtualmachineid = self.id
-        if hostid:
-            cmd.hostid = hostid
-        apiclient.migrateVirtualMachine(cmd)
-
-    def attach_volume(self, apiclient, volume):
-        """Attach volume to instance"""
-        cmd = attachVolume.attachVolumeCmd()
-        cmd.id = volume.id
-        cmd.virtualmachineid = self.id
-        return apiclient.attachVolume(cmd)
-
-    def detach_volume(self, apiclient, volume):
-        """Detach volume to instance"""
-        cmd = detachVolume.detachVolumeCmd()
-        cmd.id = volume.id
-        return apiclient.detachVolume(cmd)
-
-    def add_nic(self, apiclient, networkId):
-        """Add a NIC to a VM"""
-        cmd = addNicToVirtualMachine.addNicToVirtualMachineCmd()
-        cmd.virtualmachineid = self.id
-        cmd.networkid = networkId
-        return apiclient.addNicToVirtualMachine(cmd)
-
-    def remove_nic(self, apiclient, nicId):
-        """Remove a NIC to a VM"""
-        cmd = removeNicFromVirtualMachine.removeNicFromVirtualMachineCmd()
-        cmd.nicid = nicId
-        cmd.virtualmachineid = self.id
-        return apiclient.removeNicFromVirtualMachine(cmd)
-
-    def update_default_nic(self, apiclient, nicId):
-        """Set a NIC to be the default network adapter for a VM"""
-        cmd = updateDefaultNicForVirtualMachine.updateDefaultNicForVirtualMachineCmd()
-        cmd.nicid = nicId
-        cmd.virtualmachineid = self.id
-        return apiclient.updateDefaultNicForVirtualMachine(cmd)
-
-    def attach_iso(self, apiclient, iso):
-        """Attach ISO to instance"""
-        cmd = attachIso.attachIsoCmd()
-        cmd.id = iso.id
-        cmd.virtualmachineid = self.id
-        return apiclient.attachIso(cmd)
-
-    def detach_iso(self, apiclient):
-        """Detach ISO to instance"""
-        cmd = detachIso.detachIsoCmd()
-        cmd.id = self.id
-        return apiclient.detachIso(cmd)
-
-    def change_service_offering(self, apiclient, serviceOfferingId):
-        """Change service offering of the instance"""
-        cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd()
-        cmd.id = self.id
-        cmd.serviceofferingid = serviceOfferingId
-        return apiclient.changeServiceForVirtualMachine(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all VMs matching criteria"""
-
-        cmd = listVirtualMachines.listVirtualMachinesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listVirtualMachines(cmd))
-
-    def resetPassword(self, apiclient):
-        """Resets VM password if VM created using password enabled template"""
-
-        cmd = resetPasswordForVirtualMachine.resetPasswordForVirtualMachineCmd()
-        cmd.id = self.id
-        try:
-            response = apiclient.resetPasswordForVirtualMachine(cmd)
-        except Exception as e:
-            raise Exception("Reset Password failed! - %s" % e)
-        if response is not None:
-            return response.password
-
-    def assign_virtual_machine(self, apiclient, account, domainid):
-        """Move a user VM to another user under same domain."""
-
-        cmd                  = assignVirtualMachine.assignVirtualMachineCmd()
-        cmd.virtualmachineid = self.id
-        cmd.account          = account
-        cmd.domainid         = domainid
-        try:
-            response = apiclient.assignVirtualMachine(cmd)
-            return response
-        except Exception as e:
-            raise Exception("assignVirtualMachine failed - %s" %e)
-
-    def update_affinity_group(self, apiclient, affinitygroupids=None,
-                              affinitygroupnames=None):
-        """Update affinity group of a VM"""
-        cmd = updateVMAffinityGroup.updateVMAffinityGroupCmd()
-        cmd.id = self.id
-
-        if affinitygroupids:
-            cmd.affinitygroupids = affinitygroupids
-
-        if affinitygroupnames:
-            cmd.affinitygroupnames = affinitygroupnames
-
-        return apiclient.updateVMAffinityGroup(cmd)
-
-
-class Volume:
-    """Manage Volume Life cycle
-    """
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, zoneid=None, account=None,
-               domainid=None, diskofferingid=None, projectid=None):
-        """Create Volume"""
-        cmd = createVolume.createVolumeCmd()
-        cmd.name = services["diskname"]
-
-        if diskofferingid:
-            cmd.diskofferingid = diskofferingid
-        elif "diskofferingid" in services:
-            cmd.diskofferingid = services["diskofferingid"]
-
-        if zoneid:
-            cmd.zoneid = zoneid
-        elif "zoneid" in services:
-            cmd.zoneid = services["zoneid"]
-
-        if account:
-            cmd.account = account
-        elif "account" in services:
-            cmd.account = services["account"]
-
-        if domainid:
-            cmd.domainid = domainid
-        elif "domainid" in services:
-            cmd.domainid = services["domainid"]
-
-        if projectid:
-            cmd.projectid = projectid
-        return Volume(apiclient.createVolume(cmd).__dict__)
-
-    @classmethod
-    def create_custom_disk(cls, apiclient, services, account=None,
-                                    domainid=None, diskofferingid=None):
-        """Create Volume from Custom disk offering"""
-        cmd = createVolume.createVolumeCmd()
-        cmd.name = services["diskname"]
-
-        if diskofferingid:
-            cmd.diskofferingid = diskofferingid
-        elif "customdiskofferingid" in services:
-            cmd.diskofferingid = services["customdiskofferingid"]
-
-        cmd.size = services["customdisksize"]
-        cmd.zoneid = services["zoneid"]
-
-        if account:
-            cmd.account = account
-        else:
-            cmd.account = services["account"]
-
-        if domainid:
-            cmd.domainid = domainid
-        else:
-            cmd.domainid = services["domainid"]
-
-        return Volume(apiclient.createVolume(cmd).__dict__)
-
-    @classmethod
-    def create_from_snapshot(cls, apiclient, snapshot_id, services,
-                             account=None, domainid=None):
-        """Create Volume from snapshot"""
-        cmd = createVolume.createVolumeCmd()
-        cmd.name = "-".join([services["diskname"], random_gen()])
-        cmd.snapshotid = snapshot_id
-        cmd.zoneid = services["zoneid"]
-        cmd.size = services["size"]
-        if account:
-            cmd.account = account
-        else:
-            cmd.account = services["account"]
-        if domainid:
-            cmd.domainid = domainid
-        else:
-            cmd.domainid = services["domainid"]
-        return Volume(apiclient.createVolume(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Volume"""
-        cmd = deleteVolume.deleteVolumeCmd()
-        cmd.id = self.id
-        apiclient.deleteVolume(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all volumes matching criteria"""
-
-        cmd = listVolumes.listVolumesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listVolumes(cmd))
-
-    def resize(self, apiclient, **kwargs):
-        """Resize a volume"""
-        cmd = resizeVolume.resizeVolumeCmd()
-        cmd.id = self.id
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.resizeVolume(cmd))
-
-    @classmethod
-    def upload(cls, apiclient, services, zoneid=None, account=None, domainid=None, url=None):
-        """Uploads the volume to specified account"""
-
-        cmd = uploadVolume.uploadVolumeCmd()
-        if zoneid:
-            cmd.zoneid = zoneid
-        if account:
-            cmd.account = account
-        if domainid:
-            cmd.domainid = domainid
-        cmd.format = services["format"]
-        cmd.name = services["diskname"]
-        if url:
-            cmd.url = url
-        else:
-            cmd.url = services["url"]
-        return Volume(apiclient.uploadVolume(cmd).__dict__)
-
-    def wait_for_upload(self, apiclient, timeout=5, interval=60):
-        """Wait for upload"""
-        # Sleep to ensure template is in proper state before download
-        time.sleep(interval)
-
-        while True:
-            volume_response = Volume.list(
-                                    apiclient,
-                                    id=self.id,
-                                    zoneid=self.zoneid,
-                                    )
-            if isinstance(volume_response, list):
-
-                volume = volume_response[0]
-                # If volume is ready,
-                # volume.state = Allocated
-                if volume.state == 'Uploaded':
-                    break
-
-                elif 'Uploading' in volume.state:
-                    time.sleep(interval)
-
-                elif 'Installing' not in volume.state:
-                    raise Exception(
-                        "Error in uploading volume: status - %s" %
-                                                            volume.state)
-            elif timeout == 0:
-                break
-
-            else:
-                time.sleep(interval)
-                timeout = timeout - 1
-        return
-
-    @classmethod
-    def migrate(cls, apiclient, **kwargs):
-        """Migrate a volume"""
-        cmd = migrateVolume.migrateVolumeCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.migrateVolume(cmd))
-
-class Snapshot:
-    """Manage Snapshot Lifecycle
-    """
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, volume_id, account=None,
-                                            domainid=None, projectid=None):
-        """Create Snapshot"""
-        cmd = createSnapshot.createSnapshotCmd()
-        cmd.volumeid = volume_id
-        if account:
-            cmd.account = account
-        if domainid:
-            cmd.domainid = domainid
-        if projectid:
-            cmd.projectid = projectid
-        return Snapshot(apiclient.createSnapshot(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Snapshot"""
-        cmd = deleteSnapshot.deleteSnapshotCmd()
-        cmd.id = self.id
-        apiclient.deleteSnapshot(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all snapshots matching criteria"""
-
-        cmd = listSnapshots.listSnapshotsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listSnapshots(cmd))
-
-
-class Template:
-    """Manage template life cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, volumeid=None,
-               account=None, domainid=None, projectid=None):
-        """Create template from Volume"""
-        # Create template from Virtual machine and Volume ID
-        cmd = createTemplate.createTemplateCmd()
-        cmd.displaytext = services["displaytext"]
-        cmd.name = "-".join([services["name"], random_gen()])
-        if "ostypeid" in services:
-            cmd.ostypeid = services["ostypeid"]
-        elif "ostype" in services:
-            # Find OSTypeId from Os type
-            sub_cmd = listOsTypes.listOsTypesCmd()
-            sub_cmd.description = services["ostype"]
-            ostypes = apiclient.listOsTypes(sub_cmd)
-
-            if not isinstance(ostypes, list):
-                raise Exception(
-                    "Unable to find Ostype id with desc: %s" %
-                                                services["ostype"])
-            cmd.ostypeid = ostypes[0].id
-        else:
-            raise Exception(
-                    "Unable to find Ostype is required for creating template")
-
-        cmd.isfeatured = services["isfeatured"] if "isfeatured" in services else False
-        cmd.ispublic = services["ispublic"] if "ispublic" in services else False
-        cmd.isextractable = services["isextractable"] if "isextractable" in services else False
-        cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False
-
-        if volumeid:
-            cmd.volumeid = volumeid
-
-        if account:
-            cmd.account = account
-
-        if domainid:
-            cmd.domainid = domainid
-
-        if projectid:
-            cmd.projectid = projectid
-        return Template(apiclient.createTemplate(cmd).__dict__)
-
-    @classmethod
-    def register(cls, apiclient, services, zoneid=None,
-                                                account=None, domainid=None):
-        """Create template from URL"""
-
-        # Create template from Virtual machine and Volume ID
-        cmd = registerTemplate.registerTemplateCmd()
-        cmd.displaytext = services["displaytext"]
-        cmd.name = "-".join([services["name"], random_gen()])
-        cmd.format = services["format"]
-        cmd.hypervisor = apiclient.hypervisor
-
-        if "ostypeid" in services:
-            cmd.ostypeid = services["ostypeid"]
-        elif "ostype" in services:
-            # Find OSTypeId from Os type
-            sub_cmd = listOsTypes.listOsTypesCmd()
-            sub_cmd.description = services["ostype"]
-            ostypes = apiclient.listOsTypes(sub_cmd)
-
-            if not isinstance(ostypes, list):
-                raise Exception(
-                    "Unable to find Ostype id with desc: %s" %
-                                                services["ostype"])
-            cmd.ostypeid = ostypes[0].id
-        else:
-            raise Exception(
-                    "Unable to find Ostype is required for registering template")
-
-        cmd.url = services["url"]
-
-        if zoneid:
-            cmd.zoneid = zoneid
-        else:
-            cmd.zoneid = services["zoneid"]
-
-        cmd.isfeatured = services["isfeatured"] if "isfeatured" in services else False
-        cmd.ispublic = services["ispublic"] if "ispublic" in services else False
-        cmd.isextractable = services["isextractable"] if "isextractable" in services else False
-        cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False
-
-        if account:
-            cmd.account = account
-
-        if domainid:
-            cmd.domainid = domainid
-
-        # Register Template
-        template = apiclient.registerTemplate(cmd)
-
-        if isinstance(template, list):
-            return Template(template[0].__dict__)
-
-    @classmethod
-    def extract(cls, apiclient, id, mode, zoneid=None):
-        "Extract template "
-
-        cmd = extractTemplate.extractTemplateCmd()
-        cmd.id = id
-        cmd.mode = mode
-        cmd.zoneid = zoneid
-
-        return apiclient.extractTemplate(cmd)
-
-    @classmethod
-    def create_from_snapshot(cls, apiclient, snapshot, services,
-                                                        random_name=True):
-        """Create Template from snapshot"""
-        # Create template from Virtual machine and Snapshot ID
-        cmd = createTemplate.createTemplateCmd()
-        cmd.displaytext = services["displaytext"]
-        cmd.name = "-".join([
-                             services["name"],
-                             random_gen()
-                            ]) if random_name else services["name"]
-
-        if "ostypeid" in services:
-            cmd.ostypeid = services["ostypeid"]
-        elif "ostype" in services:
-            # Find OSTypeId from Os type
-            sub_cmd = listOsTypes.listOsTypesCmd()
-            sub_cmd.description = services["ostype"]
-            ostypes = apiclient.listOsTypes(sub_cmd)
-
-            if not isinstance(ostypes, list):
-                raise Exception(
-                    "Unable to find Ostype id with desc: %s" %
-                                                services["ostype"])
-            cmd.ostypeid = ostypes[0].id
-        else:
-            raise Exception(
-                    "Unable to find Ostype is required for creating template")
-
-        cmd.snapshotid = snapshot.id
-        return Template(apiclient.createTemplate(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Template"""
-
-        cmd = deleteTemplate.deleteTemplateCmd()
-        cmd.id = self.id
-        apiclient.deleteTemplate(cmd)
-
-    def download(self, apiclient, timeout=5, interval=60):
-        """Download Template"""
-        # Sleep to ensure template is in proper state before download
-        time.sleep(interval)
-
-        while True:
-            template_response = Template.list(
-                                    apiclient,
-                                    id=self.id,
-                                    zoneid=self.zoneid,
-                                    templatefilter='self'
-                                    )
-            if isinstance(template_response, list):
-
-                template = template_response[0]
-                # If template is ready,
-                # template.status = Download Complete
-                # Downloading - x% Downloaded
-                # Error - Any other string
-                if template.status == 'Download Complete':
-                    break
-
-                elif 'Downloaded' in template.status:
-                    time.sleep(interval)
-
-                elif 'Installing' not in template.status:
-                    raise Exception(
-                        "Error in downloading template: status - %s" %
-                                                            template.status)
-
-            elif timeout == 0:
-                break
-
-            else:
-                time.sleep(interval)
-                timeout = timeout - 1
-        return
-
-    def updatePermissions(self, apiclient, **kwargs):
-        """Updates the template permissions"""
-
-        cmd = updateTemplatePermissions.updateTemplatePermissionsCmd()
-        cmd.id = self.id
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.updateTemplatePermissions(cmd))
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all templates matching criteria"""
-
-        cmd = listTemplates.listTemplatesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listTemplates(cmd))
-
-
-class Iso:
-    """Manage ISO life cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, account=None, domainid=None,
-                                                        projectid=None):
-        """Create an ISO"""
-        # Create ISO from URL
-        cmd = registerIso.registerIsoCmd()
-        cmd.displaytext = services["displaytext"]
-        cmd.name = services["name"]
-        if "ostypeid" in services:
-            cmd.ostypeid = services["ostypeid"]
-        elif "ostype" in services:
-            # Find OSTypeId from Os type
-            sub_cmd = listOsTypes.listOsTypesCmd()
-            sub_cmd.description = services["ostype"]
-            ostypes = apiclient.listOsTypes(sub_cmd)
-
-            if not isinstance(ostypes, list):
-                raise Exception(
-                    "Unable to find Ostype id with desc: %s" %
-                                                services["ostype"])
-            cmd.ostypeid = ostypes[0].id
-        else:
-            raise Exception(
-                    "Unable to find Ostype is required for creating ISO")
-
-        cmd.url = services["url"]
-        cmd.zoneid = services["zoneid"]
-
-        if "isextractable" in services:
-            cmd.isextractable = services["isextractable"]
-        if "isfeatured" in services:
-            cmd.isfeatured = services["isfeatured"]
-        if "ispublic" in services:
-            cmd.ispublic = services["ispublic"]
-
-        if account:
-            cmd.account = account
-        if domainid:
-            cmd.domainid = domainid
-        if projectid:
-            cmd.projectid = projectid
-        # Register ISO
-        iso = apiclient.registerIso(cmd)
-
-        if iso:
-            return Iso(iso[0].__dict__)
-
-    def delete(self, apiclient):
-        """Delete an ISO"""
-        cmd = deleteIso.deleteIsoCmd()
-        cmd.id = self.id
-        apiclient.deleteIso(cmd)
-        return
-
-    def download(self, apiclient, timeout=5, interval=60):
-        """Download an ISO"""
-        # Ensuring ISO is successfully downloaded
-        while True:
-            time.sleep(interval)
-
-            cmd = listIsos.listIsosCmd()
-            cmd.id = self.id
-            iso_response = apiclient.listIsos(cmd)
-
-            if isinstance(iso_response, list):
-                response = iso_response[0]
-                # Again initialize timeout to avoid listISO failure
-                timeout = 5
-                # Check whether download is in progress(for Ex:10% Downloaded)
-                # or ISO is 'Successfully Installed'
-                if response.status == 'Successfully Installed':
-                    return
-                elif 'Downloaded' not in response.status and \
-                    'Installing' not in response.status:
-                    raise Exception(
-                        "Error In Downloading ISO: ISO Status - %s" %
-                                                            response.status)
-
-            elif timeout == 0:
-                raise Exception("ISO download Timeout Exception")
-            else:
-                timeout = timeout - 1
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all available ISO files."""
-
-        cmd = listIsos.listIsosCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listIsos(cmd))
-
-
-class PublicIPAddress:
-    """Manage Public IP Addresses"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, accountid=None, zoneid=None, domainid=None, services=None,
-               networkid=None, projectid=None, vpcid=None, isportable=False):
-        """Associate Public IP address"""
-        cmd = associateIpAddress.associateIpAddressCmd()
-
-        if accountid:
-            cmd.account = accountid
-        elif "account" in services:
-            cmd.account = services["account"]
-
-        if zoneid:
-            cmd.zoneid = zoneid
-        elif "zoneid" in services:
-            cmd.zoneid = services["zoneid"]
-
-        if domainid:
-            cmd.domainid = domainid
-        elif "domainid" in services:
-            cmd.domainid = services["domainid"]
-
-        if isportable:
-            cmd.isportable = isportable
-
-        if networkid:
-            cmd.networkid = networkid
-
-        if projectid:
-            cmd.projectid = projectid
-
-        if vpcid:
-            cmd.vpcid = vpcid
-        return PublicIPAddress(apiclient.associateIpAddress(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Dissociate Public IP address"""
-        cmd = disassociateIpAddress.disassociateIpAddressCmd()
-        cmd.id = self.ipaddress.id
-        apiclient.disassociateIpAddress(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Public IPs matching criteria"""
-
-        cmd = listPublicIpAddresses.listPublicIpAddressesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listPublicIpAddresses(cmd))
-
-
-class NATRule:
-    """Manage port forwarding rule"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, virtual_machine, services, ipaddressid=None,
-               projectid=None, openfirewall=False, networkid=None, vpcid=None):
-        """Create Port forwarding rule"""
-        cmd = createPortForwardingRule.createPortForwardingRuleCmd()
-
-        if ipaddressid:
-            cmd.ipaddressid = ipaddressid
-        elif "ipaddressid" in services:
-            cmd.ipaddressid = services["ipaddressid"]
-
-        cmd.privateport = services["privateport"]
-        cmd.publicport = services["publicport"]
-        if "privateendport" in services:
-            cmd.privateendport = services["privateendport"]
-        if "publicendport" in services:
-            cmd.publicendport = services["publicendport"]
-        cmd.protocol = services["protocol"]
-        cmd.virtualmachineid = virtual_machine.id
-
-        if projectid:
-            cmd.projectid = projectid
-
-        if openfirewall:
-            cmd.openfirewall = True
-
-        if networkid:
-            cmd.networkid = networkid
-
-        if vpcid:
-            cmd.vpcid = vpcid
-        return NATRule(apiclient.createPortForwardingRule(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete port forwarding"""
-        cmd = deletePortForwardingRule.deletePortForwardingRuleCmd()
-        cmd.id = self.id
-        apiclient.deletePortForwardingRule(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all NAT rules matching criteria"""
-
-        cmd = listPortForwardingRules.listPortForwardingRulesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listPortForwardingRules(cmd))
-
-
-class StaticNATRule:
-    """Manage Static NAT rule"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, ipaddressid=None, networkid=None, vpcid=None):
-        """Creates static ip forwarding rule"""
-
-        cmd = createFirewallRule.createFirewallRuleCmd()
-        cmd.protocol = services["protocol"]
-        cmd.startport = services["startport"]
-
-        if "endport" in services:
-            cmd.endport = services["endport"]
-
-        if "cidrlist" in services:
-            cmd.cidrlist = services["cidrlist"]
-
-        if ipaddressid:
-            cmd.ipaddressid = ipaddressid
-        elif "ipaddressid" in services:
-            cmd.ipaddressid = services["ipaddressid"]
-
-        if networkid:
-            cmd.networkid = networkid
-
-        if vpcid:
-            cmd.vpcid = vpcid
-        return StaticNATRule(apiclient.createFirewallRule(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete IP forwarding rule"""
-        cmd = deleteIpForwardingRule.deleteIpForwardingRuleCmd()
-        cmd.id = self.id
-        apiclient.deleteIpForwardingRule(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all IP forwarding rules matching criteria"""
-
-        cmd = listIpForwardingRules.listIpForwardingRulesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listIpForwardingRules(cmd))
-
-    @classmethod
-    def enable(cls, apiclient, ipaddressid, virtualmachineid, networkid=None):
-        """Enables Static NAT rule"""
-
-        cmd = enableStaticNat.enableStaticNatCmd()
-        cmd.ipaddressid = ipaddressid
-        cmd.virtualmachineid = virtualmachineid
-        if networkid:
-            cmd.networkid = networkid
-        apiclient.enableStaticNat(cmd)
-        return
-
-    @classmethod
-    def disable(cls, apiclient, ipaddressid, virtualmachineid):
-        """Disables Static NAT rule"""
-
-        cmd = disableStaticNat.disableStaticNatCmd()
-        cmd.ipaddressid = ipaddressid
-        apiclient.disableStaticNat(cmd)
-        return
-
-
-class EgressFireWallRule:
-    """Manage Egress Firewall rule"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, networkid, protocol, cidrlist=None,
-               startport=None, endport=None):
-        """Create Egress Firewall Rule"""
-        cmd = createEgressFirewallRule.createEgressFirewallRuleCmd()
-        cmd.networkid = networkid
-        cmd.protocol = protocol
-        if cidrlist:
-            cmd.cidrlist = cidrlist
-        if startport:
-            cmd.startport = startport
-        if endport:
-            cmd.endport = endport
-
-        return EgressFireWallRule(apiclient.createEgressFirewallRule(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Egress Firewall rule"""
-        cmd = deleteEgressFirewallRule.deleteEgressFirewallRuleCmd()
-        cmd.id = self.id
-        apiclient.deleteEgressFirewallRule(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Egress Firewall Rules matching criteria"""
-
-        cmd = listEgressFirewallRules.listEgressFirewallRulesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listEgressFirewallRules(cmd))
-
-
-
-class FireWallRule:
-    """Manage Firewall rule"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, ipaddressid, protocol, cidrlist=None,
-               startport=None, endport=None, projectid=None, vpcid=None):
-        """Create Firewall Rule"""
-        cmd = createFirewallRule.createFirewallRuleCmd()
-        cmd.ipaddressid = ipaddressid
-        cmd.protocol = protocol
-        if cidrlist:
-            cmd.cidrlist = cidrlist
-        if startport:
-            cmd.startport = startport
-        if endport:
-            cmd.endport = endport
-
-        if projectid:
-            cmd.projectid = projectid
-
-        if vpcid:
-            cmd.vpcid = vpcid
-
-        return FireWallRule(apiclient.createFirewallRule(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Firewall rule"""
-        cmd = deleteFirewallRule.deleteFirewallRuleCmd()
-        cmd.id = self.id
-        apiclient.deleteFirewallRule(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Firewall Rules matching criteria"""
-
-        cmd = listFirewallRules.listFirewallRulesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listFirewallRules(cmd))
-
-
-class ServiceOffering:
-    """Manage service offerings cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, domainid=None, **kwargs):
-        """Create Service offering"""
-        cmd = createServiceOffering.createServiceOfferingCmd()
-        cmd.cpunumber = services["cpunumber"]
-        cmd.cpuspeed = services["cpuspeed"]
-        cmd.displaytext = services["displaytext"]
-        cmd.memory = services["memory"]
-        cmd.name = services["name"]
-        if "storagetype" in services:
-            cmd.storagetype = services["storagetype"]
-
-        if "systemvmtype" in services:
-            cmd.systemvmtype = services['systemvmtype']
-
-        if "issystem" in services:
-            cmd.issystem = services['issystem']
-
-        if "tags" in services:
-            cmd.tags = services["tags"]
-
-        if "deploymentplanner" in services:
-            cmd.deploymentplanner = services["deploymentplanner"]
-
-        # Service Offering private to that domain
-        if domainid:
-            cmd.domainid = domainid
-
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return ServiceOffering(apiclient.createServiceOffering(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Service offering"""
-        cmd = deleteServiceOffering.deleteServiceOfferingCmd()
-        cmd.id = self.id
-        apiclient.deleteServiceOffering(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all available service offerings."""
-
-        cmd = listServiceOfferings.listServiceOfferingsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listServiceOfferings(cmd))
-
-
-class DiskOffering:
-    """Manage disk offerings cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, custom=False, domainid=None):
-        """Create Disk offering"""
-        cmd = createDiskOffering.createDiskOfferingCmd()
-        cmd.displaytext = services["displaytext"]
-        cmd.name = services["name"]
-        if custom:
-            cmd.customized = True
-        else:
-            cmd.disksize = services["disksize"]
-
-        if domainid:
-            cmd.domainid = domainid
-
-        if "storagetype" in services:
-            cmd.storagetype = services["storagetype"]
-
-        return DiskOffering(apiclient.createDiskOffering(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Disk offering"""
-        cmd = deleteDiskOffering.deleteDiskOfferingCmd()
-        cmd.id = self.id
-        apiclient.deleteDiskOffering(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all available disk offerings."""
-
-        cmd = listDiskOfferings.listDiskOfferingsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listDiskOfferings(cmd))
-
-
-class NetworkOffering:
-    """Manage network offerings cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, **kwargs):
-        """Create network offering"""
-
-        cmd = createNetworkOffering.createNetworkOfferingCmd()
-        cmd.displaytext = "-".join([services["displaytext"], random_gen()])
-        cmd.name = "-".join([services["name"], random_gen()])
-        cmd.guestiptype = services["guestiptype"]
-        cmd.supportedservices = ''
-        if "supportedservices" in services:
-            cmd.supportedservices = services["supportedservices"]
-        cmd.traffictype = services["traffictype"]
-
-        if "useVpc" in services:
-            cmd.useVpc = services["useVpc"]
-        cmd.serviceproviderlist = []
-        if "serviceProviderList" in services:
-            for service, provider in services["serviceProviderList"].items():
-                cmd.serviceproviderlist.append({
-                                            'service': service,
-                                            'provider': provider
-                                           })
-        if "serviceCapabilityList" in services:
-            cmd.servicecapabilitylist = []
-            for service, capability in services["serviceCapabilityList"].items():
-                for ctype, value in capability.items():
-                    cmd.servicecapabilitylist.append({
-                                            'service': service,
-                                            'capabilitytype': ctype,
-                                            'capabilityvalue': value
-                                           })
-        if "specifyVlan" in services:
-            cmd.specifyVlan = services["specifyVlan"]
-        if "specifyIpRanges" in services:
-            cmd.specifyIpRanges = services["specifyIpRanges"]
-
-        if "egress_policy" in services:
-            cmd.egressdefaultpolicy = services["egress_policy"]
-
-        cmd.availability = 'Optional'
-
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-
-        return NetworkOffering(apiclient.createNetworkOffering(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete network offering"""
-        cmd = deleteNetworkOffering.deleteNetworkOfferingCmd()
-        cmd.id = self.id
-        apiclient.deleteNetworkOffering(cmd)
-        return
-
-    def update(self, apiclient, **kwargs):
-        """Lists all available network offerings."""
-
-        cmd = updateNetworkOffering.updateNetworkOfferingCmd()
-        cmd.id = self.id
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.updateNetworkOffering(cmd))
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all available network offerings."""
-
-        cmd = listNetworkOfferings.listNetworkOfferingsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listNetworkOfferings(cmd))
-
-
-class SnapshotPolicy:
-    """Manage snapshot policies"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, volumeid, services):
-        """Create Snapshot policy"""
-        cmd = createSnapshotPolicy.createSnapshotPolicyCmd()
-        cmd.intervaltype = services["intervaltype"]
-        cmd.maxsnaps = services["maxsnaps"]
-        cmd.schedule = services["schedule"]
-        cmd.timezone = services["timezone"]
-        cmd.volumeid = volumeid
-        return SnapshotPolicy(apiclient.createSnapshotPolicy(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Snapshot policy"""
-        cmd = deleteSnapshotPolicies.deleteSnapshotPoliciesCmd()
-        cmd.id = self.id
-        apiclient.deleteSnapshotPolicies(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists snapshot policies."""
-
-        cmd = listSnapshotPolicies.listSnapshotPoliciesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listSnapshotPolicies(cmd))
-
-
-class LoadBalancerRule:
-    """Manage Load Balancer rule"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, ipaddressid=None, accountid=None,
-               networkid=None, vpcid=None, projectid=None, domainid=None):
-        """Create Load balancing Rule"""
-
-        cmd = createLoadBalancerRule.createLoadBalancerRuleCmd()
-
-        if ipaddressid:
-            cmd.publicipid = ipaddressid
-        elif "ipaddressid" in services:
-            cmd.publicipid = services["ipaddressid"]
-
-        if accountid:
-            cmd.account = accountid
-        elif "account" in services:
-            cmd.account = services["account"]
-
-        if domainid:
-            cmd.domainid = domainid
-
-        if vpcid:
-            cmd.vpcid = vpcid
-        cmd.name = services["name"]
-        cmd.algorithm = services["alg"]
-        cmd.privateport = services["privateport"]
-        cmd.publicport = services["publicport"]
-
-        if "openfirewall" in services:
-            cmd.openfirewall = services["openfirewall"]
-
-        if projectid:
-            cmd.projectid = projectid
-
-        if networkid:
-            cmd.networkid = networkid
-        return LoadBalancerRule(apiclient.createLoadBalancerRule(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete load balancing rule"""
-        cmd = deleteLoadBalancerRule.deleteLoadBalancerRuleCmd()
-        cmd.id = self.id
-        apiclient.deleteLoadBalancerRule(cmd)
-        return
-
-    def assign(self, apiclient, vms):
-        """Assign virtual machines to load balancing rule"""
-        cmd = assignToLoadBalancerRule.assignToLoadBalancerRuleCmd()
-        cmd.id = self.id
-        cmd.virtualmachineids = [str(vm.id) for vm in vms]
-        apiclient.assignToLoadBalancerRule(cmd)
-        return
-
-    def remove(self, apiclient, vms):
-        """Remove virtual machines from load balancing rule"""
-        cmd = removeFromLoadBalancerRule.removeFromLoadBalancerRuleCmd()
-        cmd.id = self.id
-        cmd.virtualmachineids = [str(vm.id) for vm in vms]
-        apiclient.removeFromLoadBalancerRule(cmd)
-        return
-
-    def update(self, apiclient, algorithm=None, description=None, name=None, **kwargs):
-        """Updates the load balancing rule"""
-        cmd = updateLoadBalancerRule.updateLoadBalancerRuleCmd()
-        cmd.id = self.id
-        if algorithm:
-            cmd.algorithm = algorithm
-        if description:
-            cmd.description = description
-        if name:
-            cmd.name = name
-
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return apiclient.updateLoadBalancerRule(cmd)
-
-    def createSticky(self, apiclient, methodname, name, description=None, param=None):
-        """Creates a sticky policy for the LB rule"""
-
-        cmd = createLBStickinessPolicy.createLBStickinessPolicyCmd()
-        cmd.lbruleid = self.id
-        cmd.methodname = methodname
-        cmd.name = name
-        if description:
-            cmd.description = description
-        if param:
-            cmd.param = []
-            for name, value in param.items():
-                cmd.param.append({'name': name, 'value': value})
-        return apiclient.createLBStickinessPolicy(cmd)
-
-    def deleteSticky(self, apiclient, id):
-        """Deletes stickyness policy"""
-
-        cmd = deleteLBStickinessPolicy.deleteLBStickinessPolicyCmd()
-        cmd.id = id
-        return apiclient.deleteLBStickinessPolicy(cmd)
-
-    @classmethod
-    def listStickyPolicies(cls, apiclient, lbruleid, **kwargs):
-        """Lists stickiness policies for load balancing rule"""
-
-        cmd = listLBStickinessPolicies.listLBStickinessPoliciesCmd()
-        cmd.lbruleid = lbruleid
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return apiclient.listLBStickinessPolicies(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Load balancing rules matching criteria"""
-
-        cmd = listLoadBalancerRules.listLoadBalancerRulesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listLoadBalancerRules(cmd))
-
-
-class Cluster:
-    """Manage Cluster life cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, zoneid=None, podid=None):
-        """Create Cluster"""
-        cmd = addCluster.addClusterCmd()
-        cmd.clustertype = services["clustertype"]
-        cmd.hypervisor = apiclient.hypervisor
-
-        if zoneid:
-            cmd.zoneid = zoneid
-        else:
-            cmd.zoneid = services["zoneid"]
-
-        if podid:
-            cmd.podid = podid
-        else:
-            cmd.podid = services["podid"]
-
-        if "username" in services:
-            cmd.username = services["username"]
-        if "password" in services:
-            cmd.password = services["password"]
-        if "url" in services:
-            cmd.url = services["url"]
-        if "clustername" in services:
-            cmd.clustername = services["clustername"]
-
-        return Cluster(apiclient.addCluster(cmd)[0].__dict__)
-
-    def delete(self, apiclient):
-        """Delete Cluster"""
-        cmd = deleteCluster.deleteClusterCmd()
-        cmd.id = self.id
-        apiclient.deleteCluster(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Clusters matching criteria"""
-
-        cmd = listClusters.listClustersCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listClusters(cmd))
-
-
-class Host:
-    """Manage Host life cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, cluster, services, zoneid=None, podid=None):
-        """Create Host in cluster"""
-
-        cmd = addHost.addHostCmd()
-        cmd.hypervisor = apiclient.hypervisor
-        cmd.url = services["url"]
-        cmd.clusterid = cluster.id
-
-        if zoneid:
-            cmd.zoneid = zoneid
-        else:
-            cmd.zoneid = services["zoneid"]
-
-        if podid:
-            cmd.podid = podid
-        else:
-            cmd.podid = services["podid"]
-
-        if "clustertype" in services:
-            cmd.clustertype = services["clustertype"]
-        if "username" in services:
-            cmd.username = services["username"]
-        if "password" in services:
-            cmd.password = services["password"]
-
-        # Add host
-        host = apiclient.addHost(cmd)
-
-        if isinstance(host, list):
-            return Host(host[0].__dict__)
-
-    def delete(self, apiclient):
-        """Delete Host"""
-        # Host must be in maintenance mode before deletion
-        cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
-        cmd.id = self.id
-        apiclient.prepareHostForMaintenance(cmd)
-        time.sleep(30)
-
-        cmd = deleteHost.deleteHostCmd()
-        cmd.id = self.id
-        apiclient.deleteHost(cmd)
-        return
-
-    def enableMaintenance(self, apiclient):
-        """enables maintenance mode Host"""
-
-        cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
-        cmd.id = self.id
-        return apiclient.prepareHostForMaintenance(cmd)
-
-    @classmethod
-    def enableMaintenance(cls, apiclient, id):
-        """enables maintenance mode Host"""
-
-        cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
-        cmd.id = id
-        return apiclient.prepareHostForMaintenance(cmd)
-
-    def cancelMaintenance(self, apiclient):
-        """Cancels maintenance mode Host"""
-
-        cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
-        cmd.id = self.id
-        return apiclient.cancelHostMaintenance(cmd)
-
-    @classmethod
-    def cancelMaintenance(cls, apiclient, id):
-        """Cancels maintenance mode Host"""
-
-        cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
-        cmd.id = id
-        return apiclient.cancelHostMaintenance(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Hosts matching criteria"""
-
-        cmd = listHosts.listHostsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listHosts(cmd))
-
-    @classmethod
-    def listForMigration(cls, apiclient, **kwargs):
-        """List all Hosts for migration matching criteria"""
-
-        cmd = findHostsForMigration.findHostsForMigrationCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.findHostsForMigration(cmd))
-
-
-class StoragePool:
-    """Manage Storage pools (Primary Storage)"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, clusterid=None,
-                                        zoneid=None, podid=None):
-        """Create Storage pool (Primary Storage)"""
-
-        cmd = createStoragePool.createStoragePoolCmd()
-        cmd.name = services["name"]
-
-        if podid:
-            cmd.podid = podid
-        else:
-            cmd.podid = services["podid"]
-
-        cmd.url = services["url"]
-        if clusterid:
-            cmd.clusterid = clusterid
-        elif "clusterid" in services:
-            cmd.clusterid = services["clusterid"]
-
-        if zoneid:
-            cmd.zoneid = zoneid
-        else:
-            cmd.zoneid = services["zoneid"]
-
-        return StoragePool(apiclient.createStoragePool(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Storage pool (Primary Storage)"""
-
-        # Storage pool must be in maintenance mode before deletion
-        cmd = enableStorageMaintenance.enableStorageMaintenanceCmd()
-        cmd.id = self.id
-        apiclient.enableStorageMaintenance(cmd)
-        time.sleep(30)
-        cmd = deleteStoragePool.deleteStoragePoolCmd()
-        cmd.id = self.id
-        apiclient.deleteStoragePool(cmd)
-        return
-
-    def enableMaintenance(self, apiclient):
-        """enables maintenance mode Storage pool"""
-
-        cmd = enableStorageMaintenance.enableStorageMaintenanceCmd()
-        cmd.id = self.id
-        return apiclient.enableStorageMaintenance(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all storage pools matching criteria"""
-
-        cmd = listStoragePools.listStoragePoolsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listStoragePools(cmd))
-
-    @classmethod
-    def listForMigration(cls, apiclient, **kwargs):
-        """List all storage pools for migration matching criteria"""
-
-        cmd = findStoragePoolsForMigration.findStoragePoolsForMigrationCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.findStoragePoolsForMigration(cmd))
-
-class Network:
-    """Manage Network pools"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, accountid=None, domainid=None,
-               networkofferingid=None, projectid=None,
-               subdomainaccess=None, zoneid=None,
-               gateway=None, netmask=None, vpcid=None, aclid=None):
-        """Create Network for account"""
-        cmd = createNetwork.createNetworkCmd()
-        cmd.name = services["name"]
-        cmd.displaytext = services["displaytext"]
-
-        if networkofferingid:
-            cmd.networkofferingid = networkofferingid
-        elif "networkoffering" in services:
-            cmd.networkofferingid = services["networkoffering"]
-
-        if zoneid:
-            cmd.zoneid = zoneid
-        elif "zoneid" in services:
-            cmd.zoneid = services["zoneid"]
-
-        if subdomainaccess is not None:
-            cmd.subdomainaccess = subdomainaccess
-
-        if gateway:
-            cmd.gateway = gateway
-        elif "gateway" in services:
-            cmd.gateway = services["gateway"]
-        if netmask:
-            cmd.netmask = netmask
-        elif "netmask" in services:
-            cmd.netmask = services["netmask"]
-        if "startip" in services:
-            cmd.startip = services["startip"]
-        if "endip" in services:
-            cmd.endip = services["endip"]
-        if "vlan" in services:
-            cmd.vlan = services["vlan"]
-        if "acltype" in services:
-            cmd.acltype = services["acltype"]
-
-        if accountid:
-            cmd.account = accountid
-        if domainid:
-            cmd.domainid = domainid
-        if projectid:
-            cmd.projectid = projectid
-        if vpcid:
-            cmd.vpcid = vpcid
-        if aclid:
-            cmd.aclid = aclid
-        return Network(apiclient.createNetwork(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Account"""
-
-        cmd = deleteNetwork.deleteNetworkCmd()
-        cmd.id = self.id
-        apiclient.deleteNetwork(cmd)
-
-    def update(self, apiclient, **kwargs):
-        """Updates network with parameters passed"""
-
-        cmd = updateNetwork.updateNetworkCmd()
-        cmd.id = self.id
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.updateNetwork(cmd))
-
-    def restart(self, apiclient, cleanup=None):
-        """Restarts the network"""
-
-        cmd = restartNetwork.restartNetworkCmd()
-        cmd.id = self.id
-        if cleanup:
-            cmd.cleanup = cleanup
-        return(apiclient.restartNetwork(cmd))
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Networks matching criteria"""
-
-        cmd = listNetworks.listNetworksCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listNetworks(cmd))
-
-
-class NetworkACL:
-    """Manage Network ACL lifecycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, networkid=None, protocol=None,
-               number=None, aclid=None, action='Allow', traffictype=None, cidrlist=[]):
-        """Create network ACL rules(Ingress/Egress)"""
-
-        cmd = createNetworkACL.createNetworkACLCmd()
-        if "networkid" in services:
-            cmd.networkid = services["networkid"]
-        elif networkid:
-            cmd.networkid = networkid
-
-        if "protocol" in services:
-            cmd.protocol = services["protocol"]
-            if services["protocol"] == 'ICMP':
-                cmd.icmptype = -1
-                cmd.icmpcode = -1
-        elif protocol:
-            cmd.protocol = protocol
-
-        if "startport" in services:
-            cmd.startport = services["startport"]
-        if "endport" in services:
-            cmd.endport = services["endport"]
-
-        if "cidrlist" in services:
-            cmd.cidrlist = services["cidrlist"]
-        elif cidrlist:
-            cmd.cidrlist = cidrlist
-
-        if "traffictype" in services:
-            cmd.traffictype = services["traffictype"]
-        elif traffictype:
-            cmd.traffictype = traffictype
-
-        if "action" in services:
-            cmd.action = services["action"]
-        elif action:
-            cmd.action = action
-
-        if "number" in services:
-            cmd.number = services["number"]
-        elif number:
-            cmd.number = number
-
-        if "aclid" in services:
-            cmd.aclid = services["aclid"]
-        elif aclid:
-            cmd.aclid = aclid
-
-        # Defaulted to Ingress
-        return NetworkACL(apiclient.createNetworkACL(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete network acl"""
-
-        cmd = deleteNetworkACL.deleteNetworkACLCmd()
-        cmd.id = self.id
-        return apiclient.deleteNetworkACL(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List Network ACLs"""
-
-        cmd = listNetworkACLs.listNetworkACLsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listNetworkACLs(cmd))
-
-
-class NetworkACLList:
-    """Manage Network ACL lists lifecycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, name=None, description=None, vpcid=None):
-        """Create network ACL container list"""
-
-        cmd = createNetworkACLList.createNetworkACLListCmd()
-        if "name" in services:
-            cmd.name = services["name"]
-        elif name:
-            cmd.name = name
-
-        if "description" in services:
-            cmd.description = services["description"]
-        elif description:
-            cmd.description = description
-
-        if "vpcid" in services:
-            cmd.vpcid = services["vpcid"]
-        elif vpcid:
-            cmd.vpcid = vpcid
-
-        return NetworkACLList(apiclient.createNetworkACLList(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete network acl list"""
-
-        cmd = deleteNetworkACLList.deleteNetworkACLListCmd()
-        cmd.id = self.id
-        return apiclient.deleteNetworkACLList(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List Network ACL lists"""
-
-        cmd = listNetworkACLLists.listNetworkACLListsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listNetworkACLLists(cmd))
-
-
-class Vpn:
-    """Manage VPN life cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, publicipid, account=None, domainid=None,
-                        projectid=None, networkid=None, vpcid=None):
-        """Create VPN for Public IP address"""
-        cmd = createRemoteAccessVpn.createRemoteAccessVpnCmd()
-        cmd.publicipid = publicipid
-        if account:
-            cmd.account = account
-        if domainid:
-            cmd.domainid = domainid
-        if projectid:
-            cmd.projectid = projectid
-        if networkid:
-            cmd.networkid = networkid
-        if vpcid:
-            cmd.vpcid = vpcid
-        return Vpn(apiclient.createRemoteAccessVpn(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete remote VPN access"""
-
-        cmd = deleteRemoteAccessVpn.deleteRemoteAccessVpnCmd()
-        cmd.publicipid = self.publicipid
-        apiclient.deleteRemoteAccessVpn(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all VPN matching criteria"""
-
-        cmd = listRemoteAccessVpns.listRemoteAccessVpnsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listRemoteAccessVpns(cmd))
-
-
-class VpnUser:
-    """Manage VPN user"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, username, password, account=None, domainid=None,
-               projectid=None, rand_name=True):
-        """Create VPN user"""
-        cmd = addVpnUser.addVpnUserCmd()
-        cmd.username = "-".join([username,
-                                 random_gen()]) if rand_name else username
-        cmd.password = password
-
-        if account:
-            cmd.account = account
-        if domainid:
-            cmd.domainid = domainid
-        if projectid:
-            cmd.projectid = projectid
-        return VpnUser(apiclient.addVpnUser(cmd).__dict__)
-
-    def delete(self, apiclient, projectid=None):
-        """Remove VPN user"""
-
-        cmd = removeVpnUser.removeVpnUserCmd()
-        cmd.username = self.username
-        if projectid:
-            cmd.projectid = projectid
-        else:
-            cmd.account = self.account
-            cmd.domainid = self.domainid
-        apiclient.removeVpnUser(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all VPN Users matching criteria"""
-
-        cmd = listVpnUsers.listVpnUsersCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listVpnUsers(cmd))
-
-
-class Zone:
-    """Manage Zone"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, domainid=None):
-        """Create zone"""
-        cmd = createZone.createZoneCmd()
-        cmd.dns1 = services["dns1"]
-        cmd.internaldns1 = services["internaldns1"]
-        cmd.name = services["name"]
-        cmd.networktype = services["networktype"]
-
-        if "dns2" in services:
-            cmd.dns2 = services["dns2"]
-        if "internaldns2" in services:
-            cmd.internaldns2 = services["internaldns2"]
-        if domainid:
-            cmd.domainid = domainid
-
-        return Zone(apiclient.createZone(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Zone"""
-
-        cmd = deleteZone.deleteZoneCmd()
-        cmd.id = self.id
-        apiclient.deleteZone(cmd)
-
-    def update(self, apiclient, **kwargs):
-        """Update the zone"""
-
-        cmd = updateZone.updateZoneCmd()
-        cmd.id = self.id
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return apiclient.updateZone(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Zones matching criteria"""
-
-        cmd = listZones.listZonesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listZones(cmd))
-
-
-class Pod:
-    """Manage Pod"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services):
-        """Create Pod"""
-        cmd = createPod.createPodCmd()
-        cmd.gateway = services["gateway"]
-        cmd.netmask = services["netmask"]
-        cmd.name = services["name"]
-        cmd.startip = services["startip"]
-        cmd.endip = services["endip"]
-        cmd.zoneid = services["zoneid"]
-
-        return Pod(apiclient.createPod(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Pod"""
-
-        cmd = deletePod.deletePodCmd()
-        cmd.id = self.id
-        apiclient.deletePod(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        "Returns a default pod for specified zone"
-
-        cmd = listPods.listPodsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return apiclient.listPods(cmd)
-
-
-class PublicIpRange:
-    """Manage VlanIpRange"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services):
-        """Create VlanIpRange"""
-
-        cmd = createVlanIpRange.createVlanIpRangeCmd()
-        cmd.gateway = services["gateway"]
-        cmd.netmask = services["netmask"]
-        cmd.forvirtualnetwork = services["forvirtualnetwork"]
-        cmd.startip = services["startip"]
-        cmd.endip = services["endip"]
-        cmd.zoneid = services["zoneid"]
-        cmd.podid = services["podid"]
-        cmd.vlan = services["vlan"]
-
-        return PublicIpRange(apiclient.createVlanIpRange(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete VlanIpRange"""
-
-        cmd = deleteVlanIpRange.deleteVlanIpRangeCmd()
-        cmd.id = self.vlan.id
-        apiclient.deleteVlanIpRange(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all VLAN IP ranges."""
-
-        cmd = listVlanIpRanges.listVlanIpRangesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listVlanIpRanges(cmd))
-
-    @classmethod
-    def dedicate(cls, apiclient, id, account=None, domainid=None, projectid=None):
-        """Dedicate VLAN IP range"""
-
-        cmd = dedicatePublicIpRange.dedicatePublicIpRangeCmd()
-        cmd.id = id
-        cmd.account = account
-        cmd.domainid = domainid
-        cmd.projectid = projectid
-        return PublicIpRange(apiclient.dedicatePublicIpRange(cmd).__dict__)
-
-    def release(self, apiclient):
-        """Release VLAN IP range"""
-
-        cmd = releasePublicIpRange.releasePublicIpRangeCmd()
-        cmd.id = self.vlan.id
-        return apiclient.releasePublicIpRange(cmd)
-
-
-class PortablePublicIpRange:
-    """Manage portable public Ip Range"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services):
-        """Create portable public Ip Range"""
-
-        cmd = createPortableIpRange.createPortableIpRangeCmd()
-        cmd.gateway = services["gateway"]
-        cmd.netmask = services["netmask"]
-        cmd.startip = services["startip"]
-        cmd.endip = services["endip"]
-        cmd.regionid = services["regionid"]
-
-        if "vlan" in services:
-            cmd.vlan = services["vlan"]
-
-        return PortablePublicIpRange(apiclient.createPortableIpRange(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete portable IpRange"""
-
-        cmd = deletePortableIpRange.deletePortableIpRangeCmd()
-        cmd.id = self.id
-        apiclient.deletePortableIpRange(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all portable public IP ranges."""
-
-        cmd = listPortableIpRanges.listPortableIpRangesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listPortableIpRanges(cmd))
-
-class SecondaryStagingStore:
-    """Manage Staging Store"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, url, provider, services=None):
-        """Create Staging Storage"""
-        cmd = createSecondaryStagingStore.createSecondaryStagingStoreCmd()
-        cmd.url = url
-        cmd.provider = provider
-        if services:
-            if "zoneid" in services:
-                cmd.zoneid = services["zoneid"]
-            if "details" in services:
-                cmd.details = services["details"]
-            if "scope" in services:
-                cmd.scope = services["scope"]
-
-        return SecondaryStagingStore(apiclient.createSecondaryStagingStore(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Staging Storage"""
-        cmd = deleteSecondaryStagingStore.deleteSecondaryStagingStoreCmd()
-        cmd.id = self.id
-        apiclient.deleteSecondaryStagingStore(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        cmd = listSecondaryStagingStores.listSecondaryStagingStoresCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listSecondaryStagingStores(cmd))
-
-
-class ImageStore:
-    """Manage image stores"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, url, provider, services=None):
-        """Add Image Store"""
-        cmd = addImageStore.addImageStoreCmd()
-        cmd.url = url
-        cmd.provider = provider
-        if services:
-            if "zoneid" in services:
-                cmd.zoneid = services["zoneid"]
-            if "details" in services:
-                cmd.details = services["details"]
-            if "scope" in services:
-                cmd.scope = services["scope"]
-
-        return ImageStore(apiclient.addImageStore(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Image Store"""
-        cmd = deleteImageStore.deleteImageStoreCmd()
-        cmd.id = self.id
-        apiclient.deleteImageStore(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        cmd = listImageStores.listImageStoresCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listImageStores(cmd))
-
-
-class PhysicalNetwork:
-    """Manage physical network storage"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, zoneid, domainid=None):
-        """Create physical network"""
-        cmd = createPhysicalNetwork.createPhysicalNetworkCmd()
-
-        cmd.name = services["name"]
-        cmd.zoneid = zoneid
-        if domainid:
-            cmd.domainid = domainid
-        return PhysicalNetwork(apiclient.createPhysicalNetwork(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Physical Network"""
-
-        cmd = deletePhysicalNetwork.deletePhysicalNetworkCmd()
-        cmd.id = self.id
-        apiclient.deletePhysicalNetwork(cmd)
-
-    def update(self, apiclient, **kwargs):
-        """Update Physical network state"""
-
-        cmd = updatePhysicalNetwork.updatePhysicalNetworkCmd()
-        cmd.id = self.id
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return apiclient.updatePhysicalNetwork(cmd)
-
-    def addTrafficType(self, apiclient, type):
-        """Add Traffic type to Physical network"""
-
-        cmd = addTrafficType.addTrafficTypeCmd()
-        cmd.physicalnetworkid = self.id
-        cmd.traffictype = type
-        return apiclient.addTrafficType(cmd)
-
-    @classmethod
-    def dedicate(cls, apiclient, vlanrange, physicalnetworkid, account=None, domainid=None, projectid=None):
-        """Dedicate guest vlan range"""
-
-        cmd = dedicateGuestVlanRange.dedicateGuestVlanRangeCmd()
-        cmd.vlanrange = vlanrange
-        cmd.physicalnetworkid = physicalnetworkid
-        cmd.account = account
-        cmd.domainid = domainid
-        cmd.projectid = projectid
-        return PhysicalNetwork(apiclient.dedicateGuestVlanRange(cmd).__dict__)
-
-    def release(self, apiclient):
-        """Release guest vlan range"""
-
-        cmd = releaseDedicatedGuestVlanRange.releaseDedicatedGuestVlanRangeCmd()
-        cmd.id = self.id
-        return apiclient.releaseDedicatedGuestVlanRange(cmd)
-
-    @classmethod
-    def listDedicated(cls, apiclient, **kwargs):
-        """Lists all dedicated guest vlan ranges"""
-
-        cmd = listDedicatedGuestVlanRanges.listDedicatedGuestVlanRangesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return apiclient.listDedicatedGuestVlanRanges(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all physical networks"""
-
-        cmd = listPhysicalNetworks.listPhysicalNetworksCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return map(lambda pn : PhysicalNetwork(pn.__dict__), apiclient.listPhysicalNetworks(cmd))
-
-
-class SecurityGroup:
-    """Manage Security Groups"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, account=None, domainid=None,
-               description=None, projectid=None):
-        """Create security group"""
-        cmd = createSecurityGroup.createSecurityGroupCmd()
-
-        cmd.name = services["name"]
-        if account:
-            cmd.account = account
-        if domainid:
-            cmd.domainid = domainid
-        if description:
-            cmd.description = description
-        if projectid:
-            cmd.projectid = projectid
-
-        return SecurityGroup(apiclient.createSecurityGroup(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Security Group"""
-
-        cmd = deleteSecurityGroup.deleteSecurityGroupCmd()
-        cmd.id = self.id
-        apiclient.deleteSecurityGroup(cmd)
-
-    def authorize(self, apiclient, services,
-                  account=None, domainid=None, projectid=None):
-        """Authorize Ingress Rule"""
-
-        cmd = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd()
-
-        if domainid:
-            cmd.domainid = domainid
-        if account:
-            cmd.account = account
-
-        if projectid:
-            cmd.projectid = projectid
-        cmd.securitygroupid = self.id
-        cmd.protocol = services["protocol"]
-
-        if services["protocol"] == 'ICMP':
-            cmd.icmptype = -1
-            cmd.icmpcode = -1
-        else:
-            cmd.startport = services["startport"]
-            cmd.endport = services["endport"]
-
-        cmd.cidrlist = services["cidrlist"]
-        return (apiclient.authorizeSecurityGroupIngress(cmd).__dict__)
-
-    def revoke(self, apiclient, id):
-        """Revoke ingress rule"""
-
-        cmd = revokeSecurityGroupIngress.revokeSecurityGroupIngressCmd()
-        cmd.id = id
-        return apiclient.revokeSecurityGroupIngress(cmd)
-
-    def authorizeEgress(self, apiclient, services, account=None, domainid=None,
-                        projectid=None, user_secgrp_list={}):
-        """Authorize Egress Rule"""
-
-        cmd = authorizeSecurityGroupEgress.authorizeSecurityGroupEgressCmd()
-
-        if domainid:
-            cmd.domainid = domainid
-        if account:
-            cmd.account = account
-
-        if projectid:
-            cmd.projectid = projectid
-        cmd.securitygroupid = self.id
-        cmd.protocol = services["protocol"]
-
-        if services["protocol"] == 'ICMP':
-            cmd.icmptype = -1
-            cmd.icmpcode = -1
-        else:
-            cmd.startport = services["startport"]
-            cmd.endport = services["endport"]
-
-        cmd.cidrlist = services["cidrlist"]
-
-        cmd.usersecuritygrouplist = []
-        for account, group in user_secgrp_list.items():
-            cmd.usersecuritygrouplist.append({
-                                            'account': account,
-                                            'group': group
-  

<TRUNCATED>

[36/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: additional factories for entities

staticnat, vpc, vpcoffering, networkoffering, etc

All classes within factories don't include the redundant *Factory in
their naming.

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/7d4b35df
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/7d4b35df
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/7d4b35df

Branch: refs/heads/marvin-refactor
Commit: 7d4b35df83872d71266feb9ba22af48d6ed75e54
Parents: dab5ae5
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Mon Sep 30 09:51:19 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:58 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/factory/data/account.py     |  6 +-
 tools/marvin/marvin/factory/data/cluster.py     |  4 +-
 .../marvin/marvin/factory/data/diskoffering.py  |  4 +-
 .../marvin/marvin/factory/data/firewallrule.py  |  4 +-
 tools/marvin/marvin/factory/data/host.py        |  4 +-
 tools/marvin/marvin/factory/data/network.py     | 32 ++++++--
 .../marvin/factory/data/networkoffering.py      | 37 +++++++++-
 .../marvin/marvin/factory/data/securitygroup.py | 72 ++++++++++++++++++
 .../marvin/factory/data/serviceoffering.py      |  2 +-
 tools/marvin/marvin/factory/data/staticnat.py   | 16 ++++
 tools/marvin/marvin/factory/data/template.py    |  2 +-
 tools/marvin/marvin/factory/data/user.py        | 10 +--
 tools/marvin/marvin/factory/data/vm.py          | 77 +++++++++++++++++---
 tools/marvin/marvin/factory/data/vpc.py         | 35 +++++++++
 tools/marvin/marvin/factory/data/vpcoffering.py | 43 +++++++++++
 tools/marvin/marvin/factory/data/zone.py        |  4 +-
 16 files changed, 312 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/account.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/account.py b/tools/marvin/marvin/factory/data/account.py
index 97caf16..be641d6 100644
--- a/tools/marvin/marvin/factory/data/account.py
+++ b/tools/marvin/marvin/factory/data/account.py
@@ -19,7 +19,7 @@ import factory
 from marvin.factory.account import AccountFactory
 from marvin.legacy.utils import random_gen
 
-class UserAccountFactory(AccountFactory):
+class UserAccount(AccountFactory):
 
     accounttype = 0
     firstname = factory.Sequence(lambda n: random_gen())
@@ -29,10 +29,10 @@ class UserAccountFactory(AccountFactory):
     password = 'password'
 
 
-class AdminAccountFactory(UserAccountFactory):
+class AdminAccount(UserAccount):
     accounttype = 1
 
 
-class DomainAdminFactory(UserAccountFactory):
+class DomainAdmin(UserAccount):
     accounttype = 2
     domainid = None

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/cluster.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/cluster.py b/tools/marvin/marvin/factory/data/cluster.py
index c51321d..5e8c8eb 100644
--- a/tools/marvin/marvin/factory/data/cluster.py
+++ b/tools/marvin/marvin/factory/data/cluster.py
@@ -19,12 +19,12 @@ import factory
 from marvin.legacy.utils import random_gen
 from marvin.factory.cluster import ClusterFactory
 
-class XenClusterFactory(ClusterFactory):
+class XenCluster(ClusterFactory):
     clustername = factory.Sequence(lambda n: "xencluster" + random_gen())
     clustertype = "XenServer"
     hypervisor = "XenServer"
 
-class KvmClusterFactory(ClusterFactory):
+class KvmCluster(ClusterFactory):
     clustername = factory.Sequence(lambda n: "kvmcluster" + random_gen())
     clustertype = "KVM"
     hypervisor = "KVM"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/diskoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/diskoffering.py b/tools/marvin/marvin/factory/data/diskoffering.py
index 48526b8..89a48b4 100644
--- a/tools/marvin/marvin/factory/data/diskoffering.py
+++ b/tools/marvin/marvin/factory/data/diskoffering.py
@@ -19,14 +19,14 @@ import factory
 from marvin.factory.diskoffering import DiskOfferingFactory
 from marvin.legacy.utils import random_gen
 
-class SharedDiskOfferingFactory(DiskOfferingFactory):
+class SharedDiskOffering(DiskOfferingFactory):
 
     displaytext = "SharedDiskOffering"
     name = factory.Sequence(lambda n : "SharedDiskOffering" + random_gen())
     storagetype = "shared"
     disksize = 10 #MB
 
-class LocalDiskOfferingFactory(DiskOfferingFactory):
+class LocalDiskOffering(DiskOfferingFactory):
 
     displaytext = "LocalDiskOffering"
     name = factory.Sequence(lambda n : "LocalDiskOffering" + random_gen())

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/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 692450b..44cc17f 100644
--- a/tools/marvin/marvin/factory/data/firewallrule.py
+++ b/tools/marvin/marvin/factory/data/firewallrule.py
@@ -17,13 +17,13 @@
 
 from marvin.factory.firewall import FirewallFactory
 
-class SshFirewallRuleFactory(FirewallFactory):
+class SshFirewallRule(FirewallFactory):
     protocol = 'tcp'
     startport = 22
     endport = 22
     cidrlist = '0.0.0.0/0'
 
-class HttpFirewallRuleFactory(FirewallFactory):
+class HttpFirewallRule(FirewallFactory):
     protocol = 'tcp'
     startport = 80
     endport = 80

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/host.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/host.py b/tools/marvin/marvin/factory/data/host.py
index 726ceb7..02d2433 100644
--- a/tools/marvin/marvin/factory/data/host.py
+++ b/tools/marvin/marvin/factory/data/host.py
@@ -17,14 +17,14 @@
 
 from marvin.factory.host import HostFactory
 
-class XenserverHostFactory(HostFactory):
+class XenserverHost(HostFactory):
 
     hypervisor = 'XenServer'
     password = 'password'
     username = 'root'
 
 
-class KvmHostFactory(HostFactory):
+class KvmHost(HostFactory):
 
     hypervisor = 'KVM'
     password = 'password'

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/network.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/network.py b/tools/marvin/marvin/factory/data/network.py
index ad6101c..50c0086 100644
--- a/tools/marvin/marvin/factory/data/network.py
+++ b/tools/marvin/marvin/factory/data/network.py
@@ -18,31 +18,47 @@
 import factory
 from marvin.legacy.utils import random_gen
 from marvin.factory.network import NetworkFactory
-from marvin.factory.data.networkoffering import DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory
-from marvin.factory.data.networkoffering import DefaultSharedNetworkOfferingFactory
+from marvin.factory.data.networkoffering import DefaultIsolatedNetworkOfferingWithSourceNatService
+from marvin.factory.data.networkoffering import DefaultSharedNetworkOffering
+from marvin.factory.data.networkoffering import DefaultIsolatedNetworkOfferingForVpc
 
-class GuestIsolatedNetworkFactory(NetworkFactory):
+class GuestIsolatedNetwork(NetworkFactory):
 
     displaytext = factory.Sequence(lambda n: 'GuestIsolatedNetwork-%s' % random_gen())
     name = factory.Sequence(lambda n: 'GuestIsolatedNetwork-%s' % random_gen())
     networkoffering =\
     factory.SubFactory(
-        DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory,
+        DefaultIsolatedNetworkOfferingWithSourceNatService,
         apiclient=factory.SelfAttribute('..apiclient'),
         name=factory.Sequence(lambda n: 'GuestIsolatedNetworkOffering-%s' % random_gen()),
     )
     networkofferingid = factory.LazyAttribute(lambda no: no.networkoffering.id if no.networkoffering else no.networkoffering)
     zoneid = None
 
-class SharedNetworkFactory(NetworkFactory):
+class SharedNetwork(NetworkFactory):
 
     displaytext = factory.Sequence(lambda n: 'SharedNetwork-%s' % random_gen())
-    name = factory.Sequence(lambda n: 'SharedNetwork-%d' % random_gen())
+    name = factory.Sequence(lambda n: 'SharedNetwork-%s' % random_gen())
     networkoffering = \
         factory.SubFactory(
-            DefaultSharedNetworkOfferingFactory,
+            DefaultSharedNetworkOffering,
             apiclient=factory.SelfAttribute('..apiclient'),
             name=factory.Sequence(lambda n: 'SharedNetworkOffering-%s' % random_gen())
         )
-    networkofferingid = factory.LazyAttribute(lambda no: no.networkoffering.id if not no.networkoffering else no.networkoffering)
+    networkofferingid = factory.LazyAttribute(lambda no: no.networkoffering.id if no.networkoffering else no.networkoffering)
+    zoneid = None
+
+class DefaultVpcNetwork(NetworkFactory):
+
+    displaytext = factory.Sequence(lambda n: 'DefaultVpcNetwork-%s' % random_gen())
+    name = factory.Sequence(lambda n: 'DefaultVpcNetwork-%s' % random_gen())
+    networkoffering = \
+        factory.SubFactory(
+            DefaultIsolatedNetworkOfferingForVpc,
+            apiclient=factory.SelfAttribute('..apiclient'),
+            name=factory.Sequence(lambda n: 'DefaultVpcNetwork-%s' % random_gen())
+        )
+    gateway = '10.0.0.1'
+    netmask = '255.255.255.192'
+    networkofferingid = factory.LazyAttribute(lambda no: no.networkoffering.id if no.networkoffering else no.networkoffering)
     zoneid = None
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/networkoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/networkoffering.py b/tools/marvin/marvin/factory/data/networkoffering.py
index 5b64cf6..1a65f85 100644
--- a/tools/marvin/marvin/factory/data/networkoffering.py
+++ b/tools/marvin/marvin/factory/data/networkoffering.py
@@ -20,7 +20,7 @@ from marvin.factory.networkoffering import NetworkOfferingFactory
 from marvin.legacy.utils import random_gen
 
 
-class DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory(NetworkOfferingFactory):
+class DefaultIsolatedNetworkOfferingWithSourceNatService(NetworkOfferingFactory):
     #FIXME: Service Capability Lists with CapabilityTypes (ElasticIP, RvR etc) needs handling
 
     displaytext = factory.Sequence(lambda n : "DefaultIsolatedNetworkOfferingWithSourceNatService" + random_gen())
@@ -51,7 +51,7 @@ class DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory(NetworkOfferingF
         self.update(apiclient=self.apiclient, id=self.id, state='Enabled')
 
 
-class DefaultSharedNetworkOfferingWithSGServiceFactory(NetworkOfferingFactory):
+class DefaultSharedNetworkOfferingWithSGService(NetworkOfferingFactory):
 
     displaytext = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingWithSGService" + random_gen())
     name = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingWithSGService" + random_gen())
@@ -86,7 +86,7 @@ class DefaultSharedNetworkOfferingWithSGServiceFactory(NetworkOfferingFactory):
         self.update(apiclient=self.apiclient, id=self.id, state='Enabled')
 
 
-class DefaultSharedNetworkOfferingFactory(NetworkOfferingFactory):
+class DefaultSharedNetworkOffering(NetworkOfferingFactory):
 
     displaytext = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingFactory-%s" % random_gen())
     name = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingFactory-%s" % random_gen())
@@ -115,3 +115,34 @@ class DefaultSharedNetworkOfferingFactory(NetworkOfferingFactory):
         if not create:
             return
         self.update(apiclient=self.apiclient, id=self.id, state='Enabled')
+
+
+class DefaultIsolatedNetworkOfferingForVpc(NetworkOfferingFactory):
+
+    displaytext = factory.Sequence(lambda n : "DefaultIsolatedNetworkOfferingForVpc-%s" % random_gen())
+    name = factory.Sequence(lambda n : "DefaultIsolatedNetworkOfferingForVpc-%s" % random_gen())
+    availability = "Optional"
+    supportedservices = "SourceNat,Dns,Lb,PortForwarding,StaticNat,NetworkACL,Dhcp,Vpn,UserData"
+    guestiptype = "Isolated"
+    traffictype = "GUEST"
+
+    specifyVlan = False
+    specifyIpRanges = False
+    isPersistent = False
+    conserveMode = False
+
+    serviceProviderList = []
+    for service in map(lambda l: l.strip(' '), supportedservices.split(',')):
+        serviceProviderList.append(
+            {
+                'service': service,
+                'provider': 'VpcVirtualRouter'
+            }
+        )
+
+    # enable the offering post generation
+    @factory.post_generation
+    def enable(self, create, extracted, **kwargs):
+        if not create:
+            return
+        self.update(apiclient=self.apiclient, id=self.id, state='Enabled')

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/securitygroup.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/securitygroup.py b/tools/marvin/marvin/factory/data/securitygroup.py
new file mode 100644
index 0000000..1e6d375
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/securitygroup.py
@@ -0,0 +1,72 @@
+# 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.
+
+import factory
+from marvin.legacy.utils import random_gen
+from marvin.entity.securitygroup import SecurityGroup
+from marvin.factory.securitygroup import SecurityGroupFactory
+
+class SecurityGroupSshIngress(SecurityGroupFactory):
+    """
+    Allow port 22 (ingress) into the guest
+    """
+    name = factory.Sequence(lambda n: 'SshSecurityGroupIngress-' + random_gen())
+    protocol = 'tcp'
+    cidrlist = '0.0.0.0/0'
+    startport = 22
+    endport = 22
+
+    @factory.post_generation
+    def authorizeIngress(self, create, extracted, **kwargs):
+        if not create:
+            return
+        sg = SecurityGroup.list(name=self.name)
+        if not sg:
+            self.authorizeSecurityGroupIngress(
+                self.apiclient,
+                name=self.name,
+                protocol=self.protocol,
+                cidrlist=self.cidrlist,
+                startport=self.startport,
+                endport=self.endport
+            )
+
+
+class SecurityGroupSshEgress(SecurityGroupFactory):
+    """
+    Allow port 22 (egress) out of the guest
+    """
+    name = factory.Sequence(lambda n: 'SshSecurityGroupEgress-' + random_gen())
+    protocol = 'tcp'
+    cidrlist = '0.0.0.0/0'
+    startport = 22
+    endport = 22
+
+    @factory.post_generation
+    def authorizeEgress(self, create, extracted, **kwargs):
+        if not create:
+            return
+        sg = SecurityGroup.list(name=self.name)
+        if not sg:
+            self.authorizeSecurityGroupEgress(
+                self.apiclient,
+                name=self.name,
+                protocol=self.protocol,
+                cidrlist=self.cidrlist,
+                startport=self.startport,
+                endport=self.endport
+            )

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/serviceoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/serviceoffering.py b/tools/marvin/marvin/factory/data/serviceoffering.py
index 955657e..cc62358 100644
--- a/tools/marvin/marvin/factory/data/serviceoffering.py
+++ b/tools/marvin/marvin/factory/data/serviceoffering.py
@@ -19,7 +19,7 @@ import factory
 from marvin.factory.serviceoffering import ServiceOfferingFactory
 from marvin.legacy.utils import random_gen
 
-class SmallServiceOfferingFactory(ServiceOfferingFactory):
+class SmallServiceOffering(ServiceOfferingFactory):
     cpunumber = 1
     cpuspeed = 100 #Mhz
     memory = 100 #MB

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/staticnat.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/staticnat.py b/tools/marvin/marvin/factory/data/staticnat.py
new file mode 100644
index 0000000..13a8339
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/staticnat.py
@@ -0,0 +1,16 @@
+# 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.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/template.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/template.py b/tools/marvin/marvin/factory/data/template.py
index 4c576fb..445899e 100644
--- a/tools/marvin/marvin/factory/data/template.py
+++ b/tools/marvin/marvin/factory/data/template.py
@@ -17,7 +17,7 @@
 
 from marvin.factory.template import TemplateFactory
 
-class DefaultBuiltInTemplateFactory(TemplateFactory):
+class DefaultBuiltInTemplate(TemplateFactory):
     ostype = 'CentOS 5.3 (64-bit)'
     displaytext = 'CentOS 5.3 (64-bit)'
     name = 'CentOS 5.3 (64-bit)'

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/user.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/user.py b/tools/marvin/marvin/factory/data/user.py
index d5fa456..588c294 100644
--- a/tools/marvin/marvin/factory/data/user.py
+++ b/tools/marvin/marvin/factory/data/user.py
@@ -17,17 +17,17 @@
 
 import factory
 from marvin.factory.user import UserFactory
-from marvin.factory.data.account import UserAccountFactory
+from marvin.factory.data.account import UserAccount
 from marvin.legacy.utils import random_gen
 
-class UserFactory(UserFactory):
+class User(UserFactory):
 
     firstname = factory.Sequence(lambda n: random_gen())
     lastname = factory.Sequence(lambda n: random_gen())
     email = factory.LazyAttribute(lambda e: '{0}.{1}@cloudstack.org'.format(e.firstname, e.lastname).lower())
     username = factory.Sequence(lambda n: random_gen())
     password = 'password'
-    account = factory.SubFactory(UserAccountFactory,
+    account = factory.SubFactory(UserAccount,
         apiclient=factory.SelfAttribute('..apiclient'),
         accounttype=0,
         firstname=factory.SelfAttribute('..firstname'),
@@ -37,9 +37,9 @@ class UserFactory(UserFactory):
         username=factory.SelfAttribute('..username'),
     )
 
-class AdminUserFactory(UserFactory):
+class AdminUser(UserFactory):
 
-    account = factory.SubFactory(UserAccountFactory,
+    account = factory.SubFactory(UserAccount,
         apiclient=factory.SelfAttribute('..apiclient'),
         accounttype=1,
         firstname=factory.SelfAttribute('..firstname'),

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/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 a09abe7..b9e6345 100644
--- a/tools/marvin/marvin/factory/data/vm.py
+++ b/tools/marvin/marvin/factory/data/vm.py
@@ -15,18 +15,77 @@
 # specific language governing permissions and limitations
 # under the License.
 
+import factory
 from marvin.factory.virtualmachine import VirtualMachineFactory
+from marvin.entity.ipaddress import IpAddress
+from marvin.entity.network import Network
+from marvin.factory.data.firewallrule import SshFirewallRule
+from marvin.factory.data.vpc import DefaultVpc
+from marvin.factory.data.network import DefaultVpcNetwork
 
-class VirtualMachineIsolatedNetwork(VirtualMachineFactory):
+class VirtualMachineWithStaticNat(VirtualMachineFactory):
+    """VirtualMachine in an isolated network of an advanced zone
+
+    Open a static-nat rule to connect to the guest over port 22
+    """
+
+    @factory.post_generation
+    def staticNat(self, create, extracted, **kwargs):
+        if not create:
+            return
+        ipassoc = IpAddress(
+            apiclient=self.apiclient,
+            account=self.account,
+            domainid=self.domainid,
+            zoneid=self.zoneid,
+        )
+        ssh_fwrule = SshFirewallRule(
+            apiclient=self.apiclient,
+            ipaddressid=ipassoc.id
+        )
+        ntwks = Network.list(
+            apiclient=self.apiclient,
+            account=self.account,
+            domainid=self.domainid,
+        )
+        ntwks[0].enableStaticNat(
+            apiclient=self.apiclient,
+            ipaddressid=ipassoc.id,
+            virtualmachineid=self.id,
+        )
+        self.ssh_ip = ipassoc.ipaddress
+        self.public_ip = ipassoc.ipaddress
+
+
+class VirtualMachineWithIngress(VirtualMachineFactory):
+    """VirtualMachine created in a basic zone with security groups
+
+    Allow port 22 (ingress) into the guest
     """
-    Creates a virtualmachine in an isolated network typically in an advanced zone inside a user account
+    @factory.post_generation
+    def allowIngress(self, create, extracted, **kwargs):
+        if not create:
+            return
 
-    Uses a serviceoffering of tinyInstance of the shared storage type
-    Uses a builtin template available
-    Deploys in the first zone available
+
+class VpcVirtualMachine(VirtualMachineFactory):
+    """
+    VirtualMachine within a VPC created by DefaultVPC offering
     """
 
-    apiclient = None
-    serviceofferingid = None
-    templateid = None
-    zoneid = None
+    vpc = factory.SubFactory(
+        DefaultVpc,
+        apiclient=factory.SelfAttribute('..apiclient'),
+        account=factory.SelfAttribute('..account'),
+        domainid=factory.SelfAttribute('..domainid'),
+        zoneid=factory.SelfAttribute('..zoneid')
+    )
+    ntwk = factory.SubFactory(
+        DefaultVpcNetwork,
+        apiclient=factory.SelfAttribute('..apiclient'),
+        account=factory.SelfAttribute('..account'),
+        domainid=factory.SelfAttribute('..domainid'),
+        zoneid=factory.SelfAttribute('..zoneid'),
+        vpcid=factory.SelfAttribute('..vpc.id')
+    )
+    networkid=factory.LazyAttribute(lambda n: n.ntwk.id if n else None)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/vpc.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/vpc.py b/tools/marvin/marvin/factory/data/vpc.py
new file mode 100644
index 0000000..fc0379c
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/vpc.py
@@ -0,0 +1,35 @@
+# 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.
+
+import factory
+from marvin.factory.vpc import VpcFactory
+from marvin.factory.data.vpcoffering import DefaultVpcOffering
+from marvin.legacy.utils import random_gen
+
+class DefaultVpc(VpcFactory):
+
+    name = factory.Sequence(lambda e: "DefaultVpc" + random_gen())
+    cidr = '10.0.0.1/24'
+    displaytext = name
+    zoneid = None
+    apiclient = None
+    vpcoffering = \
+        factory.SubFactory(
+            DefaultVpcOffering,
+            apiclient=factory.SelfAttribute('..apiclient')
+        )
+    vpcofferingid = factory.LazyAttribute(lambda vo: vo.vpcoffering.id if vo.vpcoffering else vo.vpcoffering)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/vpcoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/vpcoffering.py b/tools/marvin/marvin/factory/data/vpcoffering.py
new file mode 100644
index 0000000..c0040c6
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/vpcoffering.py
@@ -0,0 +1,43 @@
+# 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.
+
+import factory
+from marvin.factory.vpcoffering import VpcOfferingFactory
+from marvin.legacy.utils import random_gen
+
+class DefaultVpcOffering(VpcOfferingFactory):
+
+    apiclient = None
+    displaytext = factory.Sequence(lambda n: 'Default VPC offering' + random_gen())
+    name = factory.Sequence(lambda n: 'Default VPC offering' + random_gen())
+    supportedservices = 'SourceNat,Dns,Lb,PortForwarding,StaticNat,NetworkACL,Dhcp,Vpn,UserData'
+
+    serviceProviderList = []
+    for service in map(lambda l: l.strip(' '), supportedservices.split(',')):
+        serviceProviderList.append(
+            {
+                'service': service,
+                'provider': 'VpcVirtualRouter'
+            }
+        )
+
+    # enable the offering post generation
+    @factory.post_generation
+    def enable(self, create, extracted, **kwargs):
+        if not create:
+            return
+        self.update(id=self.id, state='Enabled')

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7d4b35df/tools/marvin/marvin/factory/data/zone.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/zone.py b/tools/marvin/marvin/factory/data/zone.py
index 67c1cb4..80cb67a 100644
--- a/tools/marvin/marvin/factory/data/zone.py
+++ b/tools/marvin/marvin/factory/data/zone.py
@@ -19,14 +19,14 @@ import factory
 from marvin.factory.zone import ZoneFactory
 from marvin.legacy.utils import random_gen
 
-class AdvancedZoneFactory(ZoneFactory):
+class AdvancedZone(ZoneFactory):
     name = factory.Sequence(lambda n: "advzone" + random_gen())
     networktype = "Advanced"
     dns1 = "8.8.8.8"
     internaldns1 = "8.8.8.8"
 
 
-class BasicZoneFactory(ZoneFactory):
+class BasicZone(ZoneFactory):
     name = factory.Sequence(lambda n: "basiczone" + random_gen())
     networktype = "Basic"
     dns1 = "8.8.8.8"


[35/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: always check for complete object identity with json

Remove check which ensured single key match for the json result with the
object response. This would return ipaddressResponse.ipaddress as a
nested object whereas the response itself is the ipaddress

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/dab5ae5e
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/dab5ae5e
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/dab5ae5e

Branch: refs/heads/marvin-refactor
Commit: dab5ae5e14c787ca56373c75cbab7ee6db336fcf
Parents: 9afab98
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Sep 18 14:31:20 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:57 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/jsonHelper.py          | 4 ----
 tools/marvin/marvin/test/test_factories.py | 6 ++----
 2 files changed, 2 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/dab5ae5e/tools/marvin/marvin/jsonHelper.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/jsonHelper.py b/tools/marvin/marvin/jsonHelper.py
index 605e06f..a395e6b 100644
--- a/tools/marvin/marvin/jsonHelper.py
+++ b/tools/marvin/marvin/jsonHelper.py
@@ -113,10 +113,6 @@ def finalizeResultObj(result, responseName, responsecls):
                                              responsecls)
         return result
     elif responsecls is not None:
-        for k, v in result.__dict__.iteritems():
-            if k in responsecls.__dict__:
-                return result
-
         attr = result.__dict__.keys()[0]
 
         value = getattr(result, attr)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/dab5ae5e/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 89d67fb..6a09303 100644
--- a/tools/marvin/marvin/test/test_factories.py
+++ b/tools/marvin/marvin/test/test_factories.py
@@ -229,11 +229,9 @@ class IpAddressFactoryTest(unittest.TestCase):
             account=accnt.name,
             domainid=accnt.domainid)
 
-        all_ips = IpAddress.listPublic(apiclient=self.apiClient)
-        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)
+        IpAddress(apiclient=self.apiClient, networkid = networks[0].id)
 
 
 class FirewallRuleFactoryTest(unittest.TestCase):
@@ -280,7 +278,7 @@ class FirewallRuleFactoryTest(unittest.TestCase):
 
         fwrule = SshFirewallRuleFactory(
             apiclient=self.apiClient,
-            ipaddressid=ipaddress.ipaddress.id
+            ipaddressid=ipaddress.id
         )
         fwrule |should_not| be(None)
         fwrule |should| be_instance_of(Firewall)


[25/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: fix imports for local deployer modules

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/4d0e53d5
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/4d0e53d5
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/4d0e53d5

Branch: refs/heads/marvin-refactor
Commit: 4d0e53d516275cbb77b2325a1b2a3b3635522695
Parents: e58cd11
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Tue Sep 10 14:27:02 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:42 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/deployAndRun.py              | 4 ++--
 tools/marvin/marvin/deployer/configGenerator.py  | 3 +--
 tools/marvin/marvin/deployer/deployDataCenter.py | 8 ++++----
 3 files changed, 7 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4d0e53d5/tools/marvin/marvin/deployAndRun.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployAndRun.py b/tools/marvin/marvin/deployAndRun.py
index d162fb3..b7485aa 100644
--- a/tools/marvin/marvin/deployAndRun.py
+++ b/tools/marvin/marvin/deployAndRun.py
@@ -15,10 +15,10 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import deployDataCenter
 import TestCaseExecuteEngine
-import sys
+from deployer import deployDataCenter
 from argparse import ArgumentParser
+
 if __name__ == "__main__":
 
     parser = ArgumentParser()

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4d0e53d5/tools/marvin/marvin/deployer/configGenerator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployer/configGenerator.py b/tools/marvin/marvin/deployer/configGenerator.py
index 3f20dfd..0e2f434 100644
--- a/tools/marvin/marvin/deployer/configGenerator.py
+++ b/tools/marvin/marvin/deployer/configGenerator.py
@@ -18,8 +18,7 @@
 import json
 import os
 from optparse import OptionParser
-import jsonHelper
-
+from marvin import jsonHelper
 
 class managementServer(object):
     def __init__(self):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4d0e53d5/tools/marvin/marvin/deployer/deployDataCenter.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployer/deployDataCenter.py b/tools/marvin/marvin/deployer/deployDataCenter.py
index 2ce8757..0c1c639 100644
--- a/tools/marvin/marvin/deployer/deployDataCenter.py
+++ b/tools/marvin/marvin/deployer/deployDataCenter.py
@@ -16,14 +16,14 @@
 # under the License.
 
 """Deploy datacenters according to a json configuration file"""
-import cloudstackException
-import cloudstackTestClient
 import logging
-from cloudstackAPI import *
+import configGenerator
 from os import path
 from time import sleep
+from cloudstackAPI import *
 from optparse import OptionParser
-from marvin.deployer import configGenerator
+from marvin import cloudstackTestClient
+from marvin import cloudstackException
 
 
 class deployDataCenters(object):


[44/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: pep8 all python files

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/f76b1029
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/f76b1029
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/f76b1029

Branch: refs/heads/marvin-refactor
Commit: f76b1029d6e55fcf949006df013d76a4fcbf5376
Parents: 3aa10ef
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Oct 2 12:05:38 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:10 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/cloudstackConnection.py |  3 ++-
 tools/marvin/marvin/codegenerator.py        | 20 +++++++++++---------
 tools/marvin/marvin/dbConnection.py         |  7 +++++--
 tools/marvin/marvin/deployAndRun.py         | 22 +++++++++++++---------
 tools/marvin/marvin/factory/data/vm.py      |  2 +-
 tools/marvin/marvin/jsonHelper.py           | 17 +++++++----------
 tools/marvin/marvin/util.py                 | 10 ++++++++--
 7 files changed, 47 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f76b1029/tools/marvin/marvin/cloudstackConnection.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py
index 1e4298e..6cd65b7 100644
--- a/tools/marvin/marvin/cloudstackConnection.py
+++ b/tools/marvin/marvin/cloudstackConnection.py
@@ -22,7 +22,8 @@ try:
     from requests import Timeout
     from requests import RequestException
 except ImportError:
-    raise Exception("requests installation not found. use pip install requests to continue")
+    raise Exception("requests installation not found. use pip install \
+            requests to continue")
 import urllib
 import base64
 import hmac

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f76b1029/tools/marvin/marvin/codegenerator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/codegenerator.py b/tools/marvin/marvin/codegenerator.py
index a736039..5ef7c41 100644
--- a/tools/marvin/marvin/codegenerator.py
+++ b/tools/marvin/marvin/codegenerator.py
@@ -21,6 +21,7 @@ from argparse import ArgumentParser
 from generate.xmltoapi import codeGenerator
 from generate.apitoentity import generate
 
+
 def get_api_cmds():
     """ Returns the API cmdlet instances
 
@@ -28,13 +29,13 @@ def get_api_cmds():
     """
     namespace = {}
     execfile('cloudstackAPI/__init__.py', namespace)
-    api_classes = __import__('cloudstackAPI', globals().update(namespace), fromlist=['*'], level=-1)
-
+    api_classes = __import__(
+        'cloudstackAPI', globals().update(namespace), fromlist=['*'], level=-1)
 
     cmdlist = map(
         lambda f: getattr(api_classes, f),
         filter(
-            lambda t: t.startswith('__') == False,
+            lambda t: t.startswith('__') is False,
             dir(api_classes)
         )
     )
@@ -45,7 +46,8 @@ def get_api_cmds():
     clslist = map(
         lambda g: getattr(g, g.__name__.split('.')[-1] + 'Cmd'),
         filter(
-            lambda h: h.__name__.split('.')[-1] not in ['baseCmd', 'baseResponse', 'cloudstackAPIClient'],
+            lambda h: h.__name__.split('.')[-1] not in [
+                'baseCmd', 'baseResponse', 'cloudstackAPIClient'],
             cmdlist
         )
     )
@@ -55,16 +57,16 @@ def get_api_cmds():
 if __name__ == "__main__":
     parser = ArgumentParser()
     parser.add_argument("-o", "--output", dest="output",
-                      help="The path to the generated code entities, default\
+                        help="The path to the generated code entities, default\
  is .")
     parser.add_argument("-s", "--specfile", dest="spec",
-                      help="The path and name of the api spec xml file,\
+                        help="The path and name of the api spec xml file,\
  default is /etc/cloud/cli/commands.xml")
     parser.add_argument("-e", "--endpoint", dest="endpoint",
-                      help="The endpoint mgmt server (with open 8096) where\
+                        help="The endpoint mgmt server (with open 8096) where\
  apis are discovered, default is localhost")
     parser.add_argument("-y", "--entity", dest="entity", action="store_true",
-                      help="Generate entity based classes")
+                        help="Generate entity based classes")
 
     options = parser.parse_args()
 
@@ -98,4 +100,4 @@ response=json' % options.endpoint
         cg.generateCodeFromJSON(endpointUrl)
 
     if options.entity:
-        generate(get_api_cmds())
\ No newline at end of file
+        generate(get_api_cmds())

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f76b1029/tools/marvin/marvin/dbConnection.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/dbConnection.py b/tools/marvin/marvin/dbConnection.py
index 98c72c5..70bd511 100644
--- a/tools/marvin/marvin/dbConnection.py
+++ b/tools/marvin/marvin/dbConnection.py
@@ -20,13 +20,16 @@ try:
     from mysql import connector
     from mysql.connector import errors
 except ImportError:
-    raise Exception("mysql-connector-python not installed. pip install mysql-connector-python to continue")
+    raise Exception(
+        "mysql-connector-python not installed. pip install \
+        mysql-connector-python to continue")
 import contextlib
 import cloudstackException
 import os
 
 
 class dbConnection(object):
+
     def __init__(self, host="localhost", port=3306, user='cloud',
                  passwd='cloud', db='cloud'):
         self.host = host
@@ -52,7 +55,7 @@ class dbConnection(object):
                 try:
                     resultRow = cursor.fetchall()
                 except errors.InterfaceError:
-                    #Raised on empty result - DML
+                    # Raised on empty result - DML
                     resultRow = []
         return resultRow
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f76b1029/tools/marvin/marvin/deployAndRun.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployAndRun.py b/tools/marvin/marvin/deployAndRun.py
index b7485aa..8bb24b3 100644
--- a/tools/marvin/marvin/deployAndRun.py
+++ b/tools/marvin/marvin/deployAndRun.py
@@ -73,20 +73,24 @@ if __name__ == "__main__":
             n = 0
             while(n < iterates):
                 engine = \
-                    TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient,
-                                                            deploy.getCfg(),
-                                                            testCaseLogFile,
-                                                            testResultLogFile)
+                    TestCaseExecuteEngine.TestCaseExecuteEngine(
+                        deploy.testClient,
+                        deploy.getCfg(
+                        ),
+                        testCaseLogFile,
+                        testResultLogFile)
                 engine.loadTestsFromFile(options.module)
                 engine.run()
                 n = n + 1
     else:
         n = 0
-        while(n<iterates):
-            engine = TestCaseExecuteEngine.TestCaseExecuteEngine(deploy.testClient,
-                                                             deploy.getCfg(),
-                                                             testCaseLogFile,
-                                                             testResultLogFile)
+        while(n < iterates):
+            engine = TestCaseExecuteEngine.TestCaseExecuteEngine(
+                deploy.testClient,
+                deploy.getCfg(
+                ),
+                testCaseLogFile,
+                testResultLogFile)
             engine.loadTestsFromDir(options.testCaseFolder)
             engine.run()
             n = n + 1

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f76b1029/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 713c9b5..3f50b52 100644
--- a/tools/marvin/marvin/factory/data/vm.py
+++ b/tools/marvin/marvin/factory/data/vm.py
@@ -39,7 +39,7 @@ class VirtualMachineWithStaticNat(VirtualMachineFactory):
             domainid=self.domainid,
             zoneid=self.zoneid,
         )
-        ipassoc.enableStaticNat(
+        self.enableStaticNat(
             apiclient=self.apiclient,
             ipaddressid=ipassoc.id,
             virtualmachineid=self.id

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f76b1029/tools/marvin/marvin/jsonHelper.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/jsonHelper.py b/tools/marvin/marvin/jsonHelper.py
index a395e6b..41d5ede 100644
--- a/tools/marvin/marvin/jsonHelper.py
+++ b/tools/marvin/marvin/jsonHelper.py
@@ -22,6 +22,7 @@ from cloudstackAPI import *
 
 
 class jsonLoader(object):
+
     '''The recursive class for building and representing objects with.'''
 
     def __init__(self, obj):
@@ -53,6 +54,7 @@ class jsonLoader(object):
 
 
 class jsonDump:
+
     @staticmethod
     def __serialize(obj):
         """Recursively walk object's hierarchy."""
@@ -75,7 +77,7 @@ class jsonDump:
         elif hasattr(obj, '__dict__'):
             return jsonDump.__serialize(obj.__dict__)
         else:
-            return repr(obj) # Don't know how to handle, convert to string
+            return repr(obj)  # Don't know how to handle, convert to string
 
     @staticmethod
     def dump(obj):
@@ -85,7 +87,8 @@ class jsonDump:
 def getClass(module, name):
     """Get the CloudStack command class in a module given the name
     @param module: cloudstack API module eg: createVolume
-    @param name: string name of the class within the module eg: createVolumeResponse
+    @param name: string name of the class within the module eg:
+    createVolumeResponse
     @return: response class
     """
     module = inspect.getmodule(module)
@@ -258,7 +261,7 @@ due to missing parameter jobid"
     except cloudstackException.cloudstackAPIException, e:
         print e
 
-    result = { "queryasyncjobresultresponse" : {}  }
+    result = {"queryasyncjobresultresponse": {}}
     asynJob = getResultObj(result)
     print "AsyncJob %s" % asynJob
 
@@ -282,13 +285,7 @@ due to missing parameter jobid"
     zone = getResultObj(result, res)
     print "Zone id %s" % zone.id
 
-    result = { "queryasyncjobresultresponse" : {"accountid":"4a8c3cd0-a696-11e2-b7a5-1aab0c3b0463","userid":"4a8c671e-a696-11e2-b7a5-1aab0c3b0463","cmd":"org.apache.cloudstack.api.command.admin.network.CreatePhysicalNetworkCmd","jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"physicalnetwork":{"id":"e0bc9017-9ba8-4551-a6f9-6b3b2ac1d59c","name":"Sandbox-pnet","broadcastdomainrange":"ZONE","zoneid":"88e796cd-953a-44b9-9445-a7c3ee205cc2","state":"Disabled"}},"created":"2013-04-16T18:37:01+0530","jobid":"8fc09350-f42a-4e04-9427-3d1b68f73dd0"} }
-    res = createPhysicalNetwork.createPhysicalNetworkResponse()
-    res = getResultObj(result, res)
-    print "PhysicalNetworkResponse %s" % res
-    print "PhysicalNetwork %s" % res.jobresult.id
-
-    result = { "listtemplatesresponse" : { } }
+    result = {"listtemplatesresponse": {}}
     print getResultObj(result, listTemplates.listTemplatesResponse())
 
     result = '''{

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f76b1029/tools/marvin/marvin/util.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/util.py b/tools/marvin/marvin/util.py
index 609e696..51a91ca 100644
--- a/tools/marvin/marvin/util.py
+++ b/tools/marvin/marvin/util.py
@@ -20,6 +20,7 @@ from marvin.entity.zone import Zone
 from marvin.entity.serviceoffering import ServiceOffering
 from marvin.entity.domain import Domain
 
+
 def get_domain(apiclient):
     "Returns a default `ROOT` domain"
 
@@ -31,6 +32,7 @@ def get_domain(apiclient):
     else:
         raise Exception("Failed to find any domains")
 
+
 def get_zone(apiclient):
     "Returns the default enabled zone"
 
@@ -46,6 +48,7 @@ def get_zone(apiclient):
     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
 
@@ -62,6 +65,7 @@ def get_service_offering(apiclient, storagetype='shared', scope=None):
                 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(
@@ -74,6 +78,8 @@ def get_template(apiclient, description=None):
             if template.isready:
                 return template
         else:
-            raise Exception("None of the templates are ready in your deployment")
+            raise Exception(
+                "None of the templates are ready in your deployment")
     else:
-        raise Exception("Failed to find ready and featured template of : %s" % description)
+        raise Exception(
+            "Failed to find ready and featured template of : %s" % description)


[28/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: data for networkoffering

use the random_gen for the name /displaytext of the offering

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/5055acd1
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/5055acd1
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/5055acd1

Branch: refs/heads/marvin-refactor
Commit: 5055acd1f24c6558e14fac61f38198507bde102d
Parents: b61f6ce
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Fri Sep 13 15:55:47 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:46 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/factory/data/networkoffering.py | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5055acd1/tools/marvin/marvin/factory/data/networkoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/networkoffering.py b/tools/marvin/marvin/factory/data/networkoffering.py
index 41cda56..5b64cf6 100644
--- a/tools/marvin/marvin/factory/data/networkoffering.py
+++ b/tools/marvin/marvin/factory/data/networkoffering.py
@@ -86,11 +86,10 @@ class DefaultSharedNetworkOfferingWithSGServiceFactory(NetworkOfferingFactory):
         self.update(apiclient=self.apiclient, id=self.id, state='Enabled')
 
 
-
 class DefaultSharedNetworkOfferingFactory(NetworkOfferingFactory):
 
-    displaytext = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingFactory-%d" % n)
-    name = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingFactory-%d" % n)
+    displaytext = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingFactory-%s" % random_gen())
+    name = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingFactory-%s" % random_gen())
     availability = "Optional"
     supportedservices = "Dns,Dhcp,UserData"
     guestiptype = "Shared"


[13/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin-refactor: moving old integration libraries to legacy


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/79a1591b
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/79a1591b
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/79a1591b

Branch: refs/heads/marvin-refactor
Commit: 79a1591b0aa34fc79bb2e8d15a3e9de57ce82f18
Parents: 8a1743c
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Fri Sep 6 20:21:30 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:21 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/common.py        |  739 ------
 tools/marvin/marvin/legacy/base.py   | 3591 +++++++++++++++++++++++++++++
 tools/marvin/marvin/legacy/common.py |  739 ++++++
 tools/marvin/marvin/legacy/utils.py  |  317 +++
 tools/marvin/marvin/oldbase.py       | 3591 -----------------------------
 tools/marvin/marvin/utils.py         |  317 ---
 6 files changed, 4647 insertions(+), 4647 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/79a1591b/tools/marvin/marvin/common.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/common.py b/tools/marvin/marvin/common.py
deleted file mode 100644
index 65d2f77..0000000
--- a/tools/marvin/marvin/common.py
+++ /dev/null
@@ -1,739 +0,0 @@
-# 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.
-"""Common functions
-"""
-
-#Import Local Modules
-from marvin.cloudstackAPI import *
-from marvin.remoteSSHClient import remoteSSHClient
-from marvin.utils import *
-from marvin.integration.lib.base import Configurations
-
-#Import System modules
-import time
-
-
-def is_config_suitable(apiclient, name, value):
-    """
-    Ensure if the deployment has the expected `value` for the global setting `name'
-    @return: true if value is set, else false
-    """
-    configs = Configurations.list(apiclient, name=name)
-    assert(configs is not None and isinstance(configs, list) and len(configs) > 0)
-    return configs[0].value == value
-
-def wait_for_cleanup(apiclient, configs=None):
-    """Sleeps till the cleanup configs passed"""
-
-    # Configs list consists of the list of global configs
-    if not isinstance(configs, list):
-        return
-    for config in configs:
-        cmd = listConfigurations.listConfigurationsCmd()
-        cmd.name = config
-        cmd.listall = True
-        try:
-            config_descs = apiclient.listConfigurations(cmd)
-        except Exception as e:
-            raise Exception("Failed to fetch configurations: %s" % e)
-
-        if not isinstance(config_descs, list):
-            raise Exception("List configs didn't returned a valid data")
-
-        config_desc = config_descs[0]
-        # Sleep for the config_desc.value time
-        time.sleep(int(config_desc.value))
-    return
-
-def add_netscaler(apiclient, zoneid, NSservice):
-    """ Adds Netscaler device and enables NS provider"""
-
-    cmd = listPhysicalNetworks.listPhysicalNetworksCmd()
-    cmd.zoneid = zoneid
-    physical_networks = apiclient.listPhysicalNetworks(cmd)
-    if isinstance(physical_networks, list):
-       physical_network = physical_networks[0]
-
-    cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd()
-    cmd.name = 'Netscaler'
-    cmd.physicalnetworkid=physical_network.id
-    nw_service_providers = apiclient.listNetworkServiceProviders(cmd)
-
-    if isinstance(nw_service_providers, list):
-        netscaler_provider = nw_service_providers[0]
-    else:
-        cmd1 = addNetworkServiceProvider.addNetworkServiceProviderCmd()
-        cmd1.name = 'Netscaler'
-        cmd1.physicalnetworkid = physical_network.id
-        netscaler_provider = apiclient.addNetworkServiceProvider(cmd1)
-
-    netscaler = NetScaler.add(
-                    apiclient,
-                    NSservice,
-                    physicalnetworkid=physical_network.id
-                    )
-    if netscaler_provider.state != 'Enabled':
-      cmd = updateNetworkServiceProvider.updateNetworkServiceProviderCmd()
-      cmd.id = netscaler_provider.id
-      cmd.state =  'Enabled'
-      response = apiclient.updateNetworkServiceProvider(cmd)
-
-    return netscaler
-
-def get_region(apiclient, services=None):
-    "Returns a default region"
-
-    cmd = listRegions.listRegionsCmd()
-    if services:
-        if "regionid" in services:
-            cmd.id = services["regionid"]
-
-    regions = apiclient.listRegions(cmd)
-
-    if isinstance(regions, list):
-        assert len(regions) > 0
-        return regions[0]
-    else:
-        raise Exception("Failed to find specified region.")
-
-def get_domain(apiclient, services=None):
-    "Returns a default domain"
-
-    cmd = listDomains.listDomainsCmd()
-    if services:
-        if "domainid" in services:
-            cmd.id = services["domainid"]
-
-    domains = apiclient.listDomains(cmd)
-
-    if isinstance(domains, list):
-        assert len(domains) > 0
-        return domains[0]
-    else:
-        raise Exception("Failed to find specified domain.")
-
-
-def get_zone(apiclient, services=None):
-    "Returns a default zone"
-
-    cmd = listZones.listZonesCmd()
-    if services:
-        if "zoneid" in services:
-            cmd.id = services["zoneid"]
-
-    zones = apiclient.listZones(cmd)
-
-    if isinstance(zones, list):
-        assert len(zones) > 0, "There are no available zones in the deployment"
-        return zones[0]
-    else:
-        raise Exception("Failed to find specified zone.")
-
-
-def get_pod(apiclient, zoneid, services=None):
-    "Returns a default pod for specified zone"
-
-    cmd = listPods.listPodsCmd()
-    cmd.zoneid = zoneid
-
-    if services:
-        if "podid" in services:
-            cmd.id = services["podid"]
-
-    pods = apiclient.listPods(cmd)
-
-    if isinstance(pods, list):
-        assert len(pods) > 0, "No pods found for zone %s"%zoneid
-        return pods[0]
-    else:
-        raise Exception("Exception: Failed to find specified pod.")
-
-
-def get_template(apiclient, zoneid, ostype, services=None):
-    "Returns a template"
-
-    cmd = listOsTypes.listOsTypesCmd()
-    cmd.description = ostype
-    ostypes = apiclient.listOsTypes(cmd)
-
-    if isinstance(ostypes, list):
-        ostypeid = ostypes[0].id
-    else:
-        raise Exception(
-            "Failed to find OS type with description: %s" % ostype)
-
-    cmd = listTemplates.listTemplatesCmd()
-    cmd.templatefilter = 'featured'
-    cmd.zoneid = zoneid
-
-    if services:
-        if "template" in services:
-            cmd.id = services["template"]
-
-    list_templates = apiclient.listTemplates(cmd)
-
-    if isinstance(list_templates, list):
-        assert len(list_templates) > 0, "received empty response on template of type %s"%ostype
-        for template in list_templates:
-            if template.ostypeid == ostypeid:
-                return template
-            elif template.isready:
-                return template
-
-    raise Exception("Exception: Failed to find template with OSTypeID: %s" %
-                                                                    ostypeid)
-    return
-
-
-def download_systemplates_sec_storage(server, services):
-    """Download System templates on sec storage"""
-
-    try:
-        # Login to management server
-        ssh = remoteSSHClient(
-                                          server["ipaddress"],
-                                          server["port"],
-                                          server["username"],
-                                          server["password"]
-                             )
-    except Exception:
-        raise Exception("SSH access failted for server with IP address: %s" %
-                                                            server["ipaddess"])
-    # Mount Secondary Storage on Management Server
-    cmds = [
-            "mkdir -p %s" % services["mnt_dir"],
-            "mount -t nfs %s:/%s %s" % (
-                                        services["sec_storage"],
-                                        services["path"],
-                                        services["mnt_dir"]
-                                        ),
-            "%s -m %s -u %s -h %s -F" % (
-                                         services["command"],
-                                         services["mnt_dir"],
-                                         services["download_url"],
-                                         services["hypervisor"]
-                                        )
-            ]
-    for c in cmds:
-        result = ssh.execute(c)
-
-    res = str(result)
-
-    # Unmount the Secondary storage
-    ssh.execute("umount %s" % (services["mnt_dir"]))
-
-    if res.count("Successfully installed system VM template") == 1:
-        return
-    else:
-        raise Exception("Failed to download System Templates on Sec Storage")
-    return
-
-
-def wait_for_ssvms(apiclient, zoneid, podid, interval=60):
-    """After setup wait for SSVMs to come Up"""
-
-    time.sleep(interval)
-    timeout = 40
-    while True:
-            list_ssvm_response = list_ssvms(
-                                        apiclient,
-                                        systemvmtype='secondarystoragevm',
-                                        zoneid=zoneid,
-                                        podid=podid
-                                        )
-            ssvm = list_ssvm_response[0]
-            if ssvm.state != 'Running':
-                # Sleep to ensure SSVMs are Up and Running
-                time.sleep(interval)
-                timeout = timeout - 1
-            elif ssvm.state == 'Running':
-                break
-            elif timeout == 0:
-                raise Exception("SSVM failed to come up")
-                break
-
-    timeout = 40
-    while True:
-            list_ssvm_response = list_ssvms(
-                                        apiclient,
-                                        systemvmtype='consoleproxy',
-                                        zoneid=zoneid,
-                                        podid=podid
-                                        )
-            cpvm = list_ssvm_response[0]
-            if cpvm.state != 'Running':
-                # Sleep to ensure SSVMs are Up and Running
-                time.sleep(interval)
-                timeout = timeout - 1
-            elif cpvm.state == 'Running':
-                break
-            elif timeout == 0:
-                raise Exception("CPVM failed to come up")
-                break
-    return
-
-def get_builtin_template_info(apiclient, zoneid):
-    """Returns hypervisor specific infor for templates"""
-
-    list_template_response = Template.list(
-                                    apiclient,
-                                    templatefilter='featured',
-                                    zoneid=zoneid,
-                                    )
-
-    for b_template in list_template_response:
-            if b_template.templatetype == 'BUILTIN':
-                break
-
-    extract_response = Template.extract(apiclient,
-                                            b_template.id,
-                                            'HTTP_DOWNLOAD',
-                                            zoneid)
-
-    return extract_response.url, b_template.hypervisor, b_template.format
-
-def download_builtin_templates(apiclient, zoneid, hypervisor, host,
-                                                linklocalip, interval=60):
-    """After setup wait till builtin templates are downloaded"""
-
-    # Change IPTABLES Rules
-    get_process_status(
-                        host["ipaddress"],
-                        host["port"],
-                        host["username"],
-                        host["password"],
-                        linklocalip,
-                        "iptables -P INPUT ACCEPT"
-                    )
-    time.sleep(interval)
-    # Find the BUILTIN Templates for given Zone, Hypervisor
-    list_template_response = list_templates(
-                                    apiclient,
-                                    hypervisor=hypervisor,
-                                    zoneid=zoneid,
-                                    templatefilter='self'
-                                    )
-
-    if not isinstance(list_template_response, list):
-        raise Exception("Failed to download BUILTIN templates")
-
-    # Ensure all BUILTIN templates are downloaded
-    templateid = None
-    for template in list_template_response:
-        if template.templatetype == "BUILTIN":
-                templateid = template.id
-
-    # Sleep to ensure that template is in downloading state after adding
-    # Sec storage
-    time.sleep(interval)
-    while True:
-        template_response = list_templates(
-                                    apiclient,
-                                    id=templateid,
-                                    zoneid=zoneid,
-                                    templatefilter='self'
-                                    )
-        template = template_response[0]
-        # If template is ready,
-        # template.status = Download Complete
-        # Downloading - x% Downloaded
-        # Error - Any other string
-        if template.status == 'Download Complete':
-            break
-
-        elif 'Downloaded' in template.status:
-            time.sleep(interval)
-
-        elif 'Installing' not in template.status:
-            raise Exception("ErrorInDownload")
-
-    return
-
-
-def update_resource_limit(apiclient, resourcetype, account=None,
-                                    domainid=None, max=None, projectid=None):
-    """Updates the resource limit to 'max' for given account"""
-
-    cmd = updateResourceLimit.updateResourceLimitCmd()
-    cmd.resourcetype = resourcetype
-    if account:
-        cmd.account = account
-    if domainid:
-        cmd.domainid = domainid
-    if max:
-        cmd.max = max
-    if projectid:
-        cmd.projectid = projectid
-    apiclient.updateResourceLimit(cmd)
-    return
-
-
-def list_os_types(apiclient, **kwargs):
-    """List all os types matching criteria"""
-
-    cmd = listOsTypes.listOsTypesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listOsTypes(cmd))
-
-
-def list_routers(apiclient, **kwargs):
-    """List all Routers matching criteria"""
-
-    cmd = listRouters.listRoutersCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listRouters(cmd))
-
-
-def list_zones(apiclient, **kwargs):
-    """List all Zones matching criteria"""
-
-    cmd = listZones.listZonesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listZones(cmd))
-
-
-def list_networks(apiclient, **kwargs):
-    """List all Networks matching criteria"""
-
-    cmd = listNetworks.listNetworksCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listNetworks(cmd))
-
-
-def list_clusters(apiclient, **kwargs):
-    """List all Clusters matching criteria"""
-
-    cmd = listClusters.listClustersCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listClusters(cmd))
-
-
-def list_ssvms(apiclient, **kwargs):
-    """List all SSVMs matching criteria"""
-
-    cmd = listSystemVms.listSystemVmsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listSystemVms(cmd))
-
-
-def list_storage_pools(apiclient, **kwargs):
-    """List all storage pools matching criteria"""
-
-    cmd = listStoragePools.listStoragePoolsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listStoragePools(cmd))
-
-
-def list_virtual_machines(apiclient, **kwargs):
-    """List all VMs matching criteria"""
-
-    cmd = listVirtualMachines.listVirtualMachinesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listVirtualMachines(cmd))
-
-
-def list_hosts(apiclient, **kwargs):
-    """List all Hosts matching criteria"""
-
-    cmd = listHosts.listHostsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listHosts(cmd))
-
-
-def list_configurations(apiclient, **kwargs):
-    """List configuration with specified name"""
-
-    cmd = listConfigurations.listConfigurationsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listConfigurations(cmd))
-
-
-def list_publicIP(apiclient, **kwargs):
-    """List all Public IPs matching criteria"""
-
-    cmd = listPublicIpAddresses.listPublicIpAddressesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listPublicIpAddresses(cmd))
-
-
-def list_nat_rules(apiclient, **kwargs):
-    """List all NAT rules matching criteria"""
-
-    cmd = listPortForwardingRules.listPortForwardingRulesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listPortForwardingRules(cmd))
-
-
-def list_lb_rules(apiclient, **kwargs):
-    """List all Load balancing rules matching criteria"""
-
-    cmd = listLoadBalancerRules.listLoadBalancerRulesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listLoadBalancerRules(cmd))
-
-
-def list_lb_instances(apiclient, **kwargs):
-    """List all Load balancing instances matching criteria"""
-
-    cmd = listLoadBalancerRuleInstances.listLoadBalancerRuleInstancesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listLoadBalancerRuleInstances(cmd))
-
-
-def list_firewall_rules(apiclient, **kwargs):
-    """List all Firewall Rules matching criteria"""
-
-    cmd = listFirewallRules.listFirewallRulesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listFirewallRules(cmd))
-
-
-def list_volumes(apiclient, **kwargs):
-    """List all volumes matching criteria"""
-
-    cmd = listVolumes.listVolumesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listVolumes(cmd))
-
-
-def list_isos(apiclient, **kwargs):
-    """Lists all available ISO files."""
-
-    cmd = listIsos.listIsosCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listIsos(cmd))
-
-
-def list_snapshots(apiclient, **kwargs):
-    """List all snapshots matching criteria"""
-
-    cmd = listSnapshots.listSnapshotsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listSnapshots(cmd))
-
-
-def list_templates(apiclient, **kwargs):
-    """List all templates matching criteria"""
-
-    cmd = listTemplates.listTemplatesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listTemplates(cmd))
-
-
-def list_domains(apiclient, **kwargs):
-    """Lists domains"""
-
-    cmd = listDomains.listDomainsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listDomains(cmd))
-
-
-def list_accounts(apiclient, **kwargs):
-    """Lists accounts and provides detailed account information for
-    listed accounts"""
-
-    cmd = listAccounts.listAccountsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listAccounts(cmd))
-
-
-def list_users(apiclient, **kwargs):
-    """Lists users and provides detailed account information for
-    listed users"""
-
-    cmd = listUsers.listUsersCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listUsers(cmd))
-
-
-def list_snapshot_policy(apiclient, **kwargs):
-    """Lists snapshot policies."""
-
-    cmd = listSnapshotPolicies.listSnapshotPoliciesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listSnapshotPolicies(cmd))
-
-
-def list_events(apiclient, **kwargs):
-    """Lists events"""
-
-    cmd = listEvents.listEventsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listEvents(cmd))
-
-
-def list_disk_offering(apiclient, **kwargs):
-    """Lists all available disk offerings."""
-
-    cmd = listDiskOfferings.listDiskOfferingsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listDiskOfferings(cmd))
-
-
-def list_service_offering(apiclient, **kwargs):
-    """Lists all available service offerings."""
-
-    cmd = listServiceOfferings.listServiceOfferingsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listServiceOfferings(cmd))
-
-
-def list_vlan_ipranges(apiclient, **kwargs):
-    """Lists all VLAN IP ranges."""
-
-    cmd = listVlanIpRanges.listVlanIpRangesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listVlanIpRanges(cmd))
-
-
-def list_usage_records(apiclient, **kwargs):
-    """Lists usage records for accounts"""
-
-    cmd = listUsageRecords.listUsageRecordsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listUsageRecords(cmd))
-
-
-def list_nw_service_prividers(apiclient, **kwargs):
-    """Lists Network service providers"""
-
-    cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listNetworkServiceProviders(cmd))
-
-
-def list_virtual_router_elements(apiclient, **kwargs):
-    """Lists Virtual Router elements"""
-
-    cmd = listVirtualRouterElements.listVirtualRouterElementsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listVirtualRouterElements(cmd))
-
-
-def list_network_offerings(apiclient, **kwargs):
-    """Lists network offerings"""
-
-    cmd = listNetworkOfferings.listNetworkOfferingsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listNetworkOfferings(cmd))
-
-
-def list_resource_limits(apiclient, **kwargs):
-    """Lists resource limits"""
-
-    cmd = listResourceLimits.listResourceLimitsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listResourceLimits(cmd))
-
-def list_vpc_offerings(apiclient, **kwargs):
-    """ Lists VPC offerings """
-
-    cmd = listVPCOfferings.listVPCOfferingsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listVPCOfferings(cmd))
-
-def update_resource_count(apiclient, domainid, accountid=None,
-                          projectid=None, rtype=None):
-        """updates the resource count
-            0     - VM
-            1     - Public IP
-            2     - Volume
-            3     - Snapshot
-            4     - Template
-            5     - Projects
-            6     - Network
-            7     - VPC
-            8     - CPUs
-            9     - RAM
-            10    - Primary (shared) storage (Volumes)
-            11    - Secondary storage (Snapshots, Templates & ISOs)
-        """
-
-        Resources.updateCount(apiclient,
-                              domainid=domainid,
-                              account=accountid if accountid else None,
-                              projectid=projectid if projectid else None,
-                              resourcetype=rtype if rtype else None
-                              )
-        return
-
-def find_suitable_host(apiclient, vm):
-        """Returns a suitable host for VM migration"""
-
-        hosts = Host.list(apiclient,
-                          virtualmachineid=vm.id,
-                          listall=True)
-
-        if isinstance(hosts, list):
-            assert len(hosts) > 0, "List host should return valid response"
-        else:
-            raise Exception("Exception: List host should return valid response")
-        return hosts[0]
-
-def get_resource_type(resource_id):
-        """Returns resource type"""
-
-        lookup = {  0: "VM",
-                    1: "Public IP",
-                    2: "Volume",
-                    3: "Snapshot",
-                    4: "Template",
-                    5: "Projects",
-                    6: "Network",
-                    7: "VPC",
-                    8: "CPUs",
-                    9: "RAM",
-                    10: "Primary (shared) storage (Volumes)",
-                    11: "Secondary storage (Snapshots, Templates & ISOs)"
-                 }
-
-        return lookup[resource_id]
-
-def get_portable_ip_range_services(config):
-    """ Reads config values related to portable ip and fills up
-    services accordingly"""
-
-    services = {}
-    attributeError = False
-
-    if config.portableIpRange.startip:
-        services["startip"] = config.portableIpRange.startip
-    else:
-        attributeError = True
-
-    if config.portableIpRange.endip:
-        services["endip"] = config.portableIpRange.endip
-    else:
-        attributeError = True
-
-    if config.portableIpRange.netmask:
-        services["netmask"] = config.portableIpRange.netmask
-    else:
-        attributeError = True
-
-    if config.portableIpRange.gateway:
-        services["gateway"] = config.portableIpRange.gateway
-    else:
-        attributeError = True
-
-    if config.portableIpRange.vlan:
-        services["vlan"] = config.portableIpRange.vlan
-
-    if attributeError:
-        services = None
-
-    return services


[11/50] [abbrv] marvin-refactor: moving old integration libraries to legacy

Posted by ts...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/79a1591b/tools/marvin/marvin/legacy/common.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/legacy/common.py b/tools/marvin/marvin/legacy/common.py
new file mode 100644
index 0000000..63bff7c
--- /dev/null
+++ b/tools/marvin/marvin/legacy/common.py
@@ -0,0 +1,739 @@
+# 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.
+"""Common functions
+"""
+
+#Import Local Modules
+from marvin.cloudstackAPI import *
+from marvin.remoteSSHClient import remoteSSHClient
+from marvin.legacy.utils import *
+from marvin.integration.lib.base import Configurations
+
+#Import System modules
+import time
+
+
+def is_config_suitable(apiclient, name, value):
+    """
+    Ensure if the deployment has the expected `value` for the global setting `name'
+    @return: true if value is set, else false
+    """
+    configs = Configurations.list(apiclient, name=name)
+    assert(configs is not None and isinstance(configs, list) and len(configs) > 0)
+    return configs[0].value == value
+
+def wait_for_cleanup(apiclient, configs=None):
+    """Sleeps till the cleanup configs passed"""
+
+    # Configs list consists of the list of global configs
+    if not isinstance(configs, list):
+        return
+    for config in configs:
+        cmd = listConfigurations.listConfigurationsCmd()
+        cmd.name = config
+        cmd.listall = True
+        try:
+            config_descs = apiclient.listConfigurations(cmd)
+        except Exception as e:
+            raise Exception("Failed to fetch configurations: %s" % e)
+
+        if not isinstance(config_descs, list):
+            raise Exception("List configs didn't returned a valid data")
+
+        config_desc = config_descs[0]
+        # Sleep for the config_desc.value time
+        time.sleep(int(config_desc.value))
+    return
+
+def add_netscaler(apiclient, zoneid, NSservice):
+    """ Adds Netscaler device and enables NS provider"""
+
+    cmd = listPhysicalNetworks.listPhysicalNetworksCmd()
+    cmd.zoneid = zoneid
+    physical_networks = apiclient.listPhysicalNetworks(cmd)
+    if isinstance(physical_networks, list):
+       physical_network = physical_networks[0]
+
+    cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd()
+    cmd.name = 'Netscaler'
+    cmd.physicalnetworkid=physical_network.id
+    nw_service_providers = apiclient.listNetworkServiceProviders(cmd)
+
+    if isinstance(nw_service_providers, list):
+        netscaler_provider = nw_service_providers[0]
+    else:
+        cmd1 = addNetworkServiceProvider.addNetworkServiceProviderCmd()
+        cmd1.name = 'Netscaler'
+        cmd1.physicalnetworkid = physical_network.id
+        netscaler_provider = apiclient.addNetworkServiceProvider(cmd1)
+
+    netscaler = NetScaler.add(
+                    apiclient,
+                    NSservice,
+                    physicalnetworkid=physical_network.id
+                    )
+    if netscaler_provider.state != 'Enabled':
+      cmd = updateNetworkServiceProvider.updateNetworkServiceProviderCmd()
+      cmd.id = netscaler_provider.id
+      cmd.state =  'Enabled'
+      response = apiclient.updateNetworkServiceProvider(cmd)
+
+    return netscaler
+
+def get_region(apiclient, services=None):
+    "Returns a default region"
+
+    cmd = listRegions.listRegionsCmd()
+    if services:
+        if "regionid" in services:
+            cmd.id = services["regionid"]
+
+    regions = apiclient.listRegions(cmd)
+
+    if isinstance(regions, list):
+        assert len(regions) > 0
+        return regions[0]
+    else:
+        raise Exception("Failed to find specified region.")
+
+def get_domain(apiclient, services=None):
+    "Returns a default domain"
+
+    cmd = listDomains.listDomainsCmd()
+    if services:
+        if "domainid" in services:
+            cmd.id = services["domainid"]
+
+    domains = apiclient.listDomains(cmd)
+
+    if isinstance(domains, list):
+        assert len(domains) > 0
+        return domains[0]
+    else:
+        raise Exception("Failed to find specified domain.")
+
+
+def get_zone(apiclient, services=None):
+    "Returns a default zone"
+
+    cmd = listZones.listZonesCmd()
+    if services:
+        if "zoneid" in services:
+            cmd.id = services["zoneid"]
+
+    zones = apiclient.listZones(cmd)
+
+    if isinstance(zones, list):
+        assert len(zones) > 0, "There are no available zones in the deployment"
+        return zones[0]
+    else:
+        raise Exception("Failed to find specified zone.")
+
+
+def get_pod(apiclient, zoneid, services=None):
+    "Returns a default pod for specified zone"
+
+    cmd = listPods.listPodsCmd()
+    cmd.zoneid = zoneid
+
+    if services:
+        if "podid" in services:
+            cmd.id = services["podid"]
+
+    pods = apiclient.listPods(cmd)
+
+    if isinstance(pods, list):
+        assert len(pods) > 0, "No pods found for zone %s"%zoneid
+        return pods[0]
+    else:
+        raise Exception("Exception: Failed to find specified pod.")
+
+
+def get_template(apiclient, zoneid, ostype, services=None):
+    "Returns a template"
+
+    cmd = listOsTypes.listOsTypesCmd()
+    cmd.description = ostype
+    ostypes = apiclient.listOsTypes(cmd)
+
+    if isinstance(ostypes, list):
+        ostypeid = ostypes[0].id
+    else:
+        raise Exception(
+            "Failed to find OS type with description: %s" % ostype)
+
+    cmd = listTemplates.listTemplatesCmd()
+    cmd.templatefilter = 'featured'
+    cmd.zoneid = zoneid
+
+    if services:
+        if "template" in services:
+            cmd.id = services["template"]
+
+    list_templates = apiclient.listTemplates(cmd)
+
+    if isinstance(list_templates, list):
+        assert len(list_templates) > 0, "received empty response on template of type %s"%ostype
+        for template in list_templates:
+            if template.ostypeid == ostypeid:
+                return template
+            elif template.isready:
+                return template
+
+    raise Exception("Exception: Failed to find template with OSTypeID: %s" %
+                                                                    ostypeid)
+    return
+
+
+def download_systemplates_sec_storage(server, services):
+    """Download System templates on sec storage"""
+
+    try:
+        # Login to management server
+        ssh = remoteSSHClient(
+                                          server["ipaddress"],
+                                          server["port"],
+                                          server["username"],
+                                          server["password"]
+                             )
+    except Exception:
+        raise Exception("SSH access failted for server with IP address: %s" %
+                                                            server["ipaddess"])
+    # Mount Secondary Storage on Management Server
+    cmds = [
+            "mkdir -p %s" % services["mnt_dir"],
+            "mount -t nfs %s:/%s %s" % (
+                                        services["sec_storage"],
+                                        services["path"],
+                                        services["mnt_dir"]
+                                        ),
+            "%s -m %s -u %s -h %s -F" % (
+                                         services["command"],
+                                         services["mnt_dir"],
+                                         services["download_url"],
+                                         services["hypervisor"]
+                                        )
+            ]
+    for c in cmds:
+        result = ssh.execute(c)
+
+    res = str(result)
+
+    # Unmount the Secondary storage
+    ssh.execute("umount %s" % (services["mnt_dir"]))
+
+    if res.count("Successfully installed system VM template") == 1:
+        return
+    else:
+        raise Exception("Failed to download System Templates on Sec Storage")
+    return
+
+
+def wait_for_ssvms(apiclient, zoneid, podid, interval=60):
+    """After setup wait for SSVMs to come Up"""
+
+    time.sleep(interval)
+    timeout = 40
+    while True:
+            list_ssvm_response = list_ssvms(
+                                        apiclient,
+                                        systemvmtype='secondarystoragevm',
+                                        zoneid=zoneid,
+                                        podid=podid
+                                        )
+            ssvm = list_ssvm_response[0]
+            if ssvm.state != 'Running':
+                # Sleep to ensure SSVMs are Up and Running
+                time.sleep(interval)
+                timeout = timeout - 1
+            elif ssvm.state == 'Running':
+                break
+            elif timeout == 0:
+                raise Exception("SSVM failed to come up")
+                break
+
+    timeout = 40
+    while True:
+            list_ssvm_response = list_ssvms(
+                                        apiclient,
+                                        systemvmtype='consoleproxy',
+                                        zoneid=zoneid,
+                                        podid=podid
+                                        )
+            cpvm = list_ssvm_response[0]
+            if cpvm.state != 'Running':
+                # Sleep to ensure SSVMs are Up and Running
+                time.sleep(interval)
+                timeout = timeout - 1
+            elif cpvm.state == 'Running':
+                break
+            elif timeout == 0:
+                raise Exception("CPVM failed to come up")
+                break
+    return
+
+def get_builtin_template_info(apiclient, zoneid):
+    """Returns hypervisor specific infor for templates"""
+
+    list_template_response = Template.list(
+                                    apiclient,
+                                    templatefilter='featured',
+                                    zoneid=zoneid,
+                                    )
+
+    for b_template in list_template_response:
+            if b_template.templatetype == 'BUILTIN':
+                break
+
+    extract_response = Template.extract(apiclient,
+                                            b_template.id,
+                                            'HTTP_DOWNLOAD',
+                                            zoneid)
+
+    return extract_response.url, b_template.hypervisor, b_template.format
+
+def download_builtin_templates(apiclient, zoneid, hypervisor, host,
+                                                linklocalip, interval=60):
+    """After setup wait till builtin templates are downloaded"""
+
+    # Change IPTABLES Rules
+    get_process_status(
+                        host["ipaddress"],
+                        host["port"],
+                        host["username"],
+                        host["password"],
+                        linklocalip,
+                        "iptables -P INPUT ACCEPT"
+                    )
+    time.sleep(interval)
+    # Find the BUILTIN Templates for given Zone, Hypervisor
+    list_template_response = list_templates(
+                                    apiclient,
+                                    hypervisor=hypervisor,
+                                    zoneid=zoneid,
+                                    templatefilter='self'
+                                    )
+
+    if not isinstance(list_template_response, list):
+        raise Exception("Failed to download BUILTIN templates")
+
+    # Ensure all BUILTIN templates are downloaded
+    templateid = None
+    for template in list_template_response:
+        if template.templatetype == "BUILTIN":
+                templateid = template.id
+
+    # Sleep to ensure that template is in downloading state after adding
+    # Sec storage
+    time.sleep(interval)
+    while True:
+        template_response = list_templates(
+                                    apiclient,
+                                    id=templateid,
+                                    zoneid=zoneid,
+                                    templatefilter='self'
+                                    )
+        template = template_response[0]
+        # If template is ready,
+        # template.status = Download Complete
+        # Downloading - x% Downloaded
+        # Error - Any other string
+        if template.status == 'Download Complete':
+            break
+
+        elif 'Downloaded' in template.status:
+            time.sleep(interval)
+
+        elif 'Installing' not in template.status:
+            raise Exception("ErrorInDownload")
+
+    return
+
+
+def update_resource_limit(apiclient, resourcetype, account=None,
+                                    domainid=None, max=None, projectid=None):
+    """Updates the resource limit to 'max' for given account"""
+
+    cmd = updateResourceLimit.updateResourceLimitCmd()
+    cmd.resourcetype = resourcetype
+    if account:
+        cmd.account = account
+    if domainid:
+        cmd.domainid = domainid
+    if max:
+        cmd.max = max
+    if projectid:
+        cmd.projectid = projectid
+    apiclient.updateResourceLimit(cmd)
+    return
+
+
+def list_os_types(apiclient, **kwargs):
+    """List all os types matching criteria"""
+
+    cmd = listOsTypes.listOsTypesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listOsTypes(cmd))
+
+
+def list_routers(apiclient, **kwargs):
+    """List all Routers matching criteria"""
+
+    cmd = listRouters.listRoutersCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listRouters(cmd))
+
+
+def list_zones(apiclient, **kwargs):
+    """List all Zones matching criteria"""
+
+    cmd = listZones.listZonesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listZones(cmd))
+
+
+def list_networks(apiclient, **kwargs):
+    """List all Networks matching criteria"""
+
+    cmd = listNetworks.listNetworksCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listNetworks(cmd))
+
+
+def list_clusters(apiclient, **kwargs):
+    """List all Clusters matching criteria"""
+
+    cmd = listClusters.listClustersCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listClusters(cmd))
+
+
+def list_ssvms(apiclient, **kwargs):
+    """List all SSVMs matching criteria"""
+
+    cmd = listSystemVms.listSystemVmsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listSystemVms(cmd))
+
+
+def list_storage_pools(apiclient, **kwargs):
+    """List all storage pools matching criteria"""
+
+    cmd = listStoragePools.listStoragePoolsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listStoragePools(cmd))
+
+
+def list_virtual_machines(apiclient, **kwargs):
+    """List all VMs matching criteria"""
+
+    cmd = listVirtualMachines.listVirtualMachinesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listVirtualMachines(cmd))
+
+
+def list_hosts(apiclient, **kwargs):
+    """List all Hosts matching criteria"""
+
+    cmd = listHosts.listHostsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listHosts(cmd))
+
+
+def list_configurations(apiclient, **kwargs):
+    """List configuration with specified name"""
+
+    cmd = listConfigurations.listConfigurationsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listConfigurations(cmd))
+
+
+def list_publicIP(apiclient, **kwargs):
+    """List all Public IPs matching criteria"""
+
+    cmd = listPublicIpAddresses.listPublicIpAddressesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listPublicIpAddresses(cmd))
+
+
+def list_nat_rules(apiclient, **kwargs):
+    """List all NAT rules matching criteria"""
+
+    cmd = listPortForwardingRules.listPortForwardingRulesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listPortForwardingRules(cmd))
+
+
+def list_lb_rules(apiclient, **kwargs):
+    """List all Load balancing rules matching criteria"""
+
+    cmd = listLoadBalancerRules.listLoadBalancerRulesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listLoadBalancerRules(cmd))
+
+
+def list_lb_instances(apiclient, **kwargs):
+    """List all Load balancing instances matching criteria"""
+
+    cmd = listLoadBalancerRuleInstances.listLoadBalancerRuleInstancesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listLoadBalancerRuleInstances(cmd))
+
+
+def list_firewall_rules(apiclient, **kwargs):
+    """List all Firewall Rules matching criteria"""
+
+    cmd = listFirewallRules.listFirewallRulesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listFirewallRules(cmd))
+
+
+def list_volumes(apiclient, **kwargs):
+    """List all volumes matching criteria"""
+
+    cmd = listVolumes.listVolumesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listVolumes(cmd))
+
+
+def list_isos(apiclient, **kwargs):
+    """Lists all available ISO files."""
+
+    cmd = listIsos.listIsosCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listIsos(cmd))
+
+
+def list_snapshots(apiclient, **kwargs):
+    """List all snapshots matching criteria"""
+
+    cmd = listSnapshots.listSnapshotsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listSnapshots(cmd))
+
+
+def list_templates(apiclient, **kwargs):
+    """List all templates matching criteria"""
+
+    cmd = listTemplates.listTemplatesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listTemplates(cmd))
+
+
+def list_domains(apiclient, **kwargs):
+    """Lists domains"""
+
+    cmd = listDomains.listDomainsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listDomains(cmd))
+
+
+def list_accounts(apiclient, **kwargs):
+    """Lists accounts and provides detailed account information for
+    listed accounts"""
+
+    cmd = listAccounts.listAccountsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listAccounts(cmd))
+
+
+def list_users(apiclient, **kwargs):
+    """Lists users and provides detailed account information for
+    listed users"""
+
+    cmd = listUsers.listUsersCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listUsers(cmd))
+
+
+def list_snapshot_policy(apiclient, **kwargs):
+    """Lists snapshot policies."""
+
+    cmd = listSnapshotPolicies.listSnapshotPoliciesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listSnapshotPolicies(cmd))
+
+
+def list_events(apiclient, **kwargs):
+    """Lists events"""
+
+    cmd = listEvents.listEventsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listEvents(cmd))
+
+
+def list_disk_offering(apiclient, **kwargs):
+    """Lists all available disk offerings."""
+
+    cmd = listDiskOfferings.listDiskOfferingsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listDiskOfferings(cmd))
+
+
+def list_service_offering(apiclient, **kwargs):
+    """Lists all available service offerings."""
+
+    cmd = listServiceOfferings.listServiceOfferingsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listServiceOfferings(cmd))
+
+
+def list_vlan_ipranges(apiclient, **kwargs):
+    """Lists all VLAN IP ranges."""
+
+    cmd = listVlanIpRanges.listVlanIpRangesCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listVlanIpRanges(cmd))
+
+
+def list_usage_records(apiclient, **kwargs):
+    """Lists usage records for accounts"""
+
+    cmd = listUsageRecords.listUsageRecordsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listUsageRecords(cmd))
+
+
+def list_nw_service_prividers(apiclient, **kwargs):
+    """Lists Network service providers"""
+
+    cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listNetworkServiceProviders(cmd))
+
+
+def list_virtual_router_elements(apiclient, **kwargs):
+    """Lists Virtual Router elements"""
+
+    cmd = listVirtualRouterElements.listVirtualRouterElementsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listVirtualRouterElements(cmd))
+
+
+def list_network_offerings(apiclient, **kwargs):
+    """Lists network offerings"""
+
+    cmd = listNetworkOfferings.listNetworkOfferingsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listNetworkOfferings(cmd))
+
+
+def list_resource_limits(apiclient, **kwargs):
+    """Lists resource limits"""
+
+    cmd = listResourceLimits.listResourceLimitsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listResourceLimits(cmd))
+
+def list_vpc_offerings(apiclient, **kwargs):
+    """ Lists VPC offerings """
+
+    cmd = listVPCOfferings.listVPCOfferingsCmd()
+    [setattr(cmd, k, v) for k, v in kwargs.items()]
+    return(apiclient.listVPCOfferings(cmd))
+
+def update_resource_count(apiclient, domainid, accountid=None,
+                          projectid=None, rtype=None):
+        """updates the resource count
+            0     - VM
+            1     - Public IP
+            2     - Volume
+            3     - Snapshot
+            4     - Template
+            5     - Projects
+            6     - Network
+            7     - VPC
+            8     - CPUs
+            9     - RAM
+            10    - Primary (shared) storage (Volumes)
+            11    - Secondary storage (Snapshots, Templates & ISOs)
+        """
+
+        Resources.updateCount(apiclient,
+                              domainid=domainid,
+                              account=accountid if accountid else None,
+                              projectid=projectid if projectid else None,
+                              resourcetype=rtype if rtype else None
+                              )
+        return
+
+def find_suitable_host(apiclient, vm):
+        """Returns a suitable host for VM migration"""
+
+        hosts = Host.list(apiclient,
+                          virtualmachineid=vm.id,
+                          listall=True)
+
+        if isinstance(hosts, list):
+            assert len(hosts) > 0, "List host should return valid response"
+        else:
+            raise Exception("Exception: List host should return valid response")
+        return hosts[0]
+
+def get_resource_type(resource_id):
+        """Returns resource type"""
+
+        lookup = {  0: "VM",
+                    1: "Public IP",
+                    2: "Volume",
+                    3: "Snapshot",
+                    4: "Template",
+                    5: "Projects",
+                    6: "Network",
+                    7: "VPC",
+                    8: "CPUs",
+                    9: "RAM",
+                    10: "Primary (shared) storage (Volumes)",
+                    11: "Secondary storage (Snapshots, Templates & ISOs)"
+                 }
+
+        return lookup[resource_id]
+
+def get_portable_ip_range_services(config):
+    """ Reads config values related to portable ip and fills up
+    services accordingly"""
+
+    services = {}
+    attributeError = False
+
+    if config.portableIpRange.startip:
+        services["startip"] = config.portableIpRange.startip
+    else:
+        attributeError = True
+
+    if config.portableIpRange.endip:
+        services["endip"] = config.portableIpRange.endip
+    else:
+        attributeError = True
+
+    if config.portableIpRange.netmask:
+        services["netmask"] = config.portableIpRange.netmask
+    else:
+        attributeError = True
+
+    if config.portableIpRange.gateway:
+        services["gateway"] = config.portableIpRange.gateway
+    else:
+        attributeError = True
+
+    if config.portableIpRange.vlan:
+        services["vlan"] = config.portableIpRange.vlan
+
+    if attributeError:
+        services = None
+
+    return services

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/79a1591b/tools/marvin/marvin/legacy/utils.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/legacy/utils.py b/tools/marvin/marvin/legacy/utils.py
new file mode 100644
index 0000000..44a6e96
--- /dev/null
+++ b/tools/marvin/marvin/legacy/utils.py
@@ -0,0 +1,317 @@
+# 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.
+"""Utilities functions
+"""
+
+import marvin
+import os
+import time
+import logging
+import string
+import random
+import imaplib
+import email
+import socket
+import urlparse
+import datetime
+from marvin.cloudstackAPI import *
+from marvin.remoteSSHClient import remoteSSHClient
+
+
+def restart_mgmt_server(server):
+    """Restarts the management server"""
+
+    try:
+        # Get the SSH client
+        ssh = is_server_ssh_ready(
+            server["ipaddress"],
+            server["port"],
+            server["username"],
+            server["password"],
+        )
+        result = ssh.execute("/etc/init.d/cloud-management restart")
+        res = str(result)
+        # Server Stop - OK
+        # Server Start - OK
+        if res.count("OK") != 2:
+            raise ("ErrorInReboot!")
+    except Exception as e:
+        raise e
+    return
+
+
+def fetch_latest_mail(services, from_mail):
+    """Fetch mail"""
+
+    # Login to mail server to verify email
+    mail = imaplib.IMAP4_SSL(services["server"])
+    mail.login(
+        services["email"],
+        services["password"]
+    )
+    mail.list()
+    mail.select(services["folder"])
+    date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y")
+
+    result, data = mail.uid(
+        'search',
+        None,
+        '(SENTSINCE {date} HEADER FROM "{mail}")'.format(
+            date=date,
+            mail=from_mail
+        )
+    )
+    # Return False if email is not present
+    if data == []:
+        return False
+
+    latest_email_uid = data[0].split()[-1]
+    result, data = mail.uid('fetch', latest_email_uid, '(RFC822)')
+    raw_email = data[0][1]
+    email_message = email.message_from_string(raw_email)
+    result = get_first_text_block(email_message)
+    return result
+
+
+def get_first_text_block(email_message_instance):
+    """fetches first text block from the mail"""
+    maintype = email_message_instance.get_content_maintype()
+    if maintype == 'multipart':
+        for part in email_message_instance.get_payload():
+            if part.get_content_maintype() == 'text':
+                return part.get_payload()
+    elif maintype == 'text':
+        return email_message_instance.get_payload()
+
+
+def random_gen(id=None, size=6, chars=string.ascii_uppercase + string.digits):
+    """Generate Random Strings of variable length"""
+    randomstr = ''.join(random.choice(chars) for x in range(size))
+    if id:
+        return ''.join([id, '-', randomstr])
+    return randomstr
+
+
+def cleanup_resources(api_client, resources):
+    """Delete resources"""
+    for obj in resources:
+        obj.delete(api_client)
+
+
+def is_server_ssh_ready(ipaddress, port, username, password, retries=10, timeout=30, keyPairFileLocation=None):
+    """Return ssh handle else wait till sshd is running"""
+    try:
+        ssh = remoteSSHClient(
+            host=ipaddress,
+            port=port,
+            user=username,
+            passwd=password,
+            keyPairFileLocation=keyPairFileLocation,
+            retries=retries,
+            delay=timeout)
+    except Exception, e:
+        raise Exception("Failed to bring up ssh service in time. Waited %ss. Error is %s" % (retries * timeout, e))
+    else:
+        return ssh
+
+
+def format_volume_to_ext3(ssh_client, device="/dev/sda"):
+    """Format attached storage to ext3 fs"""
+    cmds = [
+        "echo -e 'n\np\n1\n\n\nw' | fdisk %s" % device,
+        "mkfs.ext3 %s1" % device,
+    ]
+    for c in cmds:
+        ssh_client.execute(c)
+
+
+def fetch_api_client(config_file='datacenterCfg'):
+    """Fetch the Cloudstack API Client"""
+    config = marvin.configGenerator.get_setup_config(config_file)
+    mgt = config.mgtSvr[0]
+    testClientLogger = logging.getLogger("testClient")
+    asyncTimeout = 3600
+    return cloudstackAPIClient.CloudStackAPIClient(
+        marvin.cloudstackConnection.cloudConnection(
+            mgt.mgtSvrIp,
+            mgt.port,
+            mgt.apiKey,
+            mgt.securityKey,
+            asyncTimeout,
+            testClientLogger
+        )
+    )
+
+def get_host_credentials(config, hostip):
+    """Get login information for a host `hostip` (ipv4) from marvin's `config`
+
+    @return the tuple username, password for the host else raise keyerror"""
+    for zone in config.zones:
+        for pod in zone.pods:
+            for cluster in pod.clusters:
+                for host in cluster.hosts:
+                    if str(host.url).startswith('http'):
+                        hostname = urlparse.urlsplit(str(host.url)).netloc
+                    else:
+                        hostname = str(host.url)
+                    try:
+                        if socket.getfqdn(hostip) == socket.getfqdn(hostname):
+                            return host.username, host.password
+                    except socket.error, e:
+                        raise Exception("Unresolvable host %s error is %s" % (hostip, e))
+    raise KeyError("Please provide the marvin configuration file with credentials to your hosts")
+
+def get_process_status(hostip, port, username, password, linklocalip, process, hypervisor=None):
+    """Double hop and returns a process status"""
+
+    #SSH to the machine
+    ssh = remoteSSHClient(hostip, port, username, password)
+    if str(hypervisor).lower() == 'vmware':
+        ssh_command = "ssh -i /var/cloudstack/management/.ssh/id_rsa -ostricthostkeychecking=no "
+    else:
+        ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
+
+    ssh_command = ssh_command +\
+                  "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % (
+                      linklocalip,
+                      process)
+
+    # Double hop into router
+    timeout = 5
+    # Ensure the SSH login is successful
+    while True:
+        res = ssh.execute(ssh_command)
+
+        if res[0] != "Host key verification failed.":
+            break
+        elif timeout == 0:
+            break
+
+        time.sleep(5)
+        timeout = timeout - 1
+    return res
+
+
+def isAlmostEqual(first_digit, second_digit, range=0):
+    digits_equal_within_range = False
+
+    try:
+        if ((first_digit - range) < second_digit < (first_digit + range)):
+            digits_equal_within_range = True
+    except Exception as e:
+        raise e
+    return digits_equal_within_range
+
+
+def xsplit(txt, seps):
+    """
+    Split a string in `txt` by list of delimiters in `seps`
+    @param txt: string to split
+    @param seps: list of separators
+    @return: list of split units
+    """
+    default_sep = seps[0]
+    for sep in seps[1:]: # we skip seps[0] because that's the default separator
+        txt = txt.replace(sep, default_sep)
+    return [i.strip() for i in txt.split(default_sep)]
+
+def is_snapshot_on_nfs(apiclient, dbconn, config, zoneid, snapshotid):
+    """
+    Checks whether a snapshot with id (not UUID) `snapshotid` is present on the nfs storage
+
+    @param apiclient: api client connection
+    @param @dbconn:  connection to the cloudstack db
+    @param config: marvin configuration file
+    @param zoneid: uuid of the zone on which the secondary nfs storage pool is mounted
+    @param snapshotid: uuid of the snapshot
+    @return: True if snapshot is found, False otherwise
+    """
+
+    from entity import ImageStore, Snapshot
+    secondaryStores = ImageStore.list(apiclient, zoneid=zoneid)
+
+    assert isinstance(secondaryStores, list), "Not a valid response for listImageStores"
+    assert len(secondaryStores) != 0, "No image stores found in zone %s" % zoneid
+
+    secondaryStore = secondaryStores[0]
+
+    if str(secondaryStore.providername).lower() != "nfs":
+        raise Exception(
+            "is_snapshot_on_nfs works only against nfs secondary storage. found %s" % str(secondaryStore.providername))
+
+    qresultset = dbconn.execute(
+                        "select id from snapshots where uuid = '%s';" \
+                        % str(snapshotid)
+                        )
+    if len(qresultset) == 0:
+        raise Exception(
+            "No snapshot found in cloudstack with id %s" % snapshotid)
+
+
+    snapshotid = qresultset[0][0]
+    qresultset = dbconn.execute(
+        "select install_path from snapshot_store_ref where snapshot_id='%s' and store_role='Image';" % snapshotid
+    )
+
+    assert isinstance(qresultset, list), "Invalid db query response for snapshot %s" % snapshotid
+    assert len(qresultset) != 0, "No such snapshot %s found in the cloudstack db" % snapshotid
+
+    snapshotPath = qresultset[0][0]
+
+    nfsurl = secondaryStore.url
+    # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test']
+    from urllib2 import urlparse
+    parse_url = urlparse.urlsplit(nfsurl, scheme='nfs')
+    host, path = parse_url.netloc, parse_url.path
+
+    if not config.mgtSvr:
+        raise Exception("Your marvin configuration does not contain mgmt server credentials")
+    host, user, passwd = config.mgtSvr[0].mgtSvrIp, config.mgtSvr[0].user, config.mgtSvr[0].passwd
+
+    try:
+        ssh_client = remoteSSHClient(
+            host,
+            22,
+            user,
+            passwd,
+        )
+        cmds = [
+                "mkdir -p %s /mnt/tmp",
+                "mount -t %s %s:%s /mnt/tmp" % (
+                    'nfs',
+                    host,
+                    path,
+                    ),
+                "test -f %s && echo 'snapshot exists'" % (
+                    os.path.join("/mnt/tmp", snapshotPath)
+                    ),
+            ]
+
+        for c in cmds:
+            result = ssh_client.execute(c)
+
+        # Unmount the Sec Storage
+        cmds = [
+                "cd",
+                "umount /mnt/tmp",
+            ]
+        for c in cmds:
+            ssh_client.execute(c)
+    except Exception as e:
+        raise Exception("SSH failed for management server: %s - %s" %
+                      (config[0].mgtSvrIp, e))
+    return 'snapshot exists' in result


[23/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: fix marvin build and code generation

- generate code using generate/ module but triggered from basedir/marvin
- fix the pom to be the same as before, use codegenerator
- fix simulator build by removing ConfigDepot bean already injected as
  part of applicationContext.xml

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/7085916f
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/7085916f
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/7085916f

Branch: refs/heads/marvin-refactor
Commit: 7085916f2593dc3b9919357f4e01ea0b7c5c10d8
Parents: f8958bd
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Tue Sep 10 12:28:02 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:39 2013 +0530

----------------------------------------------------------------------
 .../tomcatconf/simulatorComponentContext.xml.in |   1 -
 tools/marvin/marvin/codegenerator.py            | 101 +++++++++++++++++++
 tools/marvin/marvin/entity/cloudstackentity.py  |  25 -----
 tools/marvin/marvin/generate/apitoentity.py     |  44 +-------
 tools/marvin/marvin/generate/xmltoapi.py        |  48 ---------
 tools/marvin/pom.xml                            |   2 +-
 6 files changed, 107 insertions(+), 114 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7085916f/client/tomcatconf/simulatorComponentContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/simulatorComponentContext.xml.in b/client/tomcatconf/simulatorComponentContext.xml.in
index 82ff433..bc3599f 100644
--- a/client/tomcatconf/simulatorComponentContext.xml.in
+++ b/client/tomcatconf/simulatorComponentContext.xml.in
@@ -281,5 +281,4 @@
   </bean>
 
   <bean id="messageBus" class = "org.apache.cloudstack.framework.messagebus.MessageBusBase" />
-  <bean id="configDepot" class = "org.apache.cloudstack.framework.config.ConfigDepotImpl" />
 </beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7085916f/tools/marvin/marvin/codegenerator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/codegenerator.py b/tools/marvin/marvin/codegenerator.py
new file mode 100644
index 0000000..a736039
--- /dev/null
+++ b/tools/marvin/marvin/codegenerator.py
@@ -0,0 +1,101 @@
+# 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.
+
+import os
+import sys
+from argparse import ArgumentParser
+from generate.xmltoapi import codeGenerator
+from generate.apitoentity import generate
+
+def get_api_cmds():
+    """ Returns the API cmdlet instances
+
+    @return: instances of all the API commands exposed by CloudStack
+    """
+    namespace = {}
+    execfile('cloudstackAPI/__init__.py', namespace)
+    api_classes = __import__('cloudstackAPI', globals().update(namespace), fromlist=['*'], level=-1)
+
+
+    cmdlist = map(
+        lambda f: getattr(api_classes, f),
+        filter(
+            lambda t: t.startswith('__') == False,
+            dir(api_classes)
+        )
+    )
+    cmdlist = filter(
+        lambda g: g is not None,
+        cmdlist
+    )
+    clslist = map(
+        lambda g: getattr(g, g.__name__.split('.')[-1] + 'Cmd'),
+        filter(
+            lambda h: h.__name__.split('.')[-1] not in ['baseCmd', 'baseResponse', 'cloudstackAPIClient'],
+            cmdlist
+        )
+    )
+    cmdlets = map(lambda t: t(), clslist)
+    return cmdlets
+
+if __name__ == "__main__":
+    parser = ArgumentParser()
+    parser.add_argument("-o", "--output", dest="output",
+                      help="The path to the generated code entities, default\
+ is .")
+    parser.add_argument("-s", "--specfile", dest="spec",
+                      help="The path and name of the api spec xml file,\
+ default is /etc/cloud/cli/commands.xml")
+    parser.add_argument("-e", "--endpoint", dest="endpoint",
+                      help="The endpoint mgmt server (with open 8096) where\
+ apis are discovered, default is localhost")
+    parser.add_argument("-y", "--entity", dest="entity", action="store_true",
+                      help="Generate entity based classes")
+
+    options = parser.parse_args()
+
+    folder = "."
+    if options.output is not None:
+        folder = options.output
+    apiModule = folder + "/cloudstackAPI"
+    if not os.path.exists(apiModule):
+        try:
+            os.mkdir(apiModule)
+        except:
+            print "Failed to create folder %s, due to %s" % (apiModule,
+                                                             sys.exc_info())
+            print parser.print_help()
+            exit(2)
+
+    apiSpecFile = "/etc/cloud/cli/commands.xml"
+    if options.spec is not None:
+        apiSpecFile = options.spec
+        if not os.path.exists(apiSpecFile):
+            print "the spec file %s does not exists" % apiSpecFile
+            print parser.print_help()
+            exit(1)
+
+    cg = codeGenerator(apiModule)
+    if options.spec is not None:
+        cg.generateCodeFromXML(apiSpecFile)
+    elif options.endpoint is not None:
+        endpointUrl = 'http://%s:8096/client/api?command=listApis&\
+response=json' % options.endpoint
+        cg.generateCodeFromJSON(endpointUrl)
+
+    if options.entity:
+        generate(get_api_cmds())
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7085916f/tools/marvin/marvin/entity/cloudstackentity.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/entity/cloudstackentity.py b/tools/marvin/marvin/entity/cloudstackentity.py
deleted file mode 100644
index b7091de..0000000
--- a/tools/marvin/marvin/entity/cloudstackentity.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# 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.
-
-cloudstack_version = "4.2.0"
-
-class CloudStackEntity(object):
-
-    __version__ = cloudstack_version
-
-    def getVersion(self):
-        return self.__version__

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7085916f/tools/marvin/marvin/generate/apitoentity.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/apitoentity.py b/tools/marvin/marvin/generate/apitoentity.py
index 0be5d9a..90b9eb2 100644
--- a/tools/marvin/marvin/generate/apitoentity.py
+++ b/tools/marvin/marvin/generate/apitoentity.py
@@ -38,45 +38,14 @@ LICENSE = """# Licensed to the Apache Software Foundation (ASF) under one
 # under the License.
 """
 
-def get_api_cmds():
-    """ Returns the API cmdlet instances
-
-    @return: instances of all the API commands exposed by CloudStack
-    """
-    namespace = {}
-    execfile('cloudstackAPI/__init__.py', namespace)
-    api_classes = __import__('cloudstackAPI', globals().update(namespace), fromlist=['*'], level=-1)
-
-
-    cmdlist = map(
-        lambda f: getattr(api_classes, f),
-        filter(
-            lambda t: t.startswith('__') == False,
-            dir(api_classes)
-        )
-    )
-    cmdlist = filter(
-        lambda g: g is not None,
-        cmdlist
-    )
-    clslist = map(
-        lambda g: getattr(g, g.__name__.split('.')[-1] + 'Cmd'),
-        filter(
-            lambda h: h.__name__.split('.')[-1] not in ['baseCmd', 'baseResponse', 'cloudstackAPIClient'],
-            cmdlist
-        )
-    )
-    cmdlets = map(lambda t: t(), clslist)
-    return cmdlets
-
-def get_entity_action_map():
+def get_entity_action_map(apimodules):
     """ Inspect cloudstack api and return a map of the Entity against the actions
     along with the required arguments to make the action call
 
     @return: Dictionary of Entity { "verb" : [required] }
     eg: VirtualMachine { "deploy" : [templateid, serviceoffering, zoneid, etc] }
     """
-    cmdlets = sorted(filter(lambda api: api.__class__.__name__ not in skip_list(), get_api_cmds()),
+    cmdlets = sorted(filter(lambda api: api.__class__.__name__ not in skip_list(), apimodules),
         key=lambda k: get_verb_and_entity(k)[1])
 
     entities = {}
@@ -109,13 +78,14 @@ def write(entity_or_factory, module):
         writer.write(LICENSE)
         writer.write(entity_or_factory.__str__())
 
-def generate(entities):
+def generate(api):
     """
     Writes the collected entity classes
 
-    @param entities: dictionary of entities and the verbs acting on them
+    @param api: api cmdlet modules read from cloudstackAPI/__init__.py
     @return:
     """
+    entities = get_entity_action_map(api)
     for entity, actions in entities.iteritems():
         e = Entity()
         f = Factory()
@@ -125,7 +95,3 @@ def generate(entities):
 
         write(e, module='entity')
         write(f, module='factory')
-
-if __name__ == '__main__':
-    entities = get_entity_action_map()
-    generate(entities)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7085916f/tools/marvin/marvin/generate/xmltoapi.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/xmltoapi.py b/tools/marvin/marvin/generate/xmltoapi.py
index 458873a..7021b3e 100644
--- a/tools/marvin/marvin/generate/xmltoapi.py
+++ b/tools/marvin/marvin/generate/xmltoapi.py
@@ -438,51 +438,3 @@ class codeGenerator(object):
 def getText(elements):
     return elements[0].childNodes[0].nodeValue.strip()
 
-if __name__ == "__main__":
-    parser = ArgumentParser()
-    parser.add_argument("-o", "--output", dest="output",
-                      help="The path to the generated code entities, default\
- is .")
-    parser.add_argument("-s", "--specfile", dest="spec",
-                      help="The path and name of the api spec xml file,\
- default is /etc/cloud/cli/commands.xml")
-    parser.add_argument("-e", "--endpoint", dest="endpoint",
-                      help="The endpoint mgmt server (with open 8096) where\
- apis are discovered, default is localhost")
-    parser.add_argument("-y", "--entity", dest="entity", action="store_true",
-                      help="Generate entity based classes")
-
-    options = parser.parse_args()
-
-    folder = "."
-    if options.output is not None:
-        folder = options.output
-    apiModule = folder + "/cloudstackAPI"
-    if not os.path.exists(apiModule):
-        try:
-            os.mkdir(apiModule)
-        except:
-            print "Failed to create folder %s, due to %s" % (apiModule,
-                                                             sys.exc_info())
-            print parser.print_help()
-            exit(2)
-
-    apiSpecFile = "/etc/cloud/cli/commands.xml"
-    if options.spec is not None:
-        apiSpecFile = options.spec
-        if not os.path.exists(apiSpecFile):
-            print "the spec file %s does not exists" % apiSpecFile
-            print parser.print_help()
-            exit(1)
-
-    cg = codeGenerator(apiModule)
-    if options.spec is not None:
-        cg.generateCodeFromXML(apiSpecFile)
-    elif options.endpoint is not None:
-        endpointUrl = 'http://%s:8096/client/api?command=listApis&\
-response=json' % options.endpoint
-        cg.generateCodeFromJSON(endpointUrl)
-
-    if options.entity:
-        entities = get_entity_action_map()
-        generate(entities, "entity")

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7085916f/tools/marvin/pom.xml
----------------------------------------------------------------------
diff --git a/tools/marvin/pom.xml b/tools/marvin/pom.xml
index 872921d..25909b3 100644
--- a/tools/marvin/pom.xml
+++ b/tools/marvin/pom.xml
@@ -55,7 +55,7 @@
               <workingDirectory>${basedir}/marvin</workingDirectory>
               <executable>python</executable>
               <arguments>
-                <argument>generate/xmltoapi.py</argument>
+                <argument>codegenerator.py</argument>
                 <argument>-s</argument>
                 <argument>${basedir}/commands.xml</argument>
               </arguments>


[34/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
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)


[17/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: correcting references to random_gen

random_gen moves to marvin.legacy.utils from marvin.utils

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/b19faeaf
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/b19faeaf
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/b19faeaf

Branch: refs/heads/marvin-refactor
Commit: b19faeaf7dc76b8f1d46a90d7982f27802bc3a54
Parents: 8cdac50
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Sat Sep 7 11:01:07 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:27 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/factory/data/account.py              | 2 +-
 tools/marvin/marvin/factory/data/cluster.py              | 2 +-
 tools/marvin/marvin/factory/data/diskoffering.py         | 2 +-
 tools/marvin/marvin/factory/data/serviceoffering.py      | 2 +-
 tools/marvin/marvin/factory/data/user.py                 | 2 +-
 tools/marvin/marvin/factory/data/vm.py                   | 2 --
 tools/marvin/marvin/factory/data/zone.py                 | 2 +-
 tools/marvin/marvin/marvinPlugin.py                      | 3 +--
 tools/marvin/marvin/sandbox/advanced/advanced_env.py     | 4 +---
 tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py | 4 +---
 tools/marvin/marvin/sandbox/basic/basic_env.py           | 4 +---
 11 files changed, 10 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b19faeaf/tools/marvin/marvin/factory/data/account.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/account.py b/tools/marvin/marvin/factory/data/account.py
index b0fcd7b..97caf16 100644
--- a/tools/marvin/marvin/factory/data/account.py
+++ b/tools/marvin/marvin/factory/data/account.py
@@ -17,7 +17,7 @@
 
 import factory
 from marvin.factory.account import AccountFactory
-from marvin.utils import random_gen
+from marvin.legacy.utils import random_gen
 
 class UserAccountFactory(AccountFactory):
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b19faeaf/tools/marvin/marvin/factory/data/cluster.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/cluster.py b/tools/marvin/marvin/factory/data/cluster.py
index 321252b..c51321d 100644
--- a/tools/marvin/marvin/factory/data/cluster.py
+++ b/tools/marvin/marvin/factory/data/cluster.py
@@ -16,7 +16,7 @@
 # under the License.
 
 import factory
-from marvin.utils import random_gen
+from marvin.legacy.utils import random_gen
 from marvin.factory.cluster import ClusterFactory
 
 class XenClusterFactory(ClusterFactory):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b19faeaf/tools/marvin/marvin/factory/data/diskoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/diskoffering.py b/tools/marvin/marvin/factory/data/diskoffering.py
index ee58c27..48526b8 100644
--- a/tools/marvin/marvin/factory/data/diskoffering.py
+++ b/tools/marvin/marvin/factory/data/diskoffering.py
@@ -17,7 +17,7 @@
 
 import factory
 from marvin.factory.diskoffering import DiskOfferingFactory
-from marvin.utils import random_gen
+from marvin.legacy.utils import random_gen
 
 class SharedDiskOfferingFactory(DiskOfferingFactory):
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b19faeaf/tools/marvin/marvin/factory/data/serviceoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/serviceoffering.py b/tools/marvin/marvin/factory/data/serviceoffering.py
index b3a7639..955657e 100644
--- a/tools/marvin/marvin/factory/data/serviceoffering.py
+++ b/tools/marvin/marvin/factory/data/serviceoffering.py
@@ -17,7 +17,7 @@
 
 import factory
 from marvin.factory.serviceoffering import ServiceOfferingFactory
-from marvin.utils import random_gen
+from marvin.legacy.utils import random_gen
 
 class SmallServiceOfferingFactory(ServiceOfferingFactory):
     cpunumber = 1

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b19faeaf/tools/marvin/marvin/factory/data/user.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/user.py b/tools/marvin/marvin/factory/data/user.py
index d3bde0d..d5fa456 100644
--- a/tools/marvin/marvin/factory/data/user.py
+++ b/tools/marvin/marvin/factory/data/user.py
@@ -18,7 +18,7 @@
 import factory
 from marvin.factory.user import UserFactory
 from marvin.factory.data.account import UserAccountFactory
-from marvin.utils import random_gen
+from marvin.legacy.utils import random_gen
 
 class UserFactory(UserFactory):
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b19faeaf/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 a938603..0d7aac0 100644
--- a/tools/marvin/marvin/factory/data/vm.py
+++ b/tools/marvin/marvin/factory/data/vm.py
@@ -15,9 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import factory
 from marvin.factory.virtualmachine import VirtualMachineFactory
-from marvin.utils import random_gen
 
 
 class VirtualMachineIsolatedNetwork(VirtualMachineFactory):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b19faeaf/tools/marvin/marvin/factory/data/zone.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/zone.py b/tools/marvin/marvin/factory/data/zone.py
index 2936c0b..67c1cb4 100644
--- a/tools/marvin/marvin/factory/data/zone.py
+++ b/tools/marvin/marvin/factory/data/zone.py
@@ -17,7 +17,7 @@
 
 import factory
 from marvin.factory.zone import ZoneFactory
-from marvin.utils import random_gen
+from marvin.legacy.utils import random_gen
 
 class AdvancedZoneFactory(ZoneFactory):
     name = factory.Sequence(lambda n: "advzone" + random_gen())

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b19faeaf/tools/marvin/marvin/marvinPlugin.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py
index aded17c..b98b5a6 100644
--- a/tools/marvin/marvin/marvinPlugin.py
+++ b/tools/marvin/marvin/marvinPlugin.py
@@ -15,13 +15,12 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import marvin
 import sys
 import logging
 import nose.core
 from marvin.cloudstackTestCase import cloudstackTestCase
-from marvin import deployDataCenter
 from nose.plugins.base import Plugin
+from marvin.deployer import deployDataCenter
 
 
 class MarvinPlugin(Plugin):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b19faeaf/tools/marvin/marvin/sandbox/advanced/advanced_env.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/advanced/advanced_env.py b/tools/marvin/marvin/sandbox/advanced/advanced_env.py
index 4a2fbfb..5483ad7 100644
--- a/tools/marvin/marvin/sandbox/advanced/advanced_env.py
+++ b/tools/marvin/marvin/sandbox/advanced/advanced_env.py
@@ -22,11 +22,9 @@
 #    * Only a sandbox
 ############################################################
 '''
-import random
-import marvin
 from ConfigParser import SafeConfigParser
 from optparse import OptionParser
-from marvin.configGenerator import *
+from marvin.deployer.configGenerator import *
 
 
 def getGlobalSettings(config):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b19faeaf/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py b/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py
index 9cf4a0a..a44bf95 100644
--- a/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py
+++ b/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py
@@ -22,11 +22,9 @@
 #    * Only a sandbox
 ############################################################
 '''
-import random
-import marvin
 from ConfigParser import SafeConfigParser
 from optparse import OptionParser
-from marvin.configGenerator import *
+from marvin.deployer.configGenerator import *
 
 
 def getGlobalSettings(config):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b19faeaf/tools/marvin/marvin/sandbox/basic/basic_env.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/basic/basic_env.py b/tools/marvin/marvin/sandbox/basic/basic_env.py
index bf106fc..c60b41d 100644
--- a/tools/marvin/marvin/sandbox/basic/basic_env.py
+++ b/tools/marvin/marvin/sandbox/basic/basic_env.py
@@ -23,11 +23,9 @@
 #    * Only a sandbox
 ############################################################
 '''
-import random
-import marvin
 from ConfigParser import SafeConfigParser
 from optparse import OptionParser
-from marvin.configGenerator import *
+from marvin.deployer.configGenerator import *
 
 
 def getGlobalSettings(config):


[21/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: UnitTests for NetworkFactory

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/0e2e5ed0
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/0e2e5ed0
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/0e2e5ed0

Branch: refs/heads/marvin-refactor
Commit: 0e2e5ed02b8f1f88f41f0383e0c81be35043bcb4
Parents: 32a42f4
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Sat Sep 7 11:11:59 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:35 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/test/test_factories.py | 82 +++++++++++++++++--------
 1 file changed, 57 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0e2e5ed0/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 e415231..bf6f228 100644
--- a/tools/marvin/marvin/test/test_factories.py
+++ b/tools/marvin/marvin/test/test_factories.py
@@ -17,6 +17,7 @@
 
 import unittest
 import logging
+from nose.plugins.attrib import attr
 
 from marvin.cloudstackTestClient import cloudstackTestClient
 
@@ -25,6 +26,7 @@ from marvin.factory.data.serviceoffering import *
 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.virtualmachine import *
 
@@ -36,6 +38,9 @@ from marvin.entity.user import User
 from marvin.entity.network import Network
 
 from marvin.entity.ipaddress import IpAddress
+
+
+
 class BuildVsCreateStrategyTest(unittest.TestCase):
     def setUp(self):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
@@ -44,11 +49,11 @@ class BuildVsCreateStrategyTest(unittest.TestCase):
         pass
 
     def test_buildUserAccountFactory(self):
-        af = UserAccountFactory()
+        af = UserAccountFactory.build()
         self.assert_(af is not None, msg="Account factory didn't initialize")
 
     def test_createAccountFactory(self):
-        af = UserAccountFactory.create(apiclient=self.apiClient)
+        af = UserAccountFactory(apiclient=self.apiClient)
         self.assert_(isinstance(af, Account))
         self.assert_(af.id is not None, msg="Account creation failed")
         self.assert_(af.domain is not None, msg="Account belongs to no domain")
@@ -59,18 +64,19 @@ class AccountFactoryTest(unittest.TestCase):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def test_adminAccountFactory(self):
-        accnt = AdminAccountFactory.create(apiclient=self.apiClient)
+        accnt = AdminAccountFactory(apiclient=self.apiClient)
         self.assert_(accnt is not None, msg="no account created by factory")
         self.assert_(accnt.name is not None)
 
     def test_userAccountFactoryCustomArgs(self):
-        accnt = UserAccountFactory.create(apiclient=self.apiClient, firstname='test', lastname='test')
+        accnt = UserAccountFactory(apiclient=self.apiClient, firstname='test', lastname='test')
         a = accnt.list(apiclient=self.apiClient, account=accnt.name, domainid=accnt.domainid)
         self.assert_(accnt is not None, msg="no account created by factory")
         self.assert_(accnt.name is not None)
 
     def test_disableAccountPostFactoryGeneration(self):
-        domadmin = DomainAdminFactory.create(apiclient=self.apiClient)
+        domadmin = DomainAdminFactory(apiclient=self.apiClient)
+        a = Account.list(apiclient=self.apiClient, id=domadmin.id)
         self.assert_(domadmin is not None, msg="no account was created")
         domadmin.disable(self.apiClient, lock=True, account=domadmin.name, domainid=domadmin.domainid)
 
@@ -83,7 +89,7 @@ class ServiceOfferingFactoryTest(unittest.TestCase):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def test_serviceOfferingFactory(self):
-        soffering = SmallServiceOfferingFactory.create(apiclient=self.apiClient)
+        soffering = SmallServiceOfferingFactory(apiclient=self.apiClient)
         self.assert_(soffering is not None, msg="no service offering was created")
         self.assert_(soffering.name is not None, msg="error in service offering factory creation")
 
@@ -97,12 +103,12 @@ class NetworkOfferingFactoryTest(unittest.TestCase):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def test_defaultSourceNatOfferingFactory(self):
-        snatOffering = DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory.create(apiclient=self.apiClient)
+        snatOffering = DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory(apiclient=self.apiClient)
         self.assert_(snatOffering is not None, msg = "no network offering was created")
         self.assert_(snatOffering.name is not None, msg="error in network offering creation")
 
     def test_defaultSGOfferingEnable(self):
-        sgOffering = DefaultSharedNetworkOfferingWithSGServiceFactory.create(apiclient=self.apiClient)
+        sgOffering = DefaultSharedNetworkOfferingWithSGServiceFactory(apiclient=self.apiClient)
         sgOffering.update(self.apiClient, state='Enabled', name=sgOffering.name, id=sgOffering.id)
 
     def tearDown(self):
@@ -114,24 +120,25 @@ class VirtualMachineFactoryTest(unittest.TestCase):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def tearDown(self):
-        pass
+        self.vm.destroy(apiclient=self.apiClient)
 
     def test_virtualMachineDeploy(self):
-        accnt = UserAccountFactory.create(apiclient=self.apiClient)
-        service = SmallServiceOfferingFactory.create(apiclient=self.apiClient)
-        tf = DefaultBuiltInTemplateFactory.build() #FIXME: Using build() strategy is confusing
+        accnt = UserAccountFactory(apiclient=self.apiClient)
+        service = SmallServiceOfferingFactory(apiclient=self.apiClient)
+        tf = DefaultBuiltInTemplateFactory.build()
         zones = Zone.list(apiclient=self.apiClient)
         template = Template.list(apiclient=self.apiClient,
                                  templatefilter="featured",
                                  ostype = tf.ostype,
                                  zoneid = zones[0].id)
-        vm = VirtualMachineFactory.create(apiclient=self.apiClient,
+        self.vm = VirtualMachineFactory(apiclient=self.apiClient,
                                           serviceofferingid = service.id,
                                           templateid = template[0].id,
                                           zoneid = zones[0].id,
                                           account = accnt.name,
                                           domainid = accnt.domainid)
-        vm.destroy(apiclient=self.apiClient)
+
+
 
 class UserFactorySubFactoryTest(unittest.TestCase):
     def setUp(self):
@@ -150,36 +157,61 @@ class UserFactorySubFactoryTest(unittest.TestCase):
         caller is not to create the user before creating the account
         @return:
         """
-        uf = UserFactory.create(apiclient=self.apiClient)
+        uf = UserFactory(apiclient=self.apiClient)
         user = User.list(apiclient=self.apiClient, username=uf.username)
         self.assert_(uf.username == user[0].username, msg="Usernames don't match")
 
 
 class IpAddressFactoryTest(unittest.TestCase):
     def setUp(self):
-        self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
+        self.apiClient = cloudstackTestClient(mgtSvr='localhost',
+            logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def tearDown(self):
         self.vm.destroy(apiclient=self.apiClient)
 
     def test_associateIpAddressToNetwork(self):
-        accnt = UserAccountFactory.create(apiclient=self.apiClient)
-        self.assert_(accnt is not None)
+        # user account where we run test
+        accnt = UserAccountFactory(apiclient=self.apiClient)
         self.assert_(isinstance(accnt, Account))
+
+        # get required arguments - templates, service offerings, zone
         service = ServiceOffering.list(apiclient=self.apiClient, displaytext='Small')
-        self.assert_(len(service) > 0)
         template = Template.list(apiclient=self.apiClient, templatefilter="featured")
-        self.assert_(len(template) > 0)
         zones = Zone.list(apiclient=self.apiClient)
-        self.vm = VirtualMachineFactory.create(
+
+        self.vm = VirtualMachineFactory(
             apiclient=self.apiClient,
-            serviceofferingid = service[0].id,
-            templateid = template[0].id,
-            zoneid = zones[0].id,
+            serviceofferingid=service[0].id,
+            templateid=template[0].id,
+            zoneid=zones[0].id,
             account=accnt.name,
             domainid=accnt.domainid)
+
         all_ips = IpAddress.listPublic(apiclient=self.apiClient)
         firstip = all_ips[0]
-        networks = Network.list(apiclient=self.apiClient, account = accnt.name, domainid = accnt.domainid)
+        networks = Network.list(apiclient=self.apiClient,
+            account = accnt.name, domainid = accnt.domainid)
         firstip.associate(apiclient=self.apiClient, networkid = networks[0].id)
 
+
+class NetworkFactoryTest(unittest.TestCase):
+    def setUp(self):
+        self.apiClient = cloudstackTestClient(mgtSvr='localhost',
+            logging=logging.getLogger('factory.cloudstack')).getApiClient()
+
+    def tearDown(self):
+        pass
+
+    @attr(tags='network')
+    def test_isolatedGuestNetwork(self):
+        """Test to create a network within a guest account
+        @return:
+        """
+        accnt = UserAccountFactory(apiclient=self.apiClient)
+        zones = Zone.list(apiclient=self.apiClient)
+        network = GuestIsolatedNetworkFactory(
+            apiclient=self.apiClient,
+            zoneid=zones[0].id,
+            )
+        self.debug("network created with id, name" %(network.id, network.name))
\ No newline at end of file


[39/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: fix client pom

extraneous license header in <project> tag

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/746399ab
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/746399ab
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/746399ab

Branch: refs/heads/marvin-refactor
Commit: 746399ab4b9c0e58ecf6b273cd44cef8ccf23808
Parents: 45afa94
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Mon Sep 30 10:16:59 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:03 2013 +0530

----------------------------------------------------------------------
 client/pom.xml | 10 ----------
 1 file changed, 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/746399ab/client/pom.xml
----------------------------------------------------------------------
diff --git a/client/pom.xml b/client/pom.xml
index 3fc8c67..639a70e 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -7,16 +7,6 @@
   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. -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  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. -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>


[18/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: network data factory

network can create isolated guest and shared guest networks. the network
object will inturn use the default networkofferings which are
auto-enabeld by their postgenerators

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/ffb7820a
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/ffb7820a
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/ffb7820a

Branch: refs/heads/marvin-refactor
Commit: ffb7820a869a117506c89554563ae59fd41a7348
Parents: b19faea
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Sat Sep 7 11:02:18 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:28 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/factory/data/network.py     | 48 ++++++++++++++++++++
 .../marvin/factory/data/networkoffering.py      | 44 +++++++++++++++++-
 2 files changed, 91 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ffb7820a/tools/marvin/marvin/factory/data/network.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/network.py b/tools/marvin/marvin/factory/data/network.py
new file mode 100644
index 0000000..ad6101c
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/network.py
@@ -0,0 +1,48 @@
+# 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.
+
+import factory
+from marvin.legacy.utils import random_gen
+from marvin.factory.network import NetworkFactory
+from marvin.factory.data.networkoffering import DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory
+from marvin.factory.data.networkoffering import DefaultSharedNetworkOfferingFactory
+
+class GuestIsolatedNetworkFactory(NetworkFactory):
+
+    displaytext = factory.Sequence(lambda n: 'GuestIsolatedNetwork-%s' % random_gen())
+    name = factory.Sequence(lambda n: 'GuestIsolatedNetwork-%s' % random_gen())
+    networkoffering =\
+    factory.SubFactory(
+        DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory,
+        apiclient=factory.SelfAttribute('..apiclient'),
+        name=factory.Sequence(lambda n: 'GuestIsolatedNetworkOffering-%s' % random_gen()),
+    )
+    networkofferingid = factory.LazyAttribute(lambda no: no.networkoffering.id if no.networkoffering else no.networkoffering)
+    zoneid = None
+
+class SharedNetworkFactory(NetworkFactory):
+
+    displaytext = factory.Sequence(lambda n: 'SharedNetwork-%s' % random_gen())
+    name = factory.Sequence(lambda n: 'SharedNetwork-%d' % random_gen())
+    networkoffering = \
+        factory.SubFactory(
+            DefaultSharedNetworkOfferingFactory,
+            apiclient=factory.SelfAttribute('..apiclient'),
+            name=factory.Sequence(lambda n: 'SharedNetworkOffering-%s' % random_gen())
+        )
+    networkofferingid = factory.LazyAttribute(lambda no: no.networkoffering.id if not no.networkoffering else no.networkoffering)
+    zoneid = None
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ffb7820a/tools/marvin/marvin/factory/data/networkoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/networkoffering.py b/tools/marvin/marvin/factory/data/networkoffering.py
index 4e54c4b..829aee0 100644
--- a/tools/marvin/marvin/factory/data/networkoffering.py
+++ b/tools/marvin/marvin/factory/data/networkoffering.py
@@ -17,7 +17,7 @@
 
 import factory
 from marvin.factory.networkoffering import NetworkOfferingFactory
-from marvin.utils import random_gen
+from marvin.legacy.utils import random_gen
 
 
 class DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory(NetworkOfferingFactory):
@@ -43,6 +43,12 @@ class DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory(NetworkOfferingF
                 'provider': 'VirtualRouter'
             }
         )
+    # enable the offering post generation
+    factory.PostGenerationMethodCall('update',
+        factory.SelfAttribute('..apiclient'),
+        id=factory.SelfAttribute('..id'),
+        state='Enabled')
+
 
 
 class DefaultSharedNetworkOfferingWithSGServiceFactory(NetworkOfferingFactory):
@@ -71,3 +77,39 @@ class DefaultSharedNetworkOfferingWithSGServiceFactory(NetworkOfferingFactory):
                 'provider': provider
             }
         )
+
+    # enable the offering post generation
+    factory.PostGenerationMethodCall('update',
+        factory.SelfAttribute('..apiclient'),
+        id=factory.SelfAttribute('..id'),
+        state='Enabled')
+
+
+class DefaultSharedNetworkOfferingFactory(NetworkOfferingFactory):
+
+    displaytext = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingFactory-%d" % n)
+    name = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingFactory-%d" % n)
+    availability = "Optional"
+    supportedservices = "Dns,Dhcp,UserData"
+    guestiptype = "Shared"
+    traffictype = "GUEST"
+
+    specifyVlan = True
+    specifyIpRanges = True
+    isPersistent = False
+    conserveMode = True
+
+    serviceProviderList = []
+    for service in map(lambda l: l.strip(' '), supportedservices.split(',')):
+        serviceProviderList.append(
+            {
+                'service': service,
+                'provider': 'VirtualRouter'
+            }
+        )
+
+    # enable the offering post generation
+    factory.PostGenerationMethodCall('update',
+        factory.SelfAttribute('..apiclient'),
+        id=factory.SelfAttribute('..id'),
+        state='Enabled')


[49/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: remove the entity from passing to the apiserver

entity attributes derived for each API should not be sent to the API
server as it messes with the signature generation.

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/167e5f68
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/167e5f68
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/167e5f68

Branch: refs/heads/marvin-refactor
Commit: 167e5f6896018154890b20f805701cbb0a5aac4b
Parents: a801696
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Oct 2 20:16:41 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:17 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/cloudstackConnection.py | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/167e5f68/tools/marvin/marvin/cloudstackConnection.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py
index 86c989c..e82e527 100644
--- a/tools/marvin/marvin/cloudstackConnection.py
+++ b/tools/marvin/marvin/cloudstackConnection.py
@@ -182,6 +182,8 @@ class CloudConnection(object):
                     isAsync = getattr(cmd, attribute)
                 elif attribute == "required":
                     required = getattr(cmd, attribute)
+                elif attribute == "entity":
+                    continue
                 else:
                     requests[attribute] = getattr(cmd, attribute)
 


[19/50] [abbrv] marvin_refactor: remove redundant examples from sandbox

Posted by ts...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/32a42f4f/tools/marvin/marvin/sandbox/demo/simulator/testcase/test_vm_life_cycle.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/demo/simulator/testcase/test_vm_life_cycle.py b/tools/marvin/marvin/sandbox/demo/simulator/testcase/test_vm_life_cycle.py
deleted file mode 100644
index 9bc7e14..0000000
--- a/tools/marvin/marvin/sandbox/demo/simulator/testcase/test_vm_life_cycle.py
+++ /dev/null
@@ -1,524 +0,0 @@
-# -*- encoding: utf-8 -*-
-# 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.
-
-""" BVT tests for Virtual Machine Life Cycle
-"""
-#Import Local Modules
-import marvin
-from marvin.cloudstackTestCase import *
-from marvin.cloudstackAPI import *
-from marvin.remoteSSHClient import remoteSSHClient
-
-from testcase.libs.utils import *
-from testcase.libs.base import *
-from testcase.libs.common import *
-
-#Import System modules
-import time
-
-class Services:
-    """Test VM Life Cycle Services
-    """
-
-    def __init__(self):
-        self.services = {
-                "disk_offering":{
-                    "displaytext": "Small",
-                    "name": "Small",
-                    "disksize": 1
-                },
-                "account": {
-                    "email": "test@test.com",
-                    "firstname": "Test",
-                    "lastname": "User",
-                    "username": "test",
-                    # Random characters are appended in create account to 
-                    # ensure unique username generated each time
-                    "password": "password",
-                },
-                "small":
-                # Create a small virtual machine instance with disk offering 
-                {
-                    "displayname": "testserver",
-                    "username": "root", # VM creds for SSH
-                    "password": "password",
-                    "ssh_port": 22,
-                    "hypervisor": 'XenServer',
-                    "privateport": 22,
-                    "publicport": 22,
-                    "protocol": 'TCP',
-                },
-                "medium":   # Create a medium virtual machine instance 
-                {
-                    "displayname": "testserver",
-                    "username": "root",
-                    "password": "password",
-                    "ssh_port": 22,
-                    "hypervisor": 'XenServer',
-                    "privateport": 22,
-                    "publicport": 22,
-                    "protocol": 'TCP',
-                },
-                "service_offerings":
-                {
-                 "tiny":
-                   {
-                        "name": "Tiny Instance",
-                        "displaytext": "Tiny Instance",
-                        "cpunumber": 1,
-                        "cpuspeed": 100, # in MHz
-                        "memory": 64, # In MBs
-                    },
-                 "small":
-                    {
-                     # Small service offering ID to for change VM 
-                     # service offering from medium to small
-                        "name": "Small Instance",
-                        "displaytext": "Small Instance",
-                        "cpunumber": 1,
-                        "cpuspeed": 500,
-                        "memory": 256
-                    },
-                "medium":
-                    {
-                    # Medium service offering ID to for
-                    # change VM service offering from small to medium
-                        "name": "Medium Instance",
-                        "displaytext": "Medium Instance",
-                        "cpunumber": 1,
-                        "cpuspeed": 1000,
-                        "memory": 1024
-                    }
-                },
-            "sleep": 60,
-            "timeout": 10,
-            #Migrate VM to hostid
-            "ostypeid": 'ccde7156-9b8b-4fb9-bf08-530dedf4dc61',
-            # CentOS 5.3 (64-bit)
-            "mode":'advanced',
-        }
-
-
-class TestDeployVM(cloudstackTestCase):
-
-    def setUp(self):
-
-        self.apiclient = self.testClient.getApiClient()
-        self.dbclient = self.testClient.getDbConnection()
-        self.services = Services().services
-        # Get Zone, Domain and templates
-        domain = get_domain(self.apiclient, self.services)
-        zone = get_zone(self.apiclient, self.services)
-
-        template = get_template(
-                            self.apiclient,
-                            zone.id,
-                            self.services["ostypeid"]
-                            )
-        # Set Zones and disk offerings
-        self.services["small"]["zoneid"] = zone.id
-        self.services["small"]["template"] = template.id
-
-        self.services["medium"]["zoneid"] = zone.id
-        self.services["medium"]["template"] = template.id
-
-        # Create Account, VMs, NAT Rules etc
-        self.account = Account.create(
-                            self.apiclient,
-                            self.services["account"],
-                            domainid=domain.id
-                            )
-
-        self.service_offering = ServiceOffering.create(
-                                    self.apiclient,
-                                    self.services["service_offerings"]["tiny"]
-                                    )
-        # Cleanup
-        self.cleanup = [
-                        self.service_offering,
-                        self.account
-                        ]
-
-    def test_deploy_vm(self):
-        """Test Deploy Virtual Machine
-        """
-
-        # Validate the following:
-        # 1. Virtual Machine is accessible via SSH
-        # 2. listVirtualMachines returns accurate information
-        # 3. The Cloud Database contains the valid information
-
-        self.virtual_machine = VirtualMachine.create(
-                                    self.apiclient,
-                                    self.services["small"],
-                                    accountid=self.account.account.name,
-                                    domainid=self.account.account.domainid,
-                                    serviceofferingid=self.service_offering.id
-                                )
-
-        list_vm_response = list_virtual_machines(
-                                                 self.apiclient,
-                                                 id=self.virtual_machine.id
-                                                 )
-
-        self.debug(
-                "Verify listVirtualMachines response for virtual machine: %s" \
-                % self.virtual_machine.id
-            )
-        
-        self.assertEqual(
-                            isinstance(list_vm_response, list),
-                            True,
-                            "Check list response returns a valid list"
-                        )
-        
-        self.assertNotEqual(
-                            len(list_vm_response),
-                            0,
-                            "Check VM available in List Virtual Machines"
-                        )
-        vm_response = list_vm_response[0]
-        
-        self.assertEqual(
-
-                            vm_response.id,
-                            self.virtual_machine.id,
-                            "Check virtual machine id in listVirtualMachines"
-                        )
-
-        self.assertEqual(
-                    vm_response.displayname,
-                    self.virtual_machine.displayname,
-                    "Check virtual machine displayname in listVirtualMachines"
-                    )
-        return
-
-    def tearDown(self):
-        try:
-            cleanup_resources(self.apiclient, self.cleanup)
-        except Exception as e:
-            self.debug("Warning! Exception in tearDown: %s" % e)
-
-
-class TestVMLifeCycle(cloudstackTestCase):
-
-    @classmethod
-    def setUpClass(cls):
-        cls.api_client = super(TestVMLifeCycle, cls).getClsTestClient().getApiClient()
-        cls.services = Services().services
-
-        # Get Zone, Domain and templates
-        domain = get_domain(cls.api_client, cls.services)
-        zone = get_zone(cls.api_client, cls.services)
-        template = get_template(
-                            cls.api_client,
-                            zone.id,
-                            cls.services["ostypeid"]
-                            )
-        # Set Zones and disk offerings
-        cls.services["small"]["zoneid"] = zone.id
-        cls.services["small"]["template"] = template.id
-
-        cls.services["medium"]["zoneid"] = zone.id
-        cls.services["medium"]["template"] = template.id
-
-        # Create VMs, NAT Rules etc
-        cls.account = Account.create(
-                            cls.api_client,
-                            cls.services["account"],
-                            domainid=domain.id
-                            )
-
-        cls.small_offering = ServiceOffering.create(
-                                    cls.api_client,
-                                    cls.services["service_offerings"]["small"]
-                                    )
-
-        cls.medium_offering = ServiceOffering.create(
-                                    cls.api_client,
-                                    cls.services["service_offerings"]["medium"]
-                                    )
-        #create small and large virtual machines
-        cls.small_virtual_machine = VirtualMachine.create(
-                                        cls.api_client,
-                                        cls.services["small"],
-                                        accountid=cls.account.account.name,
-                                        domainid=cls.account.account.domainid,
-                                        serviceofferingid=cls.small_offering.id,
-                                        mode=cls.services["mode"]
-                                        )
-        cls.medium_virtual_machine = VirtualMachine.create(
-                                       cls.api_client,
-                                       cls.services["medium"],
-                                       accountid=cls.account.account.name,
-                                       domainid=cls.account.account.domainid,
-                                       serviceofferingid=cls.medium_offering.id,
-                                       mode=cls.services["mode"]
-                                    )
-        cls.virtual_machine = VirtualMachine.create(
-                                        cls.api_client,
-                                        cls.services["small"],
-                                        accountid=cls.account.account.name,
-                                        domainid=cls.account.account.domainid,
-                                        serviceofferingid=cls.small_offering.id,
-                                        mode=cls.services["mode"]
-                                        )
-        cls._cleanup = [
-                        cls.small_offering,
-                        cls.medium_offering,
-                        cls.account
-                        ]
-
-    @classmethod
-    def tearDownClass(cls):
-        cls.api_client = super(TestVMLifeCycle, cls).getClsTestClient().getApiClient()
-        cleanup_resources(cls.api_client, cls._cleanup)
-        return
-
-    def setUp(self):
-        self.apiclient = self.testClient.getApiClient()
-        self.dbclient = self.testClient.getDbConnection()
-        self.cleanup = []
-
-    def tearDown(self):
-        #Clean up, terminate the created ISOs
-        cleanup_resources(self.apiclient, self.cleanup)
-        return
-
-    def test_01_stop_vm(self):
-        """Test Stop Virtual Machine
-        """
-
-        # Validate the following
-        # 1. Should Not be able to login to the VM.
-        # 2. listVM command should return
-        #    this VM.State of this VM should be ""Stopped"".
-
-        self.debug("Stopping VM - ID: %s" % self.virtual_machine.id)
-        self.small_virtual_machine.stop(self.apiclient)
-
-        list_vm_response = list_virtual_machines(
-                                            self.apiclient,
-                                            id=self.small_virtual_machine.id
-                                            )
-        
-        self.assertEqual(
-                            isinstance(list_vm_response, list),
-                            True,
-                            "Check list response returns a valid list"
-                        )
-        self.assertNotEqual(
-                            len(list_vm_response),
-                            0,
-                            "Check VM available in List Virtual Machines"
-                        )
-
-        self.assertEqual(
-                            list_vm_response[0].state,
-                            "Stopped",
-                            "Check virtual machine is in stopped state"
-                        )
-        return
-
-    def test_02_start_vm(self):
-        """Test Start Virtual Machine
-        """
-        # Validate the following
-        # 1. listVM command should return this VM.State
-        #    of this VM should be Running".
-        
-        self.debug("Starting VM - ID: %s" % self.virtual_machine.id)
-        self.small_virtual_machine.start(self.apiclient)
-
-        list_vm_response = list_virtual_machines(
-                                            self.apiclient,
-                                            id=self.small_virtual_machine.id
-                                            )
-        self.assertEqual(
-                            isinstance(list_vm_response, list),
-                            True,
-                            "Check list response returns a valid list"
-                        )
-        
-        self.assertNotEqual(
-                            len(list_vm_response),
-                            0,
-                            "Check VM avaliable in List Virtual Machines"
-                        )
-
-        self.debug(
-                "Verify listVirtualMachines response for virtual machine: %s" \
-                % self.small_virtual_machine.id
-                )
-        self.assertEqual(
-                            list_vm_response[0].state,
-                            "Running",
-                            "Check virtual machine is in running state"
-                        )
-        return
-
-    def test_04_change_offering_small(self):
-        """Change Offering to a small capacity
-        """
-
-        # Validate the following
-        # 1. Log in to the Vm .We should see that the CPU and memory Info of
-        #    this Vm matches the one specified for "Small" service offering. 
-        # 2. Using  listVM command verify that this Vm 
-        #    has Small service offering Id.
-        
-        self.debug("Stopping VM - ID: %s" % self.medium_virtual_machine.id)
-        
-        self.medium_virtual_machine.stop(self.apiclient)
-        
-        # Poll listVM to ensure VM is stopped properly
-        timeout = self.services["timeout"]
-        
-        while True:
-            time.sleep(self.services["sleep"])
-        
-            # Ensure that VM is in stopped state
-            list_vm_response = list_virtual_machines(
-                                            self.apiclient,
-                                            id=self.medium_virtual_machine.id
-                                            )
-            
-            if isinstance(list_vm_response, list):
-                
-                vm = list_vm_response[0]
-                if vm.state == 'Stopped':
-                    self.debug("VM state: %s" % vm.state)
-                    break
-            
-            if timeout == 0: 
-                    raise Exception(
-                        "Failed to stop VM (ID: %s) in change service offering" % vm.id)
-                    
-            timeout = timeout - 1
-        
-        self.debug("Change Service offering VM - ID: %s" % 
-                                    self.medium_virtual_machine.id)
-        
-        cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd()
-        cmd.id = self.medium_virtual_machine.id
-        cmd.serviceofferingid = self.small_offering.id
-        self.apiclient.changeServiceForVirtualMachine(cmd)
-
-        self.debug("Starting VM - ID: %s" % self.medium_virtual_machine.id)
-        self.medium_virtual_machine.start(self.apiclient)
-        
-        # Poll listVM to ensure VM is started properly
-        timeout = self.services["timeout"]
-        
-        while True:
-            time.sleep(self.services["sleep"])
-        
-            # Ensure that VM is in running state
-            list_vm_response = list_virtual_machines(
-                                            self.apiclient,
-                                            id=self.medium_virtual_machine.id
-                                            )
-            
-            if isinstance(list_vm_response, list):
-                
-                vm = list_vm_response[0]
-                if vm.state == 'Running':
-                    self.debug("VM state: %s" % vm.state)
-                    break
-            
-            if timeout == 0: 
-                    raise Exception(
-                        "Failed to start VM (ID: %s) after changing service offering" % vm.id)
-                    
-            timeout = timeout - 1
-        
-        return
-
-    def test_06_destroy_vm(self):
-        """Test destroy Virtual Machine
-        """
-
-        # Validate the following
-        # 1. Should not be able to login to the VM.
-        # 2. listVM command should return this VM.State
-        #    of this VM should be "Destroyed".
-        
-        self.debug("Destroy VM - ID: %s" % self.small_virtual_machine.id)
-        self.small_virtual_machine.delete(self.apiclient)
-
-        list_vm_response = list_virtual_machines(
-                                            self.apiclient,
-                                            id=self.small_virtual_machine.id
-                                            )
-        self.assertEqual(
-                            isinstance(list_vm_response, list),
-                            True,
-                            "Check list response returns a valid list"
-                        )
-        
-        self.assertNotEqual(
-                            len(list_vm_response),
-                            0,
-                            "Check VM avaliable in List Virtual Machines"
-                        )
-
-        self.assertEqual(
-                            list_vm_response[0].state,
-                            "Destroyed",
-                            "Check virtual machine is in destroyed state"
-                        )
-        return
-
-    def test_07_restore_vm(self):
-        """Test recover Virtual Machine
-        """
-
-        # Validate the following
-        # 1. listVM command should return this VM.
-        #    State of this VM should be "Stopped".
-        # 2. We should be able to Start this VM successfully.
-        
-        self.debug("Recovering VM - ID: %s" % self.small_virtual_machine.id)
-        
-        cmd = recoverVirtualMachine.recoverVirtualMachineCmd()
-        cmd.id = self.small_virtual_machine.id
-        self.apiclient.recoverVirtualMachine(cmd)
-
-        list_vm_response = list_virtual_machines(
-                                            self.apiclient,
-                                            id=self.small_virtual_machine.id
-                                            )
-        self.assertEqual(
-                            isinstance(list_vm_response, list),
-                            True,
-                            "Check list response returns a valid list"
-                        )
-        
-        self.assertNotEqual(
-                            len(list_vm_response),
-                            0,
-                            "Check VM avaliable in List Virtual Machines"
-                        )
-
-        self.assertEqual(
-                            list_vm_response[0].state,
-                            "Stopped",
-                            "Check virtual machine is in Stopped state"
-                        )
-
-        return


[07/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: getText() reveals the actual value

otherwise required is always not None and always True

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/1a6006c1
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/1a6006c1
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/1a6006c1

Branch: refs/heads/marvin-refactor
Commit: 1a6006c14653dccfe32ac94a1d87b45a3a693fa0
Parents: a81600b
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Sep 4 13:11:05 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:16 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/codegenerator.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1a6006c1/tools/marvin/marvin/codegenerator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/codegenerator.py b/tools/marvin/marvin/codegenerator.py
index cb0cb5c..28ec4dd 100644
--- a/tools/marvin/marvin/codegenerator.py
+++ b/tools/marvin/marvin/codegenerator.py
@@ -311,7 +311,7 @@ class codeGenerator(object):
                 assert paramProperty.name
 
                 required = param.getElementsByTagName('required')
-                if required:
+                if getText(required) == "true":
                     paramProperty.required = getText(required)
 
                 requestDescription = param.getElementsByTagName('description')


[30/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: changes to legacy's imports


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/1b82d7c5
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/1b82d7c5
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/1b82d7c5

Branch: refs/heads/marvin-refactor
Commit: 1b82d7c56572c22e69cb4ee62fa02f14419d1828
Parents: 5eebce1
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Fri Sep 13 15:58:12 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:49 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/legacy/common.py | 2 +-
 tools/marvin/marvin/legacy/utils.py  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b82d7c5/tools/marvin/marvin/legacy/common.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/legacy/common.py b/tools/marvin/marvin/legacy/common.py
index 63bff7c..cfb8ea6 100644
--- a/tools/marvin/marvin/legacy/common.py
+++ b/tools/marvin/marvin/legacy/common.py
@@ -21,7 +21,7 @@
 from marvin.cloudstackAPI import *
 from marvin.remoteSSHClient import remoteSSHClient
 from marvin.legacy.utils import *
-from marvin.integration.lib.base import Configurations
+from marvin.legacy.base import Configurations
 
 #Import System modules
 import time

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1b82d7c5/tools/marvin/marvin/legacy/utils.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/legacy/utils.py b/tools/marvin/marvin/legacy/utils.py
index 44a6e96..f1b8e03 100644
--- a/tools/marvin/marvin/legacy/utils.py
+++ b/tools/marvin/marvin/legacy/utils.py
@@ -241,7 +241,7 @@ def is_snapshot_on_nfs(apiclient, dbconn, config, zoneid, snapshotid):
     @return: True if snapshot is found, False otherwise
     """
 
-    from entity import ImageStore, Snapshot
+    from base import ImageStore, Snapshot
     secondaryStores = ImageStore.list(apiclient, zoneid=zoneid)
 
     assert isinstance(secondaryStores, list), "Not a valid response for listImageStores"


[46/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: prepending marvin. to all logs

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/8d70352b
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8d70352b
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8d70352b

Branch: refs/heads/marvin-refactor
Commit: 8d70352b74c5650bddf8545e0eb8098846cfab58
Parents: a0cdb61
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Oct 2 19:44:42 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:13 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/TestCaseExecuteEngine.py | 4 ++--
 tools/marvin/marvin/cloudstackConnection.py  | 2 ++
 tools/marvin/marvin/marvinPlugin.py          | 6 +++---
 tools/marvin/marvin/remoteSSHClient.py       | 2 +-
 tools/marvin/marvin/util.py                  | 2 +-
 5 files changed, 9 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d70352b/tools/marvin/marvin/TestCaseExecuteEngine.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/TestCaseExecuteEngine.py b/tools/marvin/marvin/TestCaseExecuteEngine.py
index c9796b8..1af9e34 100644
--- a/tools/marvin/marvin/TestCaseExecuteEngine.py
+++ b/tools/marvin/marvin/TestCaseExecuteEngine.py
@@ -48,7 +48,7 @@ class TestCaseExecuteEngine(object):
 
         if testcaseLogFile is not None:
             self.logfile = testcaseLogFile
-            self.logger = logging.getLogger("TestCaseExecuteEngine")
+            self.logger = logging.getLogger("marvin.TestCaseExecuteEngine")
             fh = logging.FileHandler(self.logfile)
             fh.setFormatter(self.logformat)
             self.logger.addHandler(fh)
@@ -81,7 +81,7 @@ class TestCaseExecuteEngine(object):
                 self.injectTestCase(test)
             else:
                 #logger bears the name of the test class
-                testcaselogger = logging.getLogger("%s" % (test))
+                testcaselogger = logging.getLogger("marvin.%s" % (test))
                 fh = logging.FileHandler(self.logfile)
                 fh.setFormatter(self.logformat)
                 testcaselogger.addHandler(fh)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d70352b/tools/marvin/marvin/cloudstackConnection.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py
index 6cd65b7..86c989c 100644
--- a/tools/marvin/marvin/cloudstackConnection.py
+++ b/tools/marvin/marvin/cloudstackConnection.py
@@ -74,6 +74,8 @@ class CloudConnection(object):
         """
         requests_log = logging.getLogger("requests")
         requests_log.setLevel(lvl)
+        factory_log = logging.getLogger("factory")
+        factory_log.setLevel(lvl)
 
     def poll(self, jobid, response):
         """

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d70352b/tools/marvin/marvin/marvinPlugin.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py
index b98b5a6..fee3139 100644
--- a/tools/marvin/marvin/marvinPlugin.py
+++ b/tools/marvin/marvin/marvinPlugin.py
@@ -42,7 +42,7 @@ class MarvinPlugin(Plugin):
                                            "%(name)s - %(message)s")
 
         if options.debug_log:
-            self.logger = logging.getLogger("NoseTestExecuteEngine")
+            self.logger = logging.getLogger("marvin.NoseTestExecuteEngine")
             self.debug_stream = logging.FileHandler(options.debug_log)
             self.debug_stream.setFormatter(self.logformat)
             self.logger.addHandler(self.debug_stream)
@@ -93,7 +93,7 @@ class MarvinPlugin(Plugin):
         Plugin.options(self, parser, env)
 
     def __init__(self):
-        self.identifier = None
+        self.identifier = ''
         Plugin.__init__(self)
 
     def prepareTestRunner(self, runner):
@@ -122,7 +122,7 @@ class MarvinPlugin(Plugin):
     def beforeTest(self, test):
         testname = test.__str__().split()[0]
         self.testclient.identifier = '-'.join([self.identifier, testname])
-        self.logger.name = test.__str__()
+        self.logger.name = "marvin.%s" % test.__str__()
 
     def _injectClients(self, test):
         self.debug_stream. \

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d70352b/tools/marvin/marvin/remoteSSHClient.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/remoteSSHClient.py b/tools/marvin/marvin/remoteSSHClient.py
index d64c82d..502fe46 100644
--- a/tools/marvin/marvin/remoteSSHClient.py
+++ b/tools/marvin/marvin/remoteSSHClient.py
@@ -32,7 +32,7 @@ class remoteSSHClient(object):
         self.keyPairFile = keyPairFileLocation
         self.ssh = paramiko.SSHClient()
         self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-        self.logger = logging.getLogger('sshClient')
+        self.logger = logging.getLogger('marvin.sshClient')
         ch = logging.StreamHandler()
         ch.setLevel(log_lvl)
         self.logger.addHandler(ch)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d70352b/tools/marvin/marvin/util.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/util.py b/tools/marvin/marvin/util.py
index 93cb56b..175a851 100644
--- a/tools/marvin/marvin/util.py
+++ b/tools/marvin/marvin/util.py
@@ -202,7 +202,7 @@ def fetch_api_client(config_file='datacenterCfg'):
     """Fetch the Cloudstack API Client"""
     config = marvin.configGenerator.get_setup_config(config_file)
     mgt = config.mgtSvr[0]
-    testClientLogger = logging.getLogger("testClient")
+    testClientLogger = logging.getLogger("marvin.testClient")
     asyncTimeout = 3600
     return cloudstackAPIClient.CloudStackAPIClient(
         marvin.cloudstackConnection.cloudConnection(


[47/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: hiding SubFactory attributes

attributes generated from subfactory calls need to be hidden from the
subsequent factory calls as these attributes are not part of the default
factory

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/c9da418e
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/c9da418e
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/c9da418e

Branch: refs/heads/marvin-refactor
Commit: c9da418ee369fe10a79844cd5fb67b73b39a2720
Parents: 8d70352
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Oct 2 19:45:13 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:15 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/factory/data/diskoffering.py    | 2 ++
 tools/marvin/marvin/factory/data/firewallrule.py    | 2 ++
 tools/marvin/marvin/factory/data/network.py         | 9 +++++++++
 tools/marvin/marvin/factory/data/networkoffering.py | 8 ++++----
 tools/marvin/marvin/factory/data/user.py            | 6 ++++++
 tools/marvin/marvin/factory/data/vm.py              | 1 +
 tools/marvin/marvin/factory/data/vpc.py             | 2 ++
 tools/marvin/marvin/factory/data/zone.py            | 1 +
 8 files changed, 27 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c9da418e/tools/marvin/marvin/factory/data/diskoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/diskoffering.py b/tools/marvin/marvin/factory/data/diskoffering.py
index 89a48b4..bb3bab1 100644
--- a/tools/marvin/marvin/factory/data/diskoffering.py
+++ b/tools/marvin/marvin/factory/data/diskoffering.py
@@ -19,6 +19,7 @@ import factory
 from marvin.factory.diskoffering import DiskOfferingFactory
 from marvin.legacy.utils import random_gen
 
+
 class SharedDiskOffering(DiskOfferingFactory):
 
     displaytext = "SharedDiskOffering"
@@ -26,6 +27,7 @@ class SharedDiskOffering(DiskOfferingFactory):
     storagetype = "shared"
     disksize = 10 #MB
 
+
 class LocalDiskOffering(DiskOfferingFactory):
 
     displaytext = "LocalDiskOffering"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c9da418e/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 44cc17f..1eb0260 100644
--- a/tools/marvin/marvin/factory/data/firewallrule.py
+++ b/tools/marvin/marvin/factory/data/firewallrule.py
@@ -17,12 +17,14 @@
 
 from marvin.factory.firewall import FirewallFactory
 
+
 class SshFirewallRule(FirewallFactory):
     protocol = 'tcp'
     startport = 22
     endport = 22
     cidrlist = '0.0.0.0/0'
 
+
 class HttpFirewallRule(FirewallFactory):
     protocol = 'tcp'
     startport = 80

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c9da418e/tools/marvin/marvin/factory/data/network.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/network.py b/tools/marvin/marvin/factory/data/network.py
index 50c0086..a6e5d47 100644
--- a/tools/marvin/marvin/factory/data/network.py
+++ b/tools/marvin/marvin/factory/data/network.py
@@ -22,8 +22,11 @@ from marvin.factory.data.networkoffering import DefaultIsolatedNetworkOfferingWi
 from marvin.factory.data.networkoffering import DefaultSharedNetworkOffering
 from marvin.factory.data.networkoffering import DefaultIsolatedNetworkOfferingForVpc
 
+
 class GuestIsolatedNetwork(NetworkFactory):
 
+    FACTORY_HIDDEN_ARGS = ('networkoffering', )
+
     displaytext = factory.Sequence(lambda n: 'GuestIsolatedNetwork-%s' % random_gen())
     name = factory.Sequence(lambda n: 'GuestIsolatedNetwork-%s' % random_gen())
     networkoffering =\
@@ -35,8 +38,11 @@ class GuestIsolatedNetwork(NetworkFactory):
     networkofferingid = factory.LazyAttribute(lambda no: no.networkoffering.id if no.networkoffering else no.networkoffering)
     zoneid = None
 
+
 class SharedNetwork(NetworkFactory):
 
+    FACTORY_HIDDEN_ARGS = ('networkoffering', )
+
     displaytext = factory.Sequence(lambda n: 'SharedNetwork-%s' % random_gen())
     name = factory.Sequence(lambda n: 'SharedNetwork-%s' % random_gen())
     networkoffering = \
@@ -48,8 +54,11 @@ class SharedNetwork(NetworkFactory):
     networkofferingid = factory.LazyAttribute(lambda no: no.networkoffering.id if no.networkoffering else no.networkoffering)
     zoneid = None
 
+
 class DefaultVpcNetwork(NetworkFactory):
 
+    FACTORY_HIDDEN_ARGS = ('networkoffering', )
+
     displaytext = factory.Sequence(lambda n: 'DefaultVpcNetwork-%s' % random_gen())
     name = factory.Sequence(lambda n: 'DefaultVpcNetwork-%s' % random_gen())
     networkoffering = \

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c9da418e/tools/marvin/marvin/factory/data/networkoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/networkoffering.py b/tools/marvin/marvin/factory/data/networkoffering.py
index 1a65f85..22dee2e 100644
--- a/tools/marvin/marvin/factory/data/networkoffering.py
+++ b/tools/marvin/marvin/factory/data/networkoffering.py
@@ -48,7 +48,7 @@ class DefaultIsolatedNetworkOfferingWithSourceNatService(NetworkOfferingFactory)
     def enable(self, create, extracted, **kwargs):
         if not create:
             return
-        self.update(apiclient=self.apiclient, id=self.id, state='Enabled')
+        self.update(id=self.id, state='Enabled')
 
 
 class DefaultSharedNetworkOfferingWithSGService(NetworkOfferingFactory):
@@ -83,7 +83,7 @@ class DefaultSharedNetworkOfferingWithSGService(NetworkOfferingFactory):
     def enable(self, create, extracted, **kwargs):
         if not create:
             return
-        self.update(apiclient=self.apiclient, id=self.id, state='Enabled')
+        self.update(id=self.id, state='Enabled')
 
 
 class DefaultSharedNetworkOffering(NetworkOfferingFactory):
@@ -114,7 +114,7 @@ class DefaultSharedNetworkOffering(NetworkOfferingFactory):
     def enable(self, create, extracted, **kwargs):
         if not create:
             return
-        self.update(apiclient=self.apiclient, id=self.id, state='Enabled')
+        self.update(id=self.id, state='Enabled')
 
 
 class DefaultIsolatedNetworkOfferingForVpc(NetworkOfferingFactory):
@@ -145,4 +145,4 @@ class DefaultIsolatedNetworkOfferingForVpc(NetworkOfferingFactory):
     def enable(self, create, extracted, **kwargs):
         if not create:
             return
-        self.update(apiclient=self.apiclient, id=self.id, state='Enabled')
+        self.update(id=self.id, state='Enabled')

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c9da418e/tools/marvin/marvin/factory/data/user.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/user.py b/tools/marvin/marvin/factory/data/user.py
index 588c294..acbe4d9 100644
--- a/tools/marvin/marvin/factory/data/user.py
+++ b/tools/marvin/marvin/factory/data/user.py
@@ -20,8 +20,11 @@ from marvin.factory.user import UserFactory
 from marvin.factory.data.account import UserAccount
 from marvin.legacy.utils import random_gen
 
+
 class User(UserFactory):
 
+    FACTORY_HIDDEN_ARGS = ('account', )
+
     firstname = factory.Sequence(lambda n: random_gen())
     lastname = factory.Sequence(lambda n: random_gen())
     email = factory.LazyAttribute(lambda e: '{0}.{1}@cloudstack.org'.format(e.firstname, e.lastname).lower())
@@ -37,8 +40,11 @@ class User(UserFactory):
         username=factory.SelfAttribute('..username'),
     )
 
+
 class AdminUser(UserFactory):
 
+    FACTORY_HIDDEN_ARGS = ('account', )
+
     account = factory.SubFactory(UserAccount,
         apiclient=factory.SelfAttribute('..apiclient'),
         accounttype=1,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c9da418e/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 3f50b52..90f275c 100644
--- a/tools/marvin/marvin/factory/data/vm.py
+++ b/tools/marvin/marvin/factory/data/vm.py
@@ -63,6 +63,7 @@ class VpcVirtualMachine(VirtualMachineFactory):
     """
     VirtualMachine within a VPC created by DefaultVPC offering
     """
+    FACTORY_HIDDEN_ARGS = ('vpc', 'ntwk', )
 
     vpc = factory.SubFactory(
         DefaultVpc,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c9da418e/tools/marvin/marvin/factory/data/vpc.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/vpc.py b/tools/marvin/marvin/factory/data/vpc.py
index fc0379c..0a90418 100644
--- a/tools/marvin/marvin/factory/data/vpc.py
+++ b/tools/marvin/marvin/factory/data/vpc.py
@@ -22,6 +22,8 @@ from marvin.legacy.utils import random_gen
 
 class DefaultVpc(VpcFactory):
 
+    FACTORY_HIDDEN_ARGS = ('vpcoffering', )
+
     name = factory.Sequence(lambda e: "DefaultVpc" + random_gen())
     cidr = '10.0.0.1/24'
     displaytext = name

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c9da418e/tools/marvin/marvin/factory/data/zone.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/zone.py b/tools/marvin/marvin/factory/data/zone.py
index 80cb67a..7cc2e32 100644
--- a/tools/marvin/marvin/factory/data/zone.py
+++ b/tools/marvin/marvin/factory/data/zone.py
@@ -19,6 +19,7 @@ import factory
 from marvin.factory.zone import ZoneFactory
 from marvin.legacy.utils import random_gen
 
+
 class AdvancedZone(ZoneFactory):
     name = factory.Sequence(lambda n: "advzone" + random_gen())
     networktype = "Advanced"


[33/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: allow the nose plugin to load

include deployer module in the packaging and correct cloudstackAPI
import to use absolute imports

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/09621e5b
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/09621e5b
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/09621e5b

Branch: refs/heads/marvin-refactor
Commit: 09621e5b7fe2992c50de0522baf460cde29eb2b9
Parents: 73aabab
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Mon Sep 16 11:52:40 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:54 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/deployer/deployDataCenter.py | 2 +-
 tools/marvin/setup.py                            | 8 +++++---
 2 files changed, 6 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/09621e5b/tools/marvin/marvin/deployer/deployDataCenter.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployer/deployDataCenter.py b/tools/marvin/marvin/deployer/deployDataCenter.py
index 0c1c639..4df05bb 100644
--- a/tools/marvin/marvin/deployer/deployDataCenter.py
+++ b/tools/marvin/marvin/deployer/deployDataCenter.py
@@ -20,7 +20,7 @@ import logging
 import configGenerator
 from os import path
 from time import sleep
-from cloudstackAPI import *
+from marvin.cloudstackAPI import *
 from optparse import OptionParser
 from marvin import cloudstackTestClient
 from marvin import cloudstackException

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/09621e5b/tools/marvin/setup.py
----------------------------------------------------------------------
diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py
index cbaa157..4a1cbc2 100644
--- a/tools/marvin/setup.py
+++ b/tools/marvin/setup.py
@@ -42,9 +42,11 @@ setup(name="Marvin",
     maintainer_email="tsp@apache.org",
     long_description="Marvin is the Apache CloudStack python client written around the unittest framework",
     platforms=("Any",),
-    packages=["marvin", "marvin.cloudstackAPI", "marvin.entity", "marvin.factory", "marvin.factory.data",
-              "marvin.generate", "marvin.legacy", "marvin.sandbox", "marvin.sandbox.advanced",
-              "marvin.sandbox.advancedsg", "marvin.sandbox.basic"],
+    packages=["marvin", "marvin.cloudstackAPI",
+              "marvin.deployer", "marvin.entity", "marvin.factory", "marvin.factory.data",
+              "marvin.generate", "marvin.legacy",
+              "marvin.sandbox", "marvin.sandbox.advanced", "marvin.sandbox.advancedsg", "marvin.sandbox.basic",
+              "marvin.test"],
     license="LICENSE.txt",
     install_requires=[
         "mysql-connector-python",


[08/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: docs updates

- fix the xml/json compilation
- need ability to send in identifiers for cloud resources

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/8a1743c0
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8a1743c0
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8a1743c0

Branch: refs/heads/marvin-refactor
Commit: 8a1743c0cc8416c513a31aa68731210490038e06
Parents: 1a6006c
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Fri Sep 6 16:33:53 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:20 2013 +0530

----------------------------------------------------------------------
 .../marvin/factory/CloudStackBaseFactory.py     | 55 --------------------
 1 file changed, 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8a1743c0/tools/marvin/marvin/factory/CloudStackBaseFactory.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/CloudStackBaseFactory.py b/tools/marvin/marvin/factory/CloudStackBaseFactory.py
deleted file mode 100644
index 4b33a52..0000000
--- a/tools/marvin/marvin/factory/CloudStackBaseFactory.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# 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.
-
-import factory
-import inspect
-
-CREATORS = ["create", "deploy", "register"]
-
-
-class CloudStackBaseFactory(factory.Factory):
-    ABSTRACT_FACTORY = True
-
-    @classmethod
-    def _build(cls, target_class, *args, **kwargs):
-        if len(args) == 0:
-            return target_class(kwargs)
-        return target_class(*args, **kwargs)
-
-    @classmethod
-    def _create(cls, target_class, *args, **kwargs):
-        if hasattr(cls, 'apiclient'):
-            members = inspect.getmembers(target_class,
-                predicate=inspect.ismethod)
-            creators = filter(lambda x: x[0] in CREATORS, members)
-            assert creators, "How do I bring this guy into existence?"
-            assert inspect.ismethod(creators[0][1])
-            creator = creators[0][1]
-            return creator(cls.apiclient, factory=cls._build(target_class,
-                *args, **kwargs))
-        else:
-            cls._build(target_class, *args, **kwargs)
-
-    @classmethod
-    def _adjust_kwargs(cls, **kwargs):
-        if "apiclient" in kwargs:
-            cls.apiclient = kwargs["apiclient"]
-            clean_kwargs = dict((k, v) for k, v in kwargs.iteritems()
-                if k != "apiclient")
-            return clean_kwargs
-        else:
-            return kwargs
\ No newline at end of file


[43/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: exception handle for non-standard libraries

non-standard python libraries that are not installed by default on
python installations need to be exception handled appropriately

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/3aa10efe
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/3aa10efe
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/3aa10efe

Branch: refs/heads/marvin-refactor
Commit: 3aa10efec176baed4ad07a9d39f0009476e753c3
Parents: c1524f3
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Oct 2 11:28:44 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:09 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/TestCaseExecuteEngine.py |  5 ++++-
 tools/marvin/marvin/cloudstackConnection.py  | 13 ++++++++-----
 tools/marvin/marvin/dbConnection.py          | 11 ++++++-----
 tools/marvin/marvin/remoteSSHClient.py       |  1 -
 tools/marvin/marvin/util.py                  |  1 -
 5 files changed, 18 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3aa10efe/tools/marvin/marvin/TestCaseExecuteEngine.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/TestCaseExecuteEngine.py b/tools/marvin/marvin/TestCaseExecuteEngine.py
index 6495000..c9796b8 100644
--- a/tools/marvin/marvin/TestCaseExecuteEngine.py
+++ b/tools/marvin/marvin/TestCaseExecuteEngine.py
@@ -15,7 +15,10 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import unittest2 as unittest
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
 import os
 import sys
 import logging

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3aa10efe/tools/marvin/marvin/cloudstackConnection.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py
index 07cb471..1e4298e 100644
--- a/tools/marvin/marvin/cloudstackConnection.py
+++ b/tools/marvin/marvin/cloudstackConnection.py
@@ -15,7 +15,14 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import requests
+try:
+    import requests
+    from requests import ConnectionError
+    from requests import HTTPError
+    from requests import Timeout
+    from requests import RequestException
+except ImportError:
+    raise Exception("requests installation not found. use pip install requests to continue")
 import urllib
 import base64
 import hmac
@@ -25,10 +32,6 @@ import time
 from marvin import cloudstackException
 from marvin.cloudstackAPI import *
 from marvin import jsonHelper
-from requests import ConnectionError
-from requests import HTTPError
-from requests import Timeout
-from requests import RequestException
 
 
 class CloudConnection(object):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3aa10efe/tools/marvin/marvin/dbConnection.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/dbConnection.py b/tools/marvin/marvin/dbConnection.py
index 99014ab..98c72c5 100644
--- a/tools/marvin/marvin/dbConnection.py
+++ b/tools/marvin/marvin/dbConnection.py
@@ -15,13 +15,14 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import mysql
+try:
+    import mysql
+    from mysql import connector
+    from mysql.connector import errors
+except ImportError:
+    raise Exception("mysql-connector-python not installed. pip install mysql-connector-python to continue")
 import contextlib
-from mysql import connector
-from mysql.connector import errors
-from contextlib import closing
 import cloudstackException
-import sys
 import os
 
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3aa10efe/tools/marvin/marvin/remoteSSHClient.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/remoteSSHClient.py b/tools/marvin/marvin/remoteSSHClient.py
index fea9b12..d64c82d 100644
--- a/tools/marvin/marvin/remoteSSHClient.py
+++ b/tools/marvin/marvin/remoteSSHClient.py
@@ -20,7 +20,6 @@ import time
 import cloudstackException
 import contextlib
 import logging
-from contextlib import closing
 
 
 class remoteSSHClient(object):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3aa10efe/tools/marvin/marvin/util.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/util.py b/tools/marvin/marvin/util.py
index 9a97c9d..609e696 100644
--- a/tools/marvin/marvin/util.py
+++ b/tools/marvin/marvin/util.py
@@ -19,7 +19,6 @@ 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"


[09/50] [abbrv] marvin-refactor: moving old integration libraries to legacy

Posted by ts...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/79a1591b/tools/marvin/marvin/utils.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/utils.py b/tools/marvin/marvin/utils.py
deleted file mode 100644
index 44a6e96..0000000
--- a/tools/marvin/marvin/utils.py
+++ /dev/null
@@ -1,317 +0,0 @@
-# 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.
-"""Utilities functions
-"""
-
-import marvin
-import os
-import time
-import logging
-import string
-import random
-import imaplib
-import email
-import socket
-import urlparse
-import datetime
-from marvin.cloudstackAPI import *
-from marvin.remoteSSHClient import remoteSSHClient
-
-
-def restart_mgmt_server(server):
-    """Restarts the management server"""
-
-    try:
-        # Get the SSH client
-        ssh = is_server_ssh_ready(
-            server["ipaddress"],
-            server["port"],
-            server["username"],
-            server["password"],
-        )
-        result = ssh.execute("/etc/init.d/cloud-management restart")
-        res = str(result)
-        # Server Stop - OK
-        # Server Start - OK
-        if res.count("OK") != 2:
-            raise ("ErrorInReboot!")
-    except Exception as e:
-        raise e
-    return
-
-
-def fetch_latest_mail(services, from_mail):
-    """Fetch mail"""
-
-    # Login to mail server to verify email
-    mail = imaplib.IMAP4_SSL(services["server"])
-    mail.login(
-        services["email"],
-        services["password"]
-    )
-    mail.list()
-    mail.select(services["folder"])
-    date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y")
-
-    result, data = mail.uid(
-        'search',
-        None,
-        '(SENTSINCE {date} HEADER FROM "{mail}")'.format(
-            date=date,
-            mail=from_mail
-        )
-    )
-    # Return False if email is not present
-    if data == []:
-        return False
-
-    latest_email_uid = data[0].split()[-1]
-    result, data = mail.uid('fetch', latest_email_uid, '(RFC822)')
-    raw_email = data[0][1]
-    email_message = email.message_from_string(raw_email)
-    result = get_first_text_block(email_message)
-    return result
-
-
-def get_first_text_block(email_message_instance):
-    """fetches first text block from the mail"""
-    maintype = email_message_instance.get_content_maintype()
-    if maintype == 'multipart':
-        for part in email_message_instance.get_payload():
-            if part.get_content_maintype() == 'text':
-                return part.get_payload()
-    elif maintype == 'text':
-        return email_message_instance.get_payload()
-
-
-def random_gen(id=None, size=6, chars=string.ascii_uppercase + string.digits):
-    """Generate Random Strings of variable length"""
-    randomstr = ''.join(random.choice(chars) for x in range(size))
-    if id:
-        return ''.join([id, '-', randomstr])
-    return randomstr
-
-
-def cleanup_resources(api_client, resources):
-    """Delete resources"""
-    for obj in resources:
-        obj.delete(api_client)
-
-
-def is_server_ssh_ready(ipaddress, port, username, password, retries=10, timeout=30, keyPairFileLocation=None):
-    """Return ssh handle else wait till sshd is running"""
-    try:
-        ssh = remoteSSHClient(
-            host=ipaddress,
-            port=port,
-            user=username,
-            passwd=password,
-            keyPairFileLocation=keyPairFileLocation,
-            retries=retries,
-            delay=timeout)
-    except Exception, e:
-        raise Exception("Failed to bring up ssh service in time. Waited %ss. Error is %s" % (retries * timeout, e))
-    else:
-        return ssh
-
-
-def format_volume_to_ext3(ssh_client, device="/dev/sda"):
-    """Format attached storage to ext3 fs"""
-    cmds = [
-        "echo -e 'n\np\n1\n\n\nw' | fdisk %s" % device,
-        "mkfs.ext3 %s1" % device,
-    ]
-    for c in cmds:
-        ssh_client.execute(c)
-
-
-def fetch_api_client(config_file='datacenterCfg'):
-    """Fetch the Cloudstack API Client"""
-    config = marvin.configGenerator.get_setup_config(config_file)
-    mgt = config.mgtSvr[0]
-    testClientLogger = logging.getLogger("testClient")
-    asyncTimeout = 3600
-    return cloudstackAPIClient.CloudStackAPIClient(
-        marvin.cloudstackConnection.cloudConnection(
-            mgt.mgtSvrIp,
-            mgt.port,
-            mgt.apiKey,
-            mgt.securityKey,
-            asyncTimeout,
-            testClientLogger
-        )
-    )
-
-def get_host_credentials(config, hostip):
-    """Get login information for a host `hostip` (ipv4) from marvin's `config`
-
-    @return the tuple username, password for the host else raise keyerror"""
-    for zone in config.zones:
-        for pod in zone.pods:
-            for cluster in pod.clusters:
-                for host in cluster.hosts:
-                    if str(host.url).startswith('http'):
-                        hostname = urlparse.urlsplit(str(host.url)).netloc
-                    else:
-                        hostname = str(host.url)
-                    try:
-                        if socket.getfqdn(hostip) == socket.getfqdn(hostname):
-                            return host.username, host.password
-                    except socket.error, e:
-                        raise Exception("Unresolvable host %s error is %s" % (hostip, e))
-    raise KeyError("Please provide the marvin configuration file with credentials to your hosts")
-
-def get_process_status(hostip, port, username, password, linklocalip, process, hypervisor=None):
-    """Double hop and returns a process status"""
-
-    #SSH to the machine
-    ssh = remoteSSHClient(hostip, port, username, password)
-    if str(hypervisor).lower() == 'vmware':
-        ssh_command = "ssh -i /var/cloudstack/management/.ssh/id_rsa -ostricthostkeychecking=no "
-    else:
-        ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
-
-    ssh_command = ssh_command +\
-                  "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % (
-                      linklocalip,
-                      process)
-
-    # Double hop into router
-    timeout = 5
-    # Ensure the SSH login is successful
-    while True:
-        res = ssh.execute(ssh_command)
-
-        if res[0] != "Host key verification failed.":
-            break
-        elif timeout == 0:
-            break
-
-        time.sleep(5)
-        timeout = timeout - 1
-    return res
-
-
-def isAlmostEqual(first_digit, second_digit, range=0):
-    digits_equal_within_range = False
-
-    try:
-        if ((first_digit - range) < second_digit < (first_digit + range)):
-            digits_equal_within_range = True
-    except Exception as e:
-        raise e
-    return digits_equal_within_range
-
-
-def xsplit(txt, seps):
-    """
-    Split a string in `txt` by list of delimiters in `seps`
-    @param txt: string to split
-    @param seps: list of separators
-    @return: list of split units
-    """
-    default_sep = seps[0]
-    for sep in seps[1:]: # we skip seps[0] because that's the default separator
-        txt = txt.replace(sep, default_sep)
-    return [i.strip() for i in txt.split(default_sep)]
-
-def is_snapshot_on_nfs(apiclient, dbconn, config, zoneid, snapshotid):
-    """
-    Checks whether a snapshot with id (not UUID) `snapshotid` is present on the nfs storage
-
-    @param apiclient: api client connection
-    @param @dbconn:  connection to the cloudstack db
-    @param config: marvin configuration file
-    @param zoneid: uuid of the zone on which the secondary nfs storage pool is mounted
-    @param snapshotid: uuid of the snapshot
-    @return: True if snapshot is found, False otherwise
-    """
-
-    from entity import ImageStore, Snapshot
-    secondaryStores = ImageStore.list(apiclient, zoneid=zoneid)
-
-    assert isinstance(secondaryStores, list), "Not a valid response for listImageStores"
-    assert len(secondaryStores) != 0, "No image stores found in zone %s" % zoneid
-
-    secondaryStore = secondaryStores[0]
-
-    if str(secondaryStore.providername).lower() != "nfs":
-        raise Exception(
-            "is_snapshot_on_nfs works only against nfs secondary storage. found %s" % str(secondaryStore.providername))
-
-    qresultset = dbconn.execute(
-                        "select id from snapshots where uuid = '%s';" \
-                        % str(snapshotid)
-                        )
-    if len(qresultset) == 0:
-        raise Exception(
-            "No snapshot found in cloudstack with id %s" % snapshotid)
-
-
-    snapshotid = qresultset[0][0]
-    qresultset = dbconn.execute(
-        "select install_path from snapshot_store_ref where snapshot_id='%s' and store_role='Image';" % snapshotid
-    )
-
-    assert isinstance(qresultset, list), "Invalid db query response for snapshot %s" % snapshotid
-    assert len(qresultset) != 0, "No such snapshot %s found in the cloudstack db" % snapshotid
-
-    snapshotPath = qresultset[0][0]
-
-    nfsurl = secondaryStore.url
-    # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test']
-    from urllib2 import urlparse
-    parse_url = urlparse.urlsplit(nfsurl, scheme='nfs')
-    host, path = parse_url.netloc, parse_url.path
-
-    if not config.mgtSvr:
-        raise Exception("Your marvin configuration does not contain mgmt server credentials")
-    host, user, passwd = config.mgtSvr[0].mgtSvrIp, config.mgtSvr[0].user, config.mgtSvr[0].passwd
-
-    try:
-        ssh_client = remoteSSHClient(
-            host,
-            22,
-            user,
-            passwd,
-        )
-        cmds = [
-                "mkdir -p %s /mnt/tmp",
-                "mount -t %s %s:%s /mnt/tmp" % (
-                    'nfs',
-                    host,
-                    path,
-                    ),
-                "test -f %s && echo 'snapshot exists'" % (
-                    os.path.join("/mnt/tmp", snapshotPath)
-                    ),
-            ]
-
-        for c in cmds:
-            result = ssh_client.execute(c)
-
-        # Unmount the Sec Storage
-        cmds = [
-                "cd",
-                "umount /mnt/tmp",
-            ]
-        for c in cmds:
-            ssh_client.execute(c)
-    except Exception as e:
-        raise Exception("SSH failed for management server: %s - %s" %
-                      (config[0].mgtSvrIp, e))
-    return 'snapshot exists' in result


[45/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: add more util functions from legacy

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/a0cdb61e
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/a0cdb61e
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/a0cdb61e

Branch: refs/heads/marvin-refactor
Commit: a0cdb61e22fafd5a5cd71ccd3e2d31f2ab5635de
Parents: f76b102
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Oct 2 16:26:34 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:12 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/util.py | 313 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 313 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a0cdb61e/tools/marvin/marvin/util.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/util.py b/tools/marvin/marvin/util.py
index 51a91ca..93cb56b 100644
--- a/tools/marvin/marvin/util.py
+++ b/tools/marvin/marvin/util.py
@@ -15,10 +15,24 @@
 # specific language governing permissions and limitations
 # under the License.
 
+import marvin
+import os
+import time
+import logging
+import string
+import random
+import imaplib
+import email
+import socket
+import urlparse
+import datetime
+from marvin.cloudstackAPI import *
+from marvin.remoteSSHClient import remoteSSHClient
 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.configuration import Configuration
 
 
 def get_domain(apiclient):
@@ -83,3 +97,302 @@ def get_template(apiclient, description=None):
     else:
         raise Exception(
             "Failed to find ready and featured template of : %s" % description)
+
+def restart_mgmt_server(server):
+    """Restarts the management server"""
+
+    try:
+        # Get the SSH client
+        ssh = is_server_ssh_ready(
+            server["ipaddress"],
+            server["port"],
+            server["username"],
+            server["password"],
+        )
+        result = ssh.execute("/etc/init.d/cloud-management restart")
+        res = str(result)
+        # Server Stop - OK
+        # Server Start - OK
+        if res.count("OK") != 2:
+            raise ("ErrorInReboot!")
+    except Exception as e:
+        raise e
+    return
+
+
+def fetch_latest_mail(services, from_mail):
+    """Fetch mail"""
+
+    # Login to mail server to verify email
+    mail = imaplib.IMAP4_SSL(services["server"])
+    mail.login(
+        services["email"],
+        services["password"]
+    )
+    mail.list()
+    mail.select(services["folder"])
+    date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y")
+
+    result, data = mail.uid(
+        'search',
+        None,
+        '(SENTSINCE {date} HEADER FROM "{mail}")'.format(
+            date=date,
+            mail=from_mail
+        )
+    )
+    # Return False if email is not present
+    if data == []:
+        return False
+
+    latest_email_uid = data[0].split()[-1]
+    result, data = mail.uid('fetch', latest_email_uid, '(RFC822)')
+    raw_email = data[0][1]
+    email_message = email.message_from_string(raw_email)
+    result = get_first_text_block(email_message)
+    return result
+
+
+def get_first_text_block(email_message_instance):
+    """fetches first text block from the mail"""
+    maintype = email_message_instance.get_content_maintype()
+    if maintype == 'multipart':
+        for part in email_message_instance.get_payload():
+            if part.get_content_maintype() == 'text':
+                return part.get_payload()
+    elif maintype == 'text':
+        return email_message_instance.get_payload()
+
+
+def random_gen(id=None, size=6, chars=string.ascii_uppercase + string.digits):
+    """Generate Random Strings of variable length"""
+    randomstr = ''.join(random.choice(chars) for x in range(size))
+    if id:
+        return ''.join([id, '-', randomstr])
+    return randomstr
+
+def is_server_ssh_ready(ipaddress, port, username, password, retries=10, timeout=30, keyPairFileLocation=None):
+    """Return ssh handle else wait till sshd is running"""
+    try:
+        ssh = remoteSSHClient(
+            host=ipaddress,
+            port=port,
+            user=username,
+            passwd=password,
+            keyPairFileLocation=keyPairFileLocation,
+            retries=retries,
+            delay=timeout)
+    except Exception, e:
+        raise Exception("Failed to bring up ssh service in time. Waited %ss. Error is %s" % (retries * timeout, e))
+    else:
+        return ssh
+
+
+def format_volume_to_ext3(ssh_client, device="/dev/sda"):
+    """Format attached storage to ext3 fs"""
+    cmds = [
+        "echo -e 'n\np\n1\n\n\nw' | fdisk %s" % device,
+        "mkfs.ext3 %s1" % device,
+    ]
+    for c in cmds:
+        ssh_client.execute(c)
+
+
+def fetch_api_client(config_file='datacenterCfg'):
+    """Fetch the Cloudstack API Client"""
+    config = marvin.configGenerator.get_setup_config(config_file)
+    mgt = config.mgtSvr[0]
+    testClientLogger = logging.getLogger("testClient")
+    asyncTimeout = 3600
+    return cloudstackAPIClient.CloudStackAPIClient(
+        marvin.cloudstackConnection.cloudConnection(
+            mgt.mgtSvrIp,
+            mgt.port,
+            mgt.apiKey,
+            mgt.securityKey,
+            asyncTimeout,
+            testClientLogger
+        )
+    )
+
+def get_host_credentials(config, hostip):
+    """Get login information for a host `hostip` (ipv4) from marvin's `config`
+
+    @return the tuple username, password for the host else raise keyerror"""
+    for zone in config.zones:
+        for pod in zone.pods:
+            for cluster in pod.clusters:
+                for host in cluster.hosts:
+                    if str(host.url).startswith('http'):
+                        hostname = urlparse.urlsplit(str(host.url)).netloc
+                    else:
+                        hostname = str(host.url)
+                    try:
+                        if socket.getfqdn(hostip) == socket.getfqdn(hostname):
+                            return host.username, host.password
+                    except socket.error, e:
+                        raise Exception("Unresolvable host %s error is %s" % (hostip, e))
+    raise KeyError("Please provide the marvin configuration file with credentials to your hosts")
+
+def get_process_status(hostip, port, username, password, linklocalip, process, hypervisor=None):
+    """Double hop and returns a process status"""
+
+    #SSH to the machine
+    ssh = remoteSSHClient(hostip, port, username, password)
+    if str(hypervisor).lower() == 'vmware':
+        ssh_command = "ssh -i /var/cloudstack/management/.ssh/id_rsa -ostricthostkeychecking=no "
+    else:
+        ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
+
+    ssh_command = ssh_command +\
+                  "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % (
+                      linklocalip,
+                      process)
+
+    # Double hop into router
+    timeout = 5
+    # Ensure the SSH login is successful
+    while True:
+        res = ssh.execute(ssh_command)
+
+        if res[0] != "Host key verification failed.":
+            break
+        elif timeout == 0:
+            break
+
+        time.sleep(5)
+        timeout = timeout - 1
+    return res
+
+
+def isAlmostEqual(first_digit, second_digit, range=0):
+    digits_equal_within_range = False
+
+    try:
+        if ((first_digit - range) < second_digit < (first_digit + range)):
+            digits_equal_within_range = True
+    except Exception as e:
+        raise e
+    return digits_equal_within_range
+
+
+def xsplit(txt, seps):
+    """
+    Split a string in `txt` by list of delimiters in `seps`
+    @param txt: string to split
+    @param seps: list of separators
+    @return: list of split units
+    """
+    default_sep = seps[0]
+    for sep in seps[1:]: # we skip seps[0] because that's the default separator
+        txt = txt.replace(sep, default_sep)
+    return [i.strip() for i in txt.split(default_sep)]
+
+def is_snapshot_on_nfs(apiclient, dbconn, config, zoneid, snapshotid):
+    """
+    Checks whether a snapshot with id (not UUID) `snapshotid` is present on the nfs storage
+
+    @param apiclient: api client connection
+    @param @dbconn:  connection to the cloudstack db
+    @param config: marvin configuration file
+    @param zoneid: uuid of the zone on which the secondary nfs storage pool is mounted
+    @param snapshotid: uuid of the snapshot
+    @return: True if snapshot is found, False otherwise
+    """
+
+    from base import ImageStore, Snapshot
+    secondaryStores = ImageStore.list(apiclient, zoneid=zoneid)
+
+    assert isinstance(secondaryStores, list), "Not a valid response for listImageStores"
+    assert len(secondaryStores) != 0, "No image stores found in zone %s" % zoneid
+
+    secondaryStore = secondaryStores[0]
+
+    if str(secondaryStore.providername).lower() != "nfs":
+        raise Exception(
+            "is_snapshot_on_nfs works only against nfs secondary storage. found %s" % str(secondaryStore.providername))
+
+    qresultset = dbconn.execute(
+                        "select id from snapshots where uuid = '%s';" \
+                        % str(snapshotid)
+                        )
+    if len(qresultset) == 0:
+        raise Exception(
+            "No snapshot found in cloudstack with id %s" % snapshotid)
+
+
+    snapshotid = qresultset[0][0]
+    qresultset = dbconn.execute(
+        "select install_path from snapshot_store_ref where snapshot_id='%s' and store_role='Image';" % snapshotid
+    )
+
+    assert isinstance(qresultset, list), "Invalid db query response for snapshot %s" % snapshotid
+    assert len(qresultset) != 0, "No such snapshot %s found in the cloudstack db" % snapshotid
+
+    snapshotPath = qresultset[0][0]
+
+    nfsurl = secondaryStore.url
+    # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test']
+    from urllib2 import urlparse
+    parse_url = urlparse.urlsplit(nfsurl, scheme='nfs')
+    host, path = parse_url.netloc, parse_url.path
+
+    if not config.mgtSvr:
+        raise Exception("Your marvin configuration does not contain mgmt server credentials")
+    host, user, passwd = config.mgtSvr[0].mgtSvrIp, config.mgtSvr[0].user, config.mgtSvr[0].passwd
+
+    try:
+        ssh_client = remoteSSHClient(
+            host,
+            22,
+            user,
+            passwd,
+        )
+        cmds = [
+                "mkdir -p %s /mnt/tmp",
+                "mount -t %s %s:%s /mnt/tmp" % (
+                    'nfs',
+                    host,
+                    path,
+                    ),
+                "test -f %s && echo 'snapshot exists'" % (
+                    os.path.join("/mnt/tmp", snapshotPath)
+                    ),
+            ]
+
+        for c in cmds:
+            result = ssh_client.execute(c)
+
+        # Unmount the Sec Storage
+        cmds = [
+                "cd",
+                "umount /mnt/tmp",
+            ]
+        for c in cmds:
+            ssh_client.execute(c)
+    except Exception as e:
+        raise Exception("SSH failed for management server: %s - %s" %
+                      (config[0].mgtSvrIp, e))
+    return 'snapshot exists' in result
+
+def is_config_suitable(apiclient, name, value):
+    """
+    Ensure if the deployment has the expected `value` for the global setting `name'
+    @return: true if value is set, else false
+    """
+    configs = Configuration.list(apiclient, name=name)
+    assert(configs is not None and isinstance(configs, list) and len(configs) > 0)
+    return configs[0].value == value
+
+def wait_for_cleanup(apiclient, configs=None):
+    """Sleeps till the cleanup configs passed"""
+
+    # Configs list consists of the list of global configs
+    if not isinstance(configs, list):
+        return
+    for config in configs:
+        configs = Configuration.list(apiclient, name=config, listall=True)
+        config_desc = configs[0]
+        # Sleep for the config_desc.value time
+        time.sleep(int(config_desc.value))
+    return


[48/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: simple vpc lifecycle test

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/a8016963
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/a8016963
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/a8016963

Branch: refs/heads/marvin-refactor
Commit: a8016963990083835c741992af4e785bcf59f155
Parents: c9da418
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Oct 2 19:46:33 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:16 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/test/test_vpc_life_cycle.py | 101 +++++++++++++++++++
 1 file changed, 101 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a8016963/tools/marvin/marvin/test/test_vpc_life_cycle.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/test/test_vpc_life_cycle.py b/tools/marvin/marvin/test/test_vpc_life_cycle.py
new file mode 100644
index 0000000..d247673
--- /dev/null
+++ b/tools/marvin/marvin/test/test_vpc_life_cycle.py
@@ -0,0 +1,101 @@
+# 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.cloudstackTestCase import *
+from marvin.factory.data.account import *
+from marvin.factory.data.vm import *
+from should_dsl import *
+from marvin.util import *
+from nose.plugins.attrib import attr
+
+
+class TestVpcLifeCycle(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        cls.apiclient = super(TestVpcLifeCycle, cls).getClsTestClient().getApiClient()
+        cls.zoneid = get_zone(cls.apiclient).id
+        cls.templateid = get_template(cls.apiclient).id,
+        cls.serviceofferingid = get_service_offering(cls.apiclient).id,
+        cls.account = UserAccount(
+            apiclient=cls.apiclient
+        )
+
+    @attr(tags='debug')
+    def test_deployvm(self):
+        vm = VpcVirtualMachine(
+            apiclient=self.apiclient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            zoneid=self.zoneid,
+            templateid=self.templateid,
+            serviceofferingid=self.serviceofferingid
+        )
+        vm.state | should | equal_to('Running')
+
+    def test_stopvm(self):
+        vm = VpcVirtualMachine(
+            apiclient=self.apiclient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            zoneid=self.zoneid,
+            templateid=self.templateid,
+            serviceofferingid=self.serviceofferingid
+        )
+        vm.stop()
+        vm.state | should | equal_to('Stopped')
+
+    def test_startvm(self):
+        vm = VpcVirtualMachine(
+            apiclient=self.apiclient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            zoneid=self.zoneid,
+            templateid=self.templateid,
+            serviceofferingid=self.serviceofferingid
+        )
+        vm.stop()
+        vm.start()
+        vm.state | should | equal_to('Running')
+
+    def test_rebootvm(self):
+        vm = VpcVirtualMachine(
+            apiclient=self.apiclient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            zoneid=self.zoneid,
+            templateid=self.templateid,
+            serviceofferingid=self.serviceofferingid
+        )
+        vm.reboot()
+        vm.state | should | equal_to('Running')
+
+    def test_destroyvm(self):
+        vm = VpcVirtualMachine(
+            apiclient=self.apiclient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            zoneid=self.zoneid,
+            templateid=self.templateid,
+            serviceofferingid=self.serviceofferingid
+        )
+        vm.destroy()
+        vm.state | should | equal_to('Destroyed')
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.account.delete()
\ No newline at end of file


[37/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: security group splits into ingress/egress

@also Include the apiclient as part of the factory instantiation so
there is not redundant parameter when dealing with the object after it
is generated by the factory.

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/9f759a8a
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/9f759a8a
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/9f759a8a

Branch: refs/heads/marvin-refactor
Commit: 9f759a8ae9ba5fc3757d111618117d5e348b8333
Parents: 7d4b35d
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Mon Sep 30 09:53:19 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:00 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/generate/entity.py   | 30 +++++++++++++++++++++------
 tools/marvin/marvin/generate/linguist.py | 10 +++++++++
 2 files changed, 34 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9f759a8a/tools/marvin/marvin/generate/entity.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/entity.py b/tools/marvin/marvin/generate/entity.py
index 2d7b627..f9d63dc 100644
--- a/tools/marvin/marvin/generate/entity.py
+++ b/tools/marvin/marvin/generate/entity.py
@@ -103,14 +103,32 @@ class Entity(object):
             #TODO: doc to explain what possible args go into **kwargs
             m.docstring = 'Placeholder for docstring\n' + 'optional arguments (**kwargs): [%s]"""' % ', '.join(
                 details['optionals'])
-            if not m.is_creator():
-                # remove the id arg as id is the self (object) itself
-                no_id_args = filter(lambda arg: arg != 'id', details['args'])
+            # remove the id arg as id is the self (object) itself
+            no_id_args = filter(lambda arg: arg != 'id', details['args'])
+            if m.is_enumerator():
+                m.signature = 'def %s(cls, apiclient=None, **kwargs):' % (action)
+                m.body.append(self.tabspace + 'cmd = %(module)s.%(command)s()' % {"module": details["apimodule"],
+                                                                                 "command": details["apicmd"]})
+                m.body.append(self.tabspace + '[setattr(cmd, key, value) for key, value in kwargs.iteritems()]')
+                m.body.append(self.tabspace + 'if apiclient:')
+                m.body.append(self.tabspace*2 + '%s = apiclient.%s(cmd)' % (entity.lower(), details['apimodule']))
+                m.body.append(self.tabspace + 'else:')
+                m.body.append(self.tabspace*2 + '%s = cls.apiclient.%s(cmd)' % (entity.lower(), details['apimodule']))
+                m.body.append(self.tabspace + '%s = map(lambda e: %s().__update__(e.__dict__), %s) '
+                                              'if %s and len(%s) > 0 else None' % ( entity.lower(),
+                                                                                    entity, entity.lower(),
+                                                                                    entity.lower(), entity.lower()))
+                m.body.append(
+                    self.tabspace + '%s = map(lambda e: e.__update__({\'apiclient\': apiclient if apiclient else cls.apiclient}), %s) if %s else None' % (
+                    entity.lower(), entity.lower(), entity.lower())
+                                  )
+                m.body.append(self.tabspace + 'return %s' % entity.lower())
+            elif not m.is_creator():
                 if len(no_id_args) > 0: # at least one required non-id argument
-                    m.signature = 'def %s(self, apiclient, %s, **kwargs):'\
+                    m.signature = 'def %s(self, %s, **kwargs):'\
                     % (action, ', '.join(list(set(no_id_args))))
                 else:
-                    m.signature = 'def %s(self, apiclient, **kwargs):' % (action)
+                    m.signature = 'def %s(self, **kwargs):' % (action)
                 m.body.append(self.tabspace + 'cmd = %(module)s.%(command)s()' % {"module": details["apimodule"],
                                                                                  "command": details["apicmd"]})
                 if 'id' in details['args']:
@@ -118,7 +136,7 @@ class Entity(object):
                 for arg in no_id_args:
                     m.body.append(self.tabspace + 'cmd.%s = %s' % (arg, arg))
                 m.body.append(self.tabspace + '[setattr(cmd, key, value) for key, value in kwargs.iteritems()]')
-                m.body.append(self.tabspace + '%s = apiclient.%s(cmd)' % (entity.lower(), details['apimodule']))
+                m.body.append(self.tabspace + '%s = self.apiclient.%s(cmd)' % (entity.lower(), details['apimodule']))
                 if m.is_enumerator():
                     m.body.append(self.tabspace +
                                   'return map(lambda e: %s().__update__(e.__dict__), %s) '

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9f759a8a/tools/marvin/marvin/generate/linguist.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/linguist.py b/tools/marvin/marvin/generate/linguist.py
index ec1f693..5e7b1c3 100644
--- a/tools/marvin/marvin/generate/linguist.py
+++ b/tools/marvin/marvin/generate/linguist.py
@@ -39,6 +39,14 @@ def transform_api(api):
         return 'login', 'CloudStack'
     elif api == 'logout':
         return 'logout', 'CloudStack'
+    elif api == 'authorizeSecurityGroupIngress':
+        return 'authorizeSecurityGroupIngress', 'SecurityGroup'
+    elif api == 'authorizeSecurityGroupEgress':
+        return 'authorizeSecurityGroupEgress', 'SecurityGroup'
+    elif api == 'revokeSecurityGroupIngress':
+        return 'revokeSecurityGroupIngress', 'SecurityGroup'
+    elif api == 'revokeSecurityGroupEgress':
+        return 'revokeSecurityGroupEgress', 'SecurityGroup'
     return api, None
 
 def verb_adjust(api, entity):
@@ -89,6 +97,8 @@ def entity_adjust(entity):
         return 'UserKeys'
     elif entity == 'FirewallRule':
         return 'Firewall'
+    elif entity == 'SecurityGroupRule':
+        return 'SecurityGroup'
     #Cloudstack maintains Template/ISO/Volume as single Image type
     #elif entity in ['Template', 'Volume']:
     #    return 'Image'


[42/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: docs for design and internals


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/c1524f3b
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/c1524f3b
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/c1524f3b

Branch: refs/heads/marvin-refactor
Commit: c1524f3b4d43263e479c30d8c2db215680f01a89
Parents: 8373183
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Oct 2 11:26:55 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:07 2013 +0530

----------------------------------------------------------------------
 tools/marvin/docs/DESIGN.markdown | 447 +++++++++++++++++++++++++++++++++
 tools/marvin/docs/errata.markdown |  29 +++
 tools/marvin/docs/errata.md       |  22 --
 3 files changed, 476 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c1524f3b/tools/marvin/docs/DESIGN.markdown
----------------------------------------------------------------------
diff --git a/tools/marvin/docs/DESIGN.markdown b/tools/marvin/docs/DESIGN.markdown
new file mode 100644
index 0000000..b88c43c
--- /dev/null
+++ b/tools/marvin/docs/DESIGN.markdown
@@ -0,0 +1,447 @@
+# Marvin Refactor
+The Marvin test framework will undergo some key improvements as part of this
+refactor:
+
+1. All CloudStack resources modelled as entities which are more object-oriented
+2. Data modelled as factories that form basic building blocks
+3. DSL support for assertions
+
+## Introduction
+Marvin which has been used thus far for testing has undergone several
+significant changes in this refactor. Many of these changes were driven by the
+need for succinctly describing a test scenario in a few lines of code. This
+document describes the changes and the reasons behind this refactor. While this
+makes the framework simple to use the internals of marvin have become a bit
+complex. For this reason we will cover some of the internal workings as part of
+this document.
+
+## Rationale
+Two main rationale were responsible for this refactor
+
+1. Brittle nature of the integration library
+2. Separating data from the test
+
+### Integration library
+Typically to write a test case previously the test case author was expected to
+know (in advance) all the APIs he was going to call to complete his scenario.
+With the growing list of APIs, their parameters and optional arguments it
+becomes tedious often to compose a single API call. To overcome this the
+integration libraries were written.  These libraries (`integration.lib.base,
+integration.lib.common` etc) present a list of resources or entities - eg:
+VirtualMachine, VPC, VLAN to the library user. Each entity can perform a set of
+operations that in turn transform into an API call.
+
+```python
+class VirtualMachine(object):
+    def deploy(self, apiclient, service, template, zone):
+        cmd = deployVirtualMachine.deployVirtualMachineCmd()
+        cmd.serviceofferingid = service
+        cmd.templateid = template
+    ...
+    ...
+    def list(self,apiclient)
+        cmd = listVirtualMachines.listVirtualMachinesCmd()
+        return apiclient.listVirtualMachines(cmd)
+```
+This makes the library usage more object-oriented. So in the testcase the
+author only has to make a call to the VirtualMachine class when
+creating/destroying/starting/stopping virtualmachine instances.
+
+The disadvantage of this approach is that the integration library is
+hand-written and brittle. When changes are made several tests are affected in
+the process. There are also inconsistencies caused by mixing the data required
+for the API call with the arguments of the operation being performed. eg:
+
+```python
+class VirtualMachine(object):
+....
+    @classmethod
+    def create(cls, apiclient, services, templateid=None, accountid=None,
+                    domainid=None, zoneid=None, networkids=None, serviceofferingid=None,
+                    securitygroupids=None, projectid=None, startvm=None,
+                    diskofferingid=None, affinitygroupnames=None, group=None,
+                    hostid=None, keypair=None, mode='basic', method='GET'):
+             ....
+             ....
+````
+In this call, every argument is optionally lookedup in the services dictionary
+or as part of the argument thereby complicating the body of the create(..)
+call. Also the naming and the size of the API call is daunting for anyone using
+the library.
+
+### Data vs Test
+Another major disadvantage of the previous approach was data required for the
+test was mixed with the test itself.  This made it difficult to generate new
+data from existing data objects. Data being highly coupled with the test
+reduces readability.
+
+Additionaly due to the strict structure of this data it would impose itself
+onto the implementation of a resource's methods in the integration library.
+
+However all of the data is reusable by other tests if presented as factories.
+The refactor will address this using factories that act as building blocks for
+creating reusable data. The document also describes how these blocks are extended.
+
+## CloudStack API Generation
+The process of API module generation remains the same as before. CloudStack
+expresses its API in XML and JSON via the ApiDiscovery plugin. For instance the
+createFirewallRule API looks as follows (some fields removed for brevity)
+
+```json
+ "api": [
+            {
+                "name": "createFirewallRule",
+                "description": "Creates a firewall rule for a given ip address",
+                "isasync": true,
+                "params": [
+                    {
+                        "name": "cidrlist",
+                        "description": "the cidr list to forward traffic from",
+                        "type": "list",
+                        "length": 255,
+                        "required": false
+                    },
+                    {
+                        "name": "icmpcode",
+                    },
+                    {
+                        "name": "icmptype",
+                    },
+                    {
+                        "name": "type",
+                    },
+                ],
+                "response": [
+                    {
+                        "name": "state",
+                        "description": "the state of the rule",
+                        "type": "string"
+                    },
+                    {
+                        "name": "endport",
+                    },
+                    {
+                        "name": "protocol",
+                    },
+                ],
+                "entity": "Firewall"
+            }
+        ]
+ ```
+
+This JSON/XML can be used to create a binding in your favorite language and for
+Marvin's purpose this will be python.  An API module named
+createFirewallRule.py with two classes (request and response) -
+createFirewallRuleCmd and createFirewallRuleResponse represents the creation of
+firewall rules.
+
+### Changes to API Discovery
+Generated API modules now include the `entity` attribute from the listApi
+response. The API discovery plugin has been enhanced to include the type of
+entity that an API is acting upon. For instance when doing createFirewallRule
+the entity that the user is dealing with is the `Firewall`. We do not
+intuitively guess what entity an API acts upon but depend on the CloudStack
+endpoint to tell us this information. Mostly because we cannot always predict
+the entity an API acts upon using the name of the API
+
+eg: dedicatePublicIpRange
+
+```json
+listapisresponse: {
+    count: 1,
+    api: [
+    {
+        name: "dedicatePublicIpRange",
+        description: "Dedicates a Public IP range to an account",
+        isasync: false,
+        related: "listVlanIpRanges",
+        params: [],
+        response: [],
+        entity: "VlanIpRange"
+     }
+    ]
+  }
+}
+```
+
+This transforms into the following Marvin entity class through auto-generation:
+
+```python
+class VlanIpRange(CloudStackEntity):
+
+    def dedicate(self, apiclient, account, domainid, **kwargs):
+        cmd = dedicatePublicIpRange.dedicatePublicIpRangeCmd()
+        cmd.id = self.id
+        cmd.account = account
+        cmd.domainid = domainid
+        [setattr(cmd, key, value) for key,value in kwargs.iteritems()]
+        publiciprange = apiclient.dedicatePublicIpRange(cmd)
+        return publiciprange if publiciprange else None
+
+```
+
+> kwargs represents all the optional arguments for dedicatePublicIpRange
+
+The use of the entity in generating a higher level model for the CloudStack API
+is described in the next section.
+
+## Entity and Factory Generation
+Marvin now includes a new module named `generate` that contains all the code
+generators.
+
+1. `xmltoapi.py` - this module is responsible for converting the JSON/XML
+response to a python binding. Previously this was the `codegenerator.py`
+2. `apitoentity.py` - this module is responsible for grouping actions on a
+given entity into a single module and define all its actions as methods on the
+entity object.
+3. `entity.py` - is the base entity creator that transforms an API into a
+cloudstackEntity
+4. `factory.py` - is the base factory creator that transforms an API into a
+factory
+
+For eg: in the method createFirewallRule the `entity` is the Firewall and the
+`action` being performed on the entity is `create`
+
+So our entity becomes
+
+```python
+class Firewall:
+    def create(...):
+        createFirewallRule()
+```
+
+Almost all APIs are transformed naturally into this model but there are a few
+exceptions. These exceptions are dealt with by the `linguist.py` module in
+which APIs that don't split this way are broken down using special
+transformers.
+
+### Required and Optional Arguments
+All required arguments to an API will be available in the API operation
+
+```python
+Entity.verb(reqd1=None, reqd2=None, ..., **kwargs)
+```
+
+Here the `Entity` (eg:Firewall) can perform an operation `verb()` (eg:create)
+using the arguments `[reqd1, reqd2]`.  The optional arguments (if any) will be
+passed as key, value pairs to the keyword args `**kwargs`.
+
+All entity classes are autogenerated and placed in the `marvin.entity` module.
+You may want to look at some sample entities like virtualmachine.py or
+network.py. To anyone who has used the previous version of marvin, these will
+look familiar. If you are looking at them for the first time, it will be
+obvious to you that each entity is a simple class defined with CRUD operations
+that map to the cloudStack API.
+
+1. **Creators**
+A creator of an entity is the API operation that brings the entity into
+existence on the cloud. For instance a firewall rule is created using the
+createFirewallRule API. Or a virtualmachine comes into existence with the
+deployVirtualMachine command. These are our creators for entities firewall and
+virtualmachines respectively. Every entity class's `__init__` method is
+basically a call to its creator
+
+2. **Enumerators**
+Often it is not necessary to bring an entity into existence since it is already
+present on the cloud infrastructure. We simply list* these entities and should
+still be able to treat them and use them like entities created using their
+corresponding creator methods. The list* APIs become our enumerators for each
+entity.
+
+## Factories
+Factories in cloudstack are implemented using the
+[factory_boy](http://factoryboy.readthedocs.org/en/latest/) framework.  The
+factory_boy framework helps cloudstack define complex relationships in its
+model. For eg.  In order to create a virtualmachine typically one needs a
+service offering, a template and a zone present to be able to launch the VM.
+Factory boy enables traversing these object relationships effectively
+(top-down or bottom-up) to create those objects.
+
+Every entity in the new framework is created using its corresponding factory
+`EntityFactory`. Factories can be thought of as objects that carry necessary
+and sufficient data to satisfy the API call that brings the entity into
+existence.  For example in order to create an account the `AccountFactory` will
+carry the `firstname, lastname, email, username` of the Account since these
+are the required arguments to the `createAccount` API.
+
+So the account factory looks as follows:
+
+```python
+import factory
+
+class AccountFactory(factory):
+
+    FACTORY_FOR = Account
+
+    accounttype = None
+    firstname = None
+    lastname = None
+    email = None
+    username = None
+    password = None
+```
+
+Here the `AccountFactory` is a bare representation with all None fields. These
+are the default factories. The default factories are simply base classes for
+defining hierarchical data using inheritance. For instance we have three
+types of accounts in cloudstack - DomainAdmin, Admin and User
+
+Each of these accounttypes represents an inheritance from the AccountFactory.
+And for each factory we have a specific value for the `accounttype`. In fact we
+don't have to repeat ourselves when defining a factory for each type of account:
+
+> UserAccount(AccountFactory)
+
+> AdminAccount(UserAccount) with (accounttype=1)
+
+> DomainAdminAccount(UserAccount) with (accounttype=2)
+
+By simply altering the accounttype and having Admin and DomainAdmin inherit
+from User we have defined factories for all types of accounts in cloudstack
+
+In order to create accounts in our tests all we have to do is the following:
+
+```python
+class TestAccounts(cloudstackTestCase):
+
+    def setUp(...):
+        apiclient = getApiClient()
+
+    def test_AccountForUser(...):
+        user = UserAccount(apiclient)
+        assert user is valid
+
+    def test_AccountForAdmin(...):
+        admin = AdminAccount(apiclient)
+        assert admin is valid
+
+    def test_AccountForDomainAdmin(...):
+        domadmin = DomainAdminAccount(apiclient)
+        assert domadmin is active
+
+    def tearDown(...):
+        user.delete()
+        admin.delete()
+        domadmin.delete()
+```
+
+## Basic tools for extending factories
+
+### Sequences
+Sequences are provided by factory boy to randomize the object generated by each
+call to the factory. Typically these are incremented integers but for the
+CloudStack objects each distinguishing attribute is randomized to prevent
+collisions and duplicate objects.
+
+To define an attribute as a sequence we simply call the factory.Sequence(..)
+method with a lambda function defining said sequence.
+
+eg:
+
+```python
+    class SharedNetworkOffering(NetworkOfferingFactory):
+        name = factory.Sequence(lambda n: 'SharedOffering' + my_random_generator_function(n))
+        ...
+```
+
+### SubFactory
+SubFactories are an important factory_boy building block for creating factories
+that depend on other factories.
+
+For eg: in order to create a SharedNetwork a networkofferingid of a
+SharedNetworkOffering is required. So we first call on the factory of
+SharedNetworkOffering using the factory.SubFactory(..) and use the id to create
+the SharedNetwork using the SharedNetwork's factory
+
+```python
+class SharedNetwork(NetworkFactory):
+    name = factory.Sequence(...)
+    networkoffering = \
+        factory.SubFactory(
+            SharedNetworkOffering,
+            attr1=val1
+        )
+    networkofferingid = networkoffering.id
+```
+
+RelatedFactory is a special case of SubFactory in that RelatedFactories are
+created after the existing factory is created.
+
+SubFactories are very powerful to chain many factories together to compose
+complex objects in cloudstack.
+
+### PostGeneration Hooks
+In many cases additional hooks are done to simplify working with cloud
+resources. For instance, when creating a virtual machine in an advanced zone it
+is useful to associate a NAT rule to be able to SSH into the virtual machine
+for post processing the effects on the virtualmachine like testing connectivity
+to the internet for instance. PostGeneration hooks work after factories have
+been created to perform such special functions. For examples, check the
+`marvin.factory.data.vm` module for the VirtualMachineWithStaticNat factory
+where we create a static nat rule allowing SSH access to the created VM.
+
+## Guidelines for defining new factories
+All factories are auto-generated and there is no need to define the default
+factories. Test case authors will mostly be creating data factories inherited
+from the default factories. All the data factories are defined in
+`marvin.factory.data`. Currently implementations are provided for often used
+data objects.
+
+1. networkoffering
+2. networks
+3. service and disk offerings
+4. security groups
+5. virtualmachine
+6. vpcoffering
+7. vpcvirtualmachine
+8. firewallrules
+9. ingress and egress rules
+
+and many more implementations should serve as examples to extend new data
+objects.
+
+Factory naming convention is simple. Any data inheriting from default factory
+`EntityFactory` should be named without the suffix `Factory`. The data should
+take the name of the purpose of the factory. Use simple prepositions
+(Of,And,With etc) to combine words. For instance: VirtualMachineWithStaticNat
+or VirtualMachineInIsolatedNetwork. Naming the data clearly aids its widespread
+use. A badly named factory will likely not be used in more than one test.
+
+## Should DSL assertions
+The typical assertion capabilites of unittest are enough to express all
+validation but it does not read naturally. Should_dsl is a library that makes
+the assertions read like natural language. This is installed by default with
+marvin now enabling all test cases to write assertions using simple dsl
+statements
+
+eg:
+
+```python
+    vm = VirtualMachineIsolatedNetwork(apiclient)
+    vm.state | should | equal_to('Running')
+    vm.nic | should_not | be(None)
+```
+
+## Utilities
+All the pre-existing utilities from the previous `util.py` are still available
+with enhancements in the util.py module. The legacy util.py module is
+deprecated but retained since older tests refer to this module. All new changes
+should go to the util.py under marvin/
+
+## unittest2 and nose2
+Marvin earlier was coupled with Python2.7 since python's unittest did not have
+the same capabilites in versions <2.7. With unittest2 all features are now
+backported to older python implementations. Marvin has also switched to
+unittest2 so that we don't have to depend on the specific version of python to
+be able to install and use marvin for testing. This change is internal and
+should not be felt by the test case writer.
+
+> There are plans to move to nose2 as well but this is separated from factory
+> work at the moment.
+
+## Legacy Libraries and Tests
+In order to not disrupt the running of existing tests all the older libraries
+in `base.py`, `common.py` and `util.py` are moved to the legacy module. Any new
+tests should be written using factories. Older libraries are retained to be
+able to run our existing tests whose imports will be switched as part of this
+refactor.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c1524f3b/tools/marvin/docs/errata.markdown
----------------------------------------------------------------------
diff --git a/tools/marvin/docs/errata.markdown b/tools/marvin/docs/errata.markdown
new file mode 100644
index 0000000..4890d3d
--- /dev/null
+++ b/tools/marvin/docs/errata.markdown
@@ -0,0 +1,29 @@
+## Marvin Refactor
+
+### Bugs
+- marvin build now requires inflect, should-dsl, unittest2 which will cause -Pdeveloper profile to break for the first time
+- Entities should include @docstring for optional arguments in their actions() methods. **kwargs is confusing
+- Handle APIs that need parameters but dont have a required args list because multiple sets of args form a required list
+	- eg: disableAccount (either provide id (account) or accoutname and domainid)
+- Better sync functionality
+- Bump up version to 0.2.0/Versioning based on cloudmonkey/cloudstack
+- Improved cleanup support using unittest2.addCleanup()
+- If setUp() fails how to handle tearDown()
+
+### Features
+- Export deployment to JSON [CLOUDSTACK-4590](https://issues.apache.org/jira//browse/CLOUDSTACK-4590)
+- nose2 support [CLOUDSTACK-4591](https://issues.apache.org/jira//browse/CLOUDSTACK-4591)
+- Python pip repository for cloudstack-marvin
+- Docs from readthedocs.org using sphinx
+- support for correlating test with cloud resources
+
+### Future
+- DSL for marvin using Behave [CLOUDSTACK-1952](https://issues.apache.org/jira/browse/CLOUDSTACK-1952)
+
+### Fixed
+- marvin.sync and xml compilation produce different versions of cloudstackAPI
+- Dissociate the grammar list to make it extensible via a properties file
+- XML precache required for factory and base generation [CLOUDSTACK-4589](https://issues.apache.org/jira//browse/CLOUDSTACK-4589)
+- Remove marvin dependency with apidoc build. Provide precache json [CLOUDSTACK-4589](https://issues.apache.org/jira//browse/CLOUDSTACK-4589)
+- unittest2 support added with [CLOUDSTACK-4591](https://issues.apache.org/jira//browse/CLOUDSTACK-4591)
+- Use distutils

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c1524f3b/tools/marvin/docs/errata.md
----------------------------------------------------------------------
diff --git a/tools/marvin/docs/errata.md b/tools/marvin/docs/errata.md
deleted file mode 100644
index f626069..0000000
--- a/tools/marvin/docs/errata.md
+++ /dev/null
@@ -1,22 +0,0 @@
-## Idea Stack
-
-### Bugs
-
-- **marvin.sync and xml compilation produce different versions of cloudstackAPI**
-- marvin build now requires inflect which will cause -Pdeveloper profile to break for the first time
-- Entities should include @docstring for optional arguments in their actions() methods. **kwargs is confusing
-- Dissociate the grammar list to make it extensible via a properties file
-- Handle APIs that need parameters but dont have a required args list because multiple sets of args form a required list
-	- eg: disableAccount (either provide id (account) or accoutname and domainid)
-- XML precache required for factory and base generation [CLOUDSTACK-4589](https://issues.apache.org/jira//browse/CLOUDSTACK-4589)
-- Remove marvin dependency with apidoc build. Provide precache json [CLOUDSTACK-4589](https://issues.apache.org/jira//browse/CLOUDSTACK-4589)
-- Better sync functionality
-- Bump up version to 0.2.0
-- Improved cleanup support
-
-### Features
-- Export deployment to JSON [CLOUDSTACK-4590](https://issues.apache.org/jira//browse/CLOUDSTACK-4590)
-- nose2 and unittest2 support [CLOUDSTACK-4591](https://issues.apache.org/jira//browse/CLOUDSTACK-4591)
-- Use distutils
-- Python pip repository for cloudstack-marvin
-- DSL for marvin using Behave [CLOUDSTACK-1952](https://issues.apache.org/jira/browse/CLOUDSTACK-1952)
\ No newline at end of file


[41/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: CLOUDSTACK-4591 - switch to unittest2

Switch marvin to unittest2 so as to support multiple python versions

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/83731835
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/83731835
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/83731835

Branch: refs/heads/marvin-refactor
Commit: 83731835753ec1d609883fbafa43797765a358c1
Parents: e3d9359
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Mon Sep 30 11:39:58 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:06 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/TestCaseExecuteEngine.py    |  2 +-
 tools/marvin/marvin/cloudstackTestCase.py       |  2 +-
 tools/marvin/marvin/factory/data/vm.py          | 13 ++-----------
 tools/marvin/marvin/sandbox/testSetupSuccess.py |  2 --
 tools/marvin/marvin/test/test_factories.py      |  2 +-
 tools/marvin/marvin/testSetupSuccess.py         |  2 --
 tools/marvin/setup.py                           |  1 +
 7 files changed, 6 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83731835/tools/marvin/marvin/TestCaseExecuteEngine.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/TestCaseExecuteEngine.py b/tools/marvin/marvin/TestCaseExecuteEngine.py
index f5af1fe..6495000 100644
--- a/tools/marvin/marvin/TestCaseExecuteEngine.py
+++ b/tools/marvin/marvin/TestCaseExecuteEngine.py
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import unittest
+import unittest2 as unittest
 import os
 import sys
 import logging

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83731835/tools/marvin/marvin/cloudstackTestCase.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cloudstackTestCase.py b/tools/marvin/marvin/cloudstackTestCase.py
index 85ef542..b337944 100644
--- a/tools/marvin/marvin/cloudstackTestCase.py
+++ b/tools/marvin/marvin/cloudstackTestCase.py
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import unittest
+import unittest2 as unittest
 
 
 def user(Name, DomainName, AcctType):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83731835/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 b9e6345..713c9b5 100644
--- a/tools/marvin/marvin/factory/data/vm.py
+++ b/tools/marvin/marvin/factory/data/vm.py
@@ -39,19 +39,10 @@ class VirtualMachineWithStaticNat(VirtualMachineFactory):
             domainid=self.domainid,
             zoneid=self.zoneid,
         )
-        ssh_fwrule = SshFirewallRule(
-            apiclient=self.apiclient,
-            ipaddressid=ipassoc.id
-        )
-        ntwks = Network.list(
-            apiclient=self.apiclient,
-            account=self.account,
-            domainid=self.domainid,
-        )
-        ntwks[0].enableStaticNat(
+        ipassoc.enableStaticNat(
             apiclient=self.apiclient,
             ipaddressid=ipassoc.id,
-            virtualmachineid=self.id,
+            virtualmachineid=self.id
         )
         self.ssh_ip = ipassoc.ipaddress
         self.public_ip = ipassoc.ipaddress

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83731835/tools/marvin/marvin/sandbox/testSetupSuccess.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/testSetupSuccess.py b/tools/marvin/marvin/sandbox/testSetupSuccess.py
index 8a0034c..452f172 100644
--- a/tools/marvin/marvin/sandbox/testSetupSuccess.py
+++ b/tools/marvin/marvin/sandbox/testSetupSuccess.py
@@ -15,8 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import marvin
-import unittest
 from marvin.cloudstackTestCase import *
 from marvin.cloudstackAPI import *
 from time import sleep as delay

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83731835/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 b3ea0ac..75bf452 100644
--- a/tools/marvin/marvin/test/test_factories.py
+++ b/tools/marvin/marvin/test/test_factories.py
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import unittest
+import unittest2 as unittest
 import logging
 from nose.plugins.attrib import attr
 from should_dsl import should, should_not

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83731835/tools/marvin/marvin/testSetupSuccess.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/testSetupSuccess.py b/tools/marvin/marvin/testSetupSuccess.py
index 1701626..9652fa0 100644
--- a/tools/marvin/marvin/testSetupSuccess.py
+++ b/tools/marvin/marvin/testSetupSuccess.py
@@ -15,8 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import marvin
-import unittest
 from marvin.cloudstackTestCase import *
 from marvin.cloudstackAPI import *
 from time import sleep as delay

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83731835/tools/marvin/setup.py
----------------------------------------------------------------------
diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py
index 4a1cbc2..231a00a 100644
--- a/tools/marvin/setup.py
+++ b/tools/marvin/setup.py
@@ -49,6 +49,7 @@ setup(name="Marvin",
               "marvin.test"],
     license="LICENSE.txt",
     install_requires=[
+        "unittest2",
         "mysql-connector-python",
         "requests",
         "paramiko",


[12/50] [abbrv] marvin-refactor: moving old integration libraries to legacy

Posted by ts...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/79a1591b/tools/marvin/marvin/legacy/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/legacy/base.py b/tools/marvin/marvin/legacy/base.py
new file mode 100644
index 0000000..d0cfc47
--- /dev/null
+++ b/tools/marvin/marvin/legacy/base.py
@@ -0,0 +1,3591 @@
+# 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.
+
+""" Base class for all Cloudstack resources
+    -Virtual machine, Volume, Snapshot etc
+"""
+
+from marvin.utils import is_server_ssh_ready, random_gen
+from marvin.cloudstackAPI import *
+# Import System modules
+import time
+import hashlib
+import base64
+
+
+class Domain:
+    """ Domain Life Cycle """
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, name=None, networkdomain=None,
+               parentdomainid=None):
+        """Creates an domain"""
+
+        cmd = createDomain.createDomainCmd()
+
+        if "domainUUID" in services:
+            cmd.domainid = "-".join([services["domainUUID"], random_gen()])
+
+        if name:
+            cmd.name = "-".join([name, random_gen()])
+        elif "name" in services:
+            cmd.name = "-".join([services["name"], random_gen()])
+
+        if networkdomain:
+            cmd.networkdomain = networkdomain
+        elif "networkdomain" in services:
+            cmd.networkdomain = services["networkdomain"]
+
+        if parentdomainid:
+            cmd.parentdomainid = parentdomainid
+        elif "parentdomainid" in services:
+            cmd.parentdomainid = services["parentdomainid"]
+        try:
+            domain = apiclient.createDomain(cmd)
+            if domain is not None:
+                return Domain(domain.__dict__)
+        except Exception as e:
+            raise e
+
+    def delete(self, apiclient, cleanup=None):
+        """Delete an domain"""
+        cmd = deleteDomain.deleteDomainCmd()
+        cmd.id = self.id
+        if cleanup:
+            cmd.cleanup = cleanup
+        apiclient.deleteDomain(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists domains"""
+        cmd = listDomains.listDomainsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listDomains(cmd))
+
+
+class Account:
+    """ Account Life Cycle """
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, admin=False, domainid=None):
+        """Creates an account"""
+        cmd = createAccount.createAccountCmd()
+
+        # 0 - User, 1 - Root Admin, 2 - Domain Admin
+        cmd.accounttype = 2 if (admin and domainid) else int(admin)
+
+        cmd.email = services["email"]
+        cmd.firstname = services["firstname"]
+        cmd.lastname = services["lastname"]
+
+        cmd.password = services["password"]
+        cmd.username = "-".join([services["username"], random_gen(id=apiclient.id)])
+
+        if "accountUUID" in services:
+            cmd.accountid =  "-".join([services["accountUUID"],random_gen()])
+
+        if "userUUID" in services:
+            cmd.userid = "-".join([services["userUUID"],random_gen()])
+
+
+        if domainid:
+            cmd.domainid = domainid
+        account = apiclient.createAccount(cmd)
+
+        return Account(account.__dict__)
+
+    def delete(self, apiclient):
+        """Delete an account"""
+        cmd = deleteAccount.deleteAccountCmd()
+        cmd.id = self.id
+        apiclient.deleteAccount(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists accounts and provides detailed account information for
+        listed accounts"""
+
+        cmd = listAccounts.listAccountsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listAccounts(cmd))
+
+
+class User:
+    """ User Life Cycle """
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, account, domainid):
+        cmd = createUser.createUserCmd()
+        """Creates an user"""
+
+        cmd.account = account
+        cmd.domainid = domainid
+        cmd.email = services["email"]
+        cmd.firstname = services["firstname"]
+        cmd.lastname = services["lastname"]
+
+        if "userUUID" in services:
+            cmd.userid = "-".join([services["userUUID"],random_gen()])
+
+        cmd.password = services["password"]
+        cmd.username = "-".join([services["username"], random_gen()])
+        user = apiclient.createUser(cmd)
+
+        return User(user.__dict__)
+
+    def delete(self, apiclient):
+        """Delete an account"""
+        cmd = deleteUser.deleteUserCmd()
+        cmd.id = self.id
+        apiclient.deleteUser(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists users and provides detailed account information for
+        listed users"""
+
+        cmd = listUsers.listUsersCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listUsers(cmd))
+
+    @classmethod
+    def registerUserKeys(cls, apiclient, userid):
+        cmd = registerUserKeys.registerUserKeysCmd()
+        cmd.id = userid
+        return apiclient.registerUserKeys(cmd)
+
+    def update(self, apiclient, **kwargs):
+        """Updates the user details"""
+
+        cmd = updateUser.updateUserCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return (apiclient.updateUser(cmd))
+
+    @classmethod
+    def update(cls, apiclient, id, **kwargs):
+        """Updates the user details (class method)"""
+
+        cmd = updateUser.updateUserCmd()
+        cmd.id = id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return (apiclient.updateUser(cmd))
+
+    @classmethod
+    def login(cls, apiclient, username, password, domain=None, domainid=None):
+        """Logins to the CloudStack"""
+
+        cmd = login.loginCmd()
+        cmd.username = username
+        cmd.password = password
+        if domain:
+            cmd.domain = domain
+        if domainid:
+            cmd.domainId = domainid
+        return apiclient.login(cmd)
+
+
+class VirtualMachine:
+    """Manage virtual machine lifecycle"""
+
+    def __init__(self, items, services):
+        self.__dict__.update(items)
+        if "username" in services:
+            self.username = services["username"]
+        else:
+            self.username = 'root'
+        if "password" in services:
+            self.password = services["password"]
+        else:
+            self.password = 'password'
+        if "ssh_port" in services:
+            self.ssh_port = services["ssh_port"]
+        else:
+            self.ssh_port = 22
+        self.ssh_client = None
+        # extract out the ipaddress
+        self.ipaddress = self.nic[0].ipaddress
+
+    @classmethod
+    def ssh_access_group(cls, apiclient, cmd):
+        """
+        Programs the security group with SSH access before deploying virtualmachine
+        @return:
+        """
+        zone_list = Zone.list(
+            apiclient,
+            id=cmd.zoneid if cmd.zoneid else None,
+            domainid=cmd.domainid if cmd.domainid else None
+        )
+        zone = zone_list[0]
+        #check if security groups settings is enabled for the zone
+        if zone.securitygroupsenabled:
+            list_security_groups = SecurityGroup.list(
+                apiclient,
+                securitygroupname="basic_sec_grp"
+            )
+
+            if not isinstance(list_security_groups, list):
+                basic_mode_security_group = SecurityGroup.create(
+                    apiclient,
+                    {"name": "basic_sec_grp"}
+                )
+                sec_grp_services = {
+                    "protocol": "TCP",
+                    "startport": 22,
+                    "endport": 22,
+                    "cidrlist": "0.0.0.0/0"
+                }
+                #Authorize security group for above ingress rule
+                basic_mode_security_group.authorize(apiclient, sec_grp_services, account=cmd.account,
+                    domainid=cmd.domainid)
+            else:
+                basic_mode_security_group = list_security_groups[0]
+
+            if isinstance(cmd.securitygroupids, list):
+                cmd.securitygroupids.append(basic_mode_security_group.id)
+            else:
+                cmd.securitygroupids = [basic_mode_security_group.id]
+
+    @classmethod
+    def access_ssh_over_nat(cls, apiclient, services, virtual_machine, allow_egress=False):
+        """
+        Program NAT and PF rules to open up ssh access to deployed guest
+        @return:
+        """
+        public_ip = PublicIPAddress.create(
+            apiclient=apiclient,
+            accountid=virtual_machine.account,
+            zoneid=virtual_machine.zoneid,
+            domainid=virtual_machine.domainid,
+            services=services
+        )
+        FireWallRule.create(
+            apiclient=apiclient,
+            ipaddressid=public_ip.ipaddress.id,
+            protocol='TCP',
+            cidrlist=['0.0.0.0/0'],
+            startport=22,
+            endport=22
+        )
+        nat_rule = NATRule.create(
+            apiclient=apiclient,
+            virtual_machine=virtual_machine,
+            services=services,
+            ipaddressid=public_ip.ipaddress.id
+        )
+        if allow_egress:
+            EgressFireWallRule.create(
+                apiclient=apiclient,
+                networkid=virtual_machine.nic[0].networkid,
+                protocol='All',
+                cidrlist='0.0.0.0/0'
+            )
+        virtual_machine.ssh_ip = nat_rule.ipaddress
+        virtual_machine.public_ip = nat_rule.ipaddress
+
+    @classmethod
+    def create(cls, apiclient, services, templateid=None, accountid=None,
+                    domainid=None, zoneid=None, networkids=None, serviceofferingid=None,
+                    securitygroupids=None, projectid=None, startvm=None,
+                    diskofferingid=None, affinitygroupnames=None, affinitygroupids=None, group=None,
+                    hostid=None, keypair=None, ipaddress=None, mode='default', method='GET'):
+        """Create the instance"""
+
+        cmd = deployVirtualMachine.deployVirtualMachineCmd()
+
+        if serviceofferingid:
+            cmd.serviceofferingid = serviceofferingid
+        elif "serviceoffering" in services:
+            cmd.serviceofferingid = services["serviceoffering"]
+
+        if zoneid:
+            cmd.zoneid = zoneid
+        elif "zoneid" in services:
+            cmd.zoneid = services["zoneid"]
+        cmd.hypervisor = apiclient.hypervisor
+
+        if "displayname" in services:
+            cmd.displayname = services["displayname"]
+
+        if "name" in services:
+            cmd.name = services["name"]
+
+        if accountid:
+            cmd.account = accountid
+        elif "account" in services:
+            cmd.account = services["account"]
+
+        if domainid:
+            cmd.domainid = domainid
+        elif "domainid" in services:
+            cmd.domainid = services["domainid"]
+
+        if networkids:
+            cmd.networkids = networkids
+            allow_egress = False
+        elif "networkids" in services:
+            cmd.networkids = services["networkids"]
+            allow_egress = False
+        else:
+            # When no networkids are passed, network
+            # is created using the "defaultOfferingWithSourceNAT"
+            # which has an egress policy of DENY. But guests in tests
+            # need access to test network connectivity
+            allow_egress = True
+
+        if templateid:
+            cmd.templateid = templateid
+        elif "template" in services:
+            cmd.templateid = services["template"]
+
+        if diskofferingid:
+            cmd.diskofferingid = diskofferingid
+        elif "diskoffering" in services:
+            cmd.diskofferingid = services["diskoffering"]
+
+        if keypair:
+            cmd.keypair = keypair
+        elif "keypair" in services:
+            cmd.keypair = services["keypair"]
+
+        if ipaddress:
+            cmd.ipaddress = ipaddress
+        elif ipaddress in services:
+            cmd.ipaddress = services["ipaddress"]
+
+        if securitygroupids:
+            cmd.securitygroupids = [str(sg_id) for sg_id in securitygroupids]
+
+        if "affinitygroupnames" in services:
+            cmd.affinitygroupnames  = services["affinitygroupnames"]
+        elif affinitygroupnames:
+            cmd.affinitygroupnames  = affinitygroupnames
+
+        if affinitygroupids:
+            cmd.affinitygroupids  = affinitygroupids
+
+        if projectid:
+            cmd.projectid = projectid
+
+        if startvm is not None:
+            cmd.startvm = startvm
+
+        if hostid:
+            cmd.hostid = hostid
+
+        if "userdata" in services:
+            cmd.userdata = base64.urlsafe_b64encode(services["userdata"])
+
+        if group:
+            cmd.group = group
+
+        #program default access to ssh
+        if mode.lower() == 'basic':
+            cls.ssh_access_group(apiclient, cmd)
+
+        virtual_machine = apiclient.deployVirtualMachine(cmd, method=method)
+
+        virtual_machine.ssh_ip = virtual_machine.nic[0].ipaddress
+        if startvm == False:
+            virtual_machine.public_ip = virtual_machine.nic[0].ipaddress
+            return VirtualMachine(virtual_machine.__dict__, services)
+
+        #program ssh access over NAT via PF
+        if mode.lower() == 'advanced':
+            cls.access_ssh_over_nat(apiclient, services, virtual_machine, allow_egress=allow_egress)
+        elif mode.lower() == 'basic':
+            if virtual_machine.publicip is not None:
+                vm_ssh_ip = virtual_machine.publicip #EIP/ELB (netscaler) enabled zone
+            else:
+                vm_ssh_ip = virtual_machine.nic[0].ipaddress #regular basic zone with security group
+            virtual_machine.ssh_ip = vm_ssh_ip
+            virtual_machine.public_ip = vm_ssh_ip
+
+        return VirtualMachine(virtual_machine.__dict__, services)
+
+    def start(self, apiclient):
+        """Start the instance"""
+        cmd = startVirtualMachine.startVirtualMachineCmd()
+        cmd.id = self.id
+        apiclient.startVirtualMachine(cmd)
+
+    def stop(self, apiclient):
+        """Stop the instance"""
+        cmd = stopVirtualMachine.stopVirtualMachineCmd()
+        cmd.id = self.id
+        apiclient.stopVirtualMachine(cmd)
+
+    def reboot(self, apiclient):
+        """Reboot the instance"""
+        cmd = rebootVirtualMachine.rebootVirtualMachineCmd()
+        cmd.id = self.id
+        apiclient.rebootVirtualMachine(cmd)
+
+    def recover(self, apiclient):
+        """Recover the instance"""
+        cmd = recoverVirtualMachine.recoverVirtualMachineCmd()
+        cmd.id = self.id
+        apiclient.recoverVirtualMachine(cmd)
+
+    def get_ssh_client(self, ipaddress=None, reconnect=False, port=None, keyPairFileLocation=None):
+        """Get SSH object of VM"""
+
+        # If NAT Rules are not created while VM deployment in Advanced mode
+        # then, IP address must be passed
+        if ipaddress != None:
+            self.ssh_ip = ipaddress
+        if port:
+            self.ssh_port = port
+
+        if keyPairFileLocation is not None:
+            self.password = None
+
+        if reconnect:
+            self.ssh_client = is_server_ssh_ready(
+                                                    self.ssh_ip,
+                                                    self.ssh_port,
+                                                    self.username,
+                                                    self.password,
+                                                    keyPairFileLocation=keyPairFileLocation
+                                                )
+        self.ssh_client = self.ssh_client or is_server_ssh_ready(
+                                                    self.ssh_ip,
+                                                    self.ssh_port,
+                                                    self.username,
+                                                    self.password,
+                                                    keyPairFileLocation=keyPairFileLocation
+                                                )
+        return self.ssh_client
+
+    def resetSshKey(self, apiclient, **kwargs):
+        """Resets SSH key"""
+
+        cmd = resetSSHKeyForVirtualMachine.resetSSHKeyForVirtualMachineCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.resetSSHKeyForVirtualMachine(cmd))
+
+    def update(self, apiclient, **kwargs):
+        """Updates the VM data"""
+
+        cmd = updateVirtualMachine.updateVirtualMachineCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.updateVirtualMachine(cmd))
+
+    def delete(self, apiclient):
+        """Destroy an Instance"""
+        cmd = destroyVirtualMachine.destroyVirtualMachineCmd()
+        cmd.id = self.id
+        apiclient.destroyVirtualMachine(cmd)
+
+    def migrate(self, apiclient, hostid=None):
+        """migrate an Instance"""
+        cmd = migrateVirtualMachine.migrateVirtualMachineCmd()
+        cmd.virtualmachineid = self.id
+        if hostid:
+            cmd.hostid = hostid
+        apiclient.migrateVirtualMachine(cmd)
+
+    def attach_volume(self, apiclient, volume):
+        """Attach volume to instance"""
+        cmd = attachVolume.attachVolumeCmd()
+        cmd.id = volume.id
+        cmd.virtualmachineid = self.id
+        return apiclient.attachVolume(cmd)
+
+    def detach_volume(self, apiclient, volume):
+        """Detach volume to instance"""
+        cmd = detachVolume.detachVolumeCmd()
+        cmd.id = volume.id
+        return apiclient.detachVolume(cmd)
+
+    def add_nic(self, apiclient, networkId):
+        """Add a NIC to a VM"""
+        cmd = addNicToVirtualMachine.addNicToVirtualMachineCmd()
+        cmd.virtualmachineid = self.id
+        cmd.networkid = networkId
+        return apiclient.addNicToVirtualMachine(cmd)
+
+    def remove_nic(self, apiclient, nicId):
+        """Remove a NIC to a VM"""
+        cmd = removeNicFromVirtualMachine.removeNicFromVirtualMachineCmd()
+        cmd.nicid = nicId
+        cmd.virtualmachineid = self.id
+        return apiclient.removeNicFromVirtualMachine(cmd)
+
+    def update_default_nic(self, apiclient, nicId):
+        """Set a NIC to be the default network adapter for a VM"""
+        cmd = updateDefaultNicForVirtualMachine.updateDefaultNicForVirtualMachineCmd()
+        cmd.nicid = nicId
+        cmd.virtualmachineid = self.id
+        return apiclient.updateDefaultNicForVirtualMachine(cmd)
+
+    def attach_iso(self, apiclient, iso):
+        """Attach ISO to instance"""
+        cmd = attachIso.attachIsoCmd()
+        cmd.id = iso.id
+        cmd.virtualmachineid = self.id
+        return apiclient.attachIso(cmd)
+
+    def detach_iso(self, apiclient):
+        """Detach ISO to instance"""
+        cmd = detachIso.detachIsoCmd()
+        cmd.id = self.id
+        return apiclient.detachIso(cmd)
+
+    def change_service_offering(self, apiclient, serviceOfferingId):
+        """Change service offering of the instance"""
+        cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd()
+        cmd.id = self.id
+        cmd.serviceofferingid = serviceOfferingId
+        return apiclient.changeServiceForVirtualMachine(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all VMs matching criteria"""
+
+        cmd = listVirtualMachines.listVirtualMachinesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listVirtualMachines(cmd))
+
+    def resetPassword(self, apiclient):
+        """Resets VM password if VM created using password enabled template"""
+
+        cmd = resetPasswordForVirtualMachine.resetPasswordForVirtualMachineCmd()
+        cmd.id = self.id
+        try:
+            response = apiclient.resetPasswordForVirtualMachine(cmd)
+        except Exception as e:
+            raise Exception("Reset Password failed! - %s" % e)
+        if response is not None:
+            return response.password
+
+    def assign_virtual_machine(self, apiclient, account, domainid):
+        """Move a user VM to another user under same domain."""
+
+        cmd                  = assignVirtualMachine.assignVirtualMachineCmd()
+        cmd.virtualmachineid = self.id
+        cmd.account          = account
+        cmd.domainid         = domainid
+        try:
+            response = apiclient.assignVirtualMachine(cmd)
+            return response
+        except Exception as e:
+            raise Exception("assignVirtualMachine failed - %s" %e)
+
+    def update_affinity_group(self, apiclient, affinitygroupids=None,
+                              affinitygroupnames=None):
+        """Update affinity group of a VM"""
+        cmd = updateVMAffinityGroup.updateVMAffinityGroupCmd()
+        cmd.id = self.id
+
+        if affinitygroupids:
+            cmd.affinitygroupids = affinitygroupids
+
+        if affinitygroupnames:
+            cmd.affinitygroupnames = affinitygroupnames
+
+        return apiclient.updateVMAffinityGroup(cmd)
+
+
+class Volume:
+    """Manage Volume Life cycle
+    """
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, zoneid=None, account=None,
+               domainid=None, diskofferingid=None, projectid=None):
+        """Create Volume"""
+        cmd = createVolume.createVolumeCmd()
+        cmd.name = services["diskname"]
+
+        if diskofferingid:
+            cmd.diskofferingid = diskofferingid
+        elif "diskofferingid" in services:
+            cmd.diskofferingid = services["diskofferingid"]
+
+        if zoneid:
+            cmd.zoneid = zoneid
+        elif "zoneid" in services:
+            cmd.zoneid = services["zoneid"]
+
+        if account:
+            cmd.account = account
+        elif "account" in services:
+            cmd.account = services["account"]
+
+        if domainid:
+            cmd.domainid = domainid
+        elif "domainid" in services:
+            cmd.domainid = services["domainid"]
+
+        if projectid:
+            cmd.projectid = projectid
+        return Volume(apiclient.createVolume(cmd).__dict__)
+
+    @classmethod
+    def create_custom_disk(cls, apiclient, services, account=None,
+                                    domainid=None, diskofferingid=None):
+        """Create Volume from Custom disk offering"""
+        cmd = createVolume.createVolumeCmd()
+        cmd.name = services["diskname"]
+
+        if diskofferingid:
+            cmd.diskofferingid = diskofferingid
+        elif "customdiskofferingid" in services:
+            cmd.diskofferingid = services["customdiskofferingid"]
+
+        cmd.size = services["customdisksize"]
+        cmd.zoneid = services["zoneid"]
+
+        if account:
+            cmd.account = account
+        else:
+            cmd.account = services["account"]
+
+        if domainid:
+            cmd.domainid = domainid
+        else:
+            cmd.domainid = services["domainid"]
+
+        return Volume(apiclient.createVolume(cmd).__dict__)
+
+    @classmethod
+    def create_from_snapshot(cls, apiclient, snapshot_id, services,
+                             account=None, domainid=None):
+        """Create Volume from snapshot"""
+        cmd = createVolume.createVolumeCmd()
+        cmd.name = "-".join([services["diskname"], random_gen()])
+        cmd.snapshotid = snapshot_id
+        cmd.zoneid = services["zoneid"]
+        cmd.size = services["size"]
+        if account:
+            cmd.account = account
+        else:
+            cmd.account = services["account"]
+        if domainid:
+            cmd.domainid = domainid
+        else:
+            cmd.domainid = services["domainid"]
+        return Volume(apiclient.createVolume(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Volume"""
+        cmd = deleteVolume.deleteVolumeCmd()
+        cmd.id = self.id
+        apiclient.deleteVolume(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all volumes matching criteria"""
+
+        cmd = listVolumes.listVolumesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listVolumes(cmd))
+
+    def resize(self, apiclient, **kwargs):
+        """Resize a volume"""
+        cmd = resizeVolume.resizeVolumeCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.resizeVolume(cmd))
+
+    @classmethod
+    def upload(cls, apiclient, services, zoneid=None, account=None, domainid=None, url=None):
+        """Uploads the volume to specified account"""
+
+        cmd = uploadVolume.uploadVolumeCmd()
+        if zoneid:
+            cmd.zoneid = zoneid
+        if account:
+            cmd.account = account
+        if domainid:
+            cmd.domainid = domainid
+        cmd.format = services["format"]
+        cmd.name = services["diskname"]
+        if url:
+            cmd.url = url
+        else:
+            cmd.url = services["url"]
+        return Volume(apiclient.uploadVolume(cmd).__dict__)
+
+    def wait_for_upload(self, apiclient, timeout=5, interval=60):
+        """Wait for upload"""
+        # Sleep to ensure template is in proper state before download
+        time.sleep(interval)
+
+        while True:
+            volume_response = Volume.list(
+                                    apiclient,
+                                    id=self.id,
+                                    zoneid=self.zoneid,
+                                    )
+            if isinstance(volume_response, list):
+
+                volume = volume_response[0]
+                # If volume is ready,
+                # volume.state = Allocated
+                if volume.state == 'Uploaded':
+                    break
+
+                elif 'Uploading' in volume.state:
+                    time.sleep(interval)
+
+                elif 'Installing' not in volume.state:
+                    raise Exception(
+                        "Error in uploading volume: status - %s" %
+                                                            volume.state)
+            elif timeout == 0:
+                break
+
+            else:
+                time.sleep(interval)
+                timeout = timeout - 1
+        return
+
+    @classmethod
+    def migrate(cls, apiclient, **kwargs):
+        """Migrate a volume"""
+        cmd = migrateVolume.migrateVolumeCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.migrateVolume(cmd))
+
+class Snapshot:
+    """Manage Snapshot Lifecycle
+    """
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, volume_id, account=None,
+                                            domainid=None, projectid=None):
+        """Create Snapshot"""
+        cmd = createSnapshot.createSnapshotCmd()
+        cmd.volumeid = volume_id
+        if account:
+            cmd.account = account
+        if domainid:
+            cmd.domainid = domainid
+        if projectid:
+            cmd.projectid = projectid
+        return Snapshot(apiclient.createSnapshot(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Snapshot"""
+        cmd = deleteSnapshot.deleteSnapshotCmd()
+        cmd.id = self.id
+        apiclient.deleteSnapshot(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all snapshots matching criteria"""
+
+        cmd = listSnapshots.listSnapshotsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listSnapshots(cmd))
+
+
+class Template:
+    """Manage template life cycle"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, volumeid=None,
+               account=None, domainid=None, projectid=None):
+        """Create template from Volume"""
+        # Create template from Virtual machine and Volume ID
+        cmd = createTemplate.createTemplateCmd()
+        cmd.displaytext = services["displaytext"]
+        cmd.name = "-".join([services["name"], random_gen()])
+        if "ostypeid" in services:
+            cmd.ostypeid = services["ostypeid"]
+        elif "ostype" in services:
+            # Find OSTypeId from Os type
+            sub_cmd = listOsTypes.listOsTypesCmd()
+            sub_cmd.description = services["ostype"]
+            ostypes = apiclient.listOsTypes(sub_cmd)
+
+            if not isinstance(ostypes, list):
+                raise Exception(
+                    "Unable to find Ostype id with desc: %s" %
+                                                services["ostype"])
+            cmd.ostypeid = ostypes[0].id
+        else:
+            raise Exception(
+                    "Unable to find Ostype is required for creating template")
+
+        cmd.isfeatured = services["isfeatured"] if "isfeatured" in services else False
+        cmd.ispublic = services["ispublic"] if "ispublic" in services else False
+        cmd.isextractable = services["isextractable"] if "isextractable" in services else False
+        cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False
+
+        if volumeid:
+            cmd.volumeid = volumeid
+
+        if account:
+            cmd.account = account
+
+        if domainid:
+            cmd.domainid = domainid
+
+        if projectid:
+            cmd.projectid = projectid
+        return Template(apiclient.createTemplate(cmd).__dict__)
+
+    @classmethod
+    def register(cls, apiclient, services, zoneid=None,
+                                                account=None, domainid=None):
+        """Create template from URL"""
+
+        # Create template from Virtual machine and Volume ID
+        cmd = registerTemplate.registerTemplateCmd()
+        cmd.displaytext = services["displaytext"]
+        cmd.name = "-".join([services["name"], random_gen()])
+        cmd.format = services["format"]
+        cmd.hypervisor = apiclient.hypervisor
+
+        if "ostypeid" in services:
+            cmd.ostypeid = services["ostypeid"]
+        elif "ostype" in services:
+            # Find OSTypeId from Os type
+            sub_cmd = listOsTypes.listOsTypesCmd()
+            sub_cmd.description = services["ostype"]
+            ostypes = apiclient.listOsTypes(sub_cmd)
+
+            if not isinstance(ostypes, list):
+                raise Exception(
+                    "Unable to find Ostype id with desc: %s" %
+                                                services["ostype"])
+            cmd.ostypeid = ostypes[0].id
+        else:
+            raise Exception(
+                    "Unable to find Ostype is required for registering template")
+
+        cmd.url = services["url"]
+
+        if zoneid:
+            cmd.zoneid = zoneid
+        else:
+            cmd.zoneid = services["zoneid"]
+
+        cmd.isfeatured = services["isfeatured"] if "isfeatured" in services else False
+        cmd.ispublic = services["ispublic"] if "ispublic" in services else False
+        cmd.isextractable = services["isextractable"] if "isextractable" in services else False
+        cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False
+
+        if account:
+            cmd.account = account
+
+        if domainid:
+            cmd.domainid = domainid
+
+        # Register Template
+        template = apiclient.registerTemplate(cmd)
+
+        if isinstance(template, list):
+            return Template(template[0].__dict__)
+
+    @classmethod
+    def extract(cls, apiclient, id, mode, zoneid=None):
+        "Extract template "
+
+        cmd = extractTemplate.extractTemplateCmd()
+        cmd.id = id
+        cmd.mode = mode
+        cmd.zoneid = zoneid
+
+        return apiclient.extractTemplate(cmd)
+
+    @classmethod
+    def create_from_snapshot(cls, apiclient, snapshot, services,
+                                                        random_name=True):
+        """Create Template from snapshot"""
+        # Create template from Virtual machine and Snapshot ID
+        cmd = createTemplate.createTemplateCmd()
+        cmd.displaytext = services["displaytext"]
+        cmd.name = "-".join([
+                             services["name"],
+                             random_gen()
+                            ]) if random_name else services["name"]
+
+        if "ostypeid" in services:
+            cmd.ostypeid = services["ostypeid"]
+        elif "ostype" in services:
+            # Find OSTypeId from Os type
+            sub_cmd = listOsTypes.listOsTypesCmd()
+            sub_cmd.description = services["ostype"]
+            ostypes = apiclient.listOsTypes(sub_cmd)
+
+            if not isinstance(ostypes, list):
+                raise Exception(
+                    "Unable to find Ostype id with desc: %s" %
+                                                services["ostype"])
+            cmd.ostypeid = ostypes[0].id
+        else:
+            raise Exception(
+                    "Unable to find Ostype is required for creating template")
+
+        cmd.snapshotid = snapshot.id
+        return Template(apiclient.createTemplate(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Template"""
+
+        cmd = deleteTemplate.deleteTemplateCmd()
+        cmd.id = self.id
+        apiclient.deleteTemplate(cmd)
+
+    def download(self, apiclient, timeout=5, interval=60):
+        """Download Template"""
+        # Sleep to ensure template is in proper state before download
+        time.sleep(interval)
+
+        while True:
+            template_response = Template.list(
+                                    apiclient,
+                                    id=self.id,
+                                    zoneid=self.zoneid,
+                                    templatefilter='self'
+                                    )
+            if isinstance(template_response, list):
+
+                template = template_response[0]
+                # If template is ready,
+                # template.status = Download Complete
+                # Downloading - x% Downloaded
+                # Error - Any other string
+                if template.status == 'Download Complete':
+                    break
+
+                elif 'Downloaded' in template.status:
+                    time.sleep(interval)
+
+                elif 'Installing' not in template.status:
+                    raise Exception(
+                        "Error in downloading template: status - %s" %
+                                                            template.status)
+
+            elif timeout == 0:
+                break
+
+            else:
+                time.sleep(interval)
+                timeout = timeout - 1
+        return
+
+    def updatePermissions(self, apiclient, **kwargs):
+        """Updates the template permissions"""
+
+        cmd = updateTemplatePermissions.updateTemplatePermissionsCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.updateTemplatePermissions(cmd))
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all templates matching criteria"""
+
+        cmd = listTemplates.listTemplatesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listTemplates(cmd))
+
+
+class Iso:
+    """Manage ISO life cycle"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, account=None, domainid=None,
+                                                        projectid=None):
+        """Create an ISO"""
+        # Create ISO from URL
+        cmd = registerIso.registerIsoCmd()
+        cmd.displaytext = services["displaytext"]
+        cmd.name = services["name"]
+        if "ostypeid" in services:
+            cmd.ostypeid = services["ostypeid"]
+        elif "ostype" in services:
+            # Find OSTypeId from Os type
+            sub_cmd = listOsTypes.listOsTypesCmd()
+            sub_cmd.description = services["ostype"]
+            ostypes = apiclient.listOsTypes(sub_cmd)
+
+            if not isinstance(ostypes, list):
+                raise Exception(
+                    "Unable to find Ostype id with desc: %s" %
+                                                services["ostype"])
+            cmd.ostypeid = ostypes[0].id
+        else:
+            raise Exception(
+                    "Unable to find Ostype is required for creating ISO")
+
+        cmd.url = services["url"]
+        cmd.zoneid = services["zoneid"]
+
+        if "isextractable" in services:
+            cmd.isextractable = services["isextractable"]
+        if "isfeatured" in services:
+            cmd.isfeatured = services["isfeatured"]
+        if "ispublic" in services:
+            cmd.ispublic = services["ispublic"]
+
+        if account:
+            cmd.account = account
+        if domainid:
+            cmd.domainid = domainid
+        if projectid:
+            cmd.projectid = projectid
+        # Register ISO
+        iso = apiclient.registerIso(cmd)
+
+        if iso:
+            return Iso(iso[0].__dict__)
+
+    def delete(self, apiclient):
+        """Delete an ISO"""
+        cmd = deleteIso.deleteIsoCmd()
+        cmd.id = self.id
+        apiclient.deleteIso(cmd)
+        return
+
+    def download(self, apiclient, timeout=5, interval=60):
+        """Download an ISO"""
+        # Ensuring ISO is successfully downloaded
+        while True:
+            time.sleep(interval)
+
+            cmd = listIsos.listIsosCmd()
+            cmd.id = self.id
+            iso_response = apiclient.listIsos(cmd)
+
+            if isinstance(iso_response, list):
+                response = iso_response[0]
+                # Again initialize timeout to avoid listISO failure
+                timeout = 5
+                # Check whether download is in progress(for Ex:10% Downloaded)
+                # or ISO is 'Successfully Installed'
+                if response.status == 'Successfully Installed':
+                    return
+                elif 'Downloaded' not in response.status and \
+                    'Installing' not in response.status:
+                    raise Exception(
+                        "Error In Downloading ISO: ISO Status - %s" %
+                                                            response.status)
+
+            elif timeout == 0:
+                raise Exception("ISO download Timeout Exception")
+            else:
+                timeout = timeout - 1
+        return
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists all available ISO files."""
+
+        cmd = listIsos.listIsosCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listIsos(cmd))
+
+
+class PublicIPAddress:
+    """Manage Public IP Addresses"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, accountid=None, zoneid=None, domainid=None, services=None,
+               networkid=None, projectid=None, vpcid=None, isportable=False):
+        """Associate Public IP address"""
+        cmd = associateIpAddress.associateIpAddressCmd()
+
+        if accountid:
+            cmd.account = accountid
+        elif "account" in services:
+            cmd.account = services["account"]
+
+        if zoneid:
+            cmd.zoneid = zoneid
+        elif "zoneid" in services:
+            cmd.zoneid = services["zoneid"]
+
+        if domainid:
+            cmd.domainid = domainid
+        elif "domainid" in services:
+            cmd.domainid = services["domainid"]
+
+        if isportable:
+            cmd.isportable = isportable
+
+        if networkid:
+            cmd.networkid = networkid
+
+        if projectid:
+            cmd.projectid = projectid
+
+        if vpcid:
+            cmd.vpcid = vpcid
+        return PublicIPAddress(apiclient.associateIpAddress(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Dissociate Public IP address"""
+        cmd = disassociateIpAddress.disassociateIpAddressCmd()
+        cmd.id = self.ipaddress.id
+        apiclient.disassociateIpAddress(cmd)
+        return
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all Public IPs matching criteria"""
+
+        cmd = listPublicIpAddresses.listPublicIpAddressesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listPublicIpAddresses(cmd))
+
+
+class NATRule:
+    """Manage port forwarding rule"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, virtual_machine, services, ipaddressid=None,
+               projectid=None, openfirewall=False, networkid=None, vpcid=None):
+        """Create Port forwarding rule"""
+        cmd = createPortForwardingRule.createPortForwardingRuleCmd()
+
+        if ipaddressid:
+            cmd.ipaddressid = ipaddressid
+        elif "ipaddressid" in services:
+            cmd.ipaddressid = services["ipaddressid"]
+
+        cmd.privateport = services["privateport"]
+        cmd.publicport = services["publicport"]
+        if "privateendport" in services:
+            cmd.privateendport = services["privateendport"]
+        if "publicendport" in services:
+            cmd.publicendport = services["publicendport"]
+        cmd.protocol = services["protocol"]
+        cmd.virtualmachineid = virtual_machine.id
+
+        if projectid:
+            cmd.projectid = projectid
+
+        if openfirewall:
+            cmd.openfirewall = True
+
+        if networkid:
+            cmd.networkid = networkid
+
+        if vpcid:
+            cmd.vpcid = vpcid
+        return NATRule(apiclient.createPortForwardingRule(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete port forwarding"""
+        cmd = deletePortForwardingRule.deletePortForwardingRuleCmd()
+        cmd.id = self.id
+        apiclient.deletePortForwardingRule(cmd)
+        return
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all NAT rules matching criteria"""
+
+        cmd = listPortForwardingRules.listPortForwardingRulesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listPortForwardingRules(cmd))
+
+
+class StaticNATRule:
+    """Manage Static NAT rule"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, ipaddressid=None, networkid=None, vpcid=None):
+        """Creates static ip forwarding rule"""
+
+        cmd = createFirewallRule.createFirewallRuleCmd()
+        cmd.protocol = services["protocol"]
+        cmd.startport = services["startport"]
+
+        if "endport" in services:
+            cmd.endport = services["endport"]
+
+        if "cidrlist" in services:
+            cmd.cidrlist = services["cidrlist"]
+
+        if ipaddressid:
+            cmd.ipaddressid = ipaddressid
+        elif "ipaddressid" in services:
+            cmd.ipaddressid = services["ipaddressid"]
+
+        if networkid:
+            cmd.networkid = networkid
+
+        if vpcid:
+            cmd.vpcid = vpcid
+        return StaticNATRule(apiclient.createFirewallRule(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete IP forwarding rule"""
+        cmd = deleteIpForwardingRule.deleteIpForwardingRuleCmd()
+        cmd.id = self.id
+        apiclient.deleteIpForwardingRule(cmd)
+        return
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all IP forwarding rules matching criteria"""
+
+        cmd = listIpForwardingRules.listIpForwardingRulesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listIpForwardingRules(cmd))
+
+    @classmethod
+    def enable(cls, apiclient, ipaddressid, virtualmachineid, networkid=None):
+        """Enables Static NAT rule"""
+
+        cmd = enableStaticNat.enableStaticNatCmd()
+        cmd.ipaddressid = ipaddressid
+        cmd.virtualmachineid = virtualmachineid
+        if networkid:
+            cmd.networkid = networkid
+        apiclient.enableStaticNat(cmd)
+        return
+
+    @classmethod
+    def disable(cls, apiclient, ipaddressid, virtualmachineid):
+        """Disables Static NAT rule"""
+
+        cmd = disableStaticNat.disableStaticNatCmd()
+        cmd.ipaddressid = ipaddressid
+        apiclient.disableStaticNat(cmd)
+        return
+
+
+class EgressFireWallRule:
+    """Manage Egress Firewall rule"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, networkid, protocol, cidrlist=None,
+               startport=None, endport=None):
+        """Create Egress Firewall Rule"""
+        cmd = createEgressFirewallRule.createEgressFirewallRuleCmd()
+        cmd.networkid = networkid
+        cmd.protocol = protocol
+        if cidrlist:
+            cmd.cidrlist = cidrlist
+        if startport:
+            cmd.startport = startport
+        if endport:
+            cmd.endport = endport
+
+        return EgressFireWallRule(apiclient.createEgressFirewallRule(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Egress Firewall rule"""
+        cmd = deleteEgressFirewallRule.deleteEgressFirewallRuleCmd()
+        cmd.id = self.id
+        apiclient.deleteEgressFirewallRule(cmd)
+        return
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all Egress Firewall Rules matching criteria"""
+
+        cmd = listEgressFirewallRules.listEgressFirewallRulesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listEgressFirewallRules(cmd))
+
+
+
+class FireWallRule:
+    """Manage Firewall rule"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, ipaddressid, protocol, cidrlist=None,
+               startport=None, endport=None, projectid=None, vpcid=None):
+        """Create Firewall Rule"""
+        cmd = createFirewallRule.createFirewallRuleCmd()
+        cmd.ipaddressid = ipaddressid
+        cmd.protocol = protocol
+        if cidrlist:
+            cmd.cidrlist = cidrlist
+        if startport:
+            cmd.startport = startport
+        if endport:
+            cmd.endport = endport
+
+        if projectid:
+            cmd.projectid = projectid
+
+        if vpcid:
+            cmd.vpcid = vpcid
+
+        return FireWallRule(apiclient.createFirewallRule(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Firewall rule"""
+        cmd = deleteFirewallRule.deleteFirewallRuleCmd()
+        cmd.id = self.id
+        apiclient.deleteFirewallRule(cmd)
+        return
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all Firewall Rules matching criteria"""
+
+        cmd = listFirewallRules.listFirewallRulesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listFirewallRules(cmd))
+
+
+class ServiceOffering:
+    """Manage service offerings cycle"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, domainid=None, **kwargs):
+        """Create Service offering"""
+        cmd = createServiceOffering.createServiceOfferingCmd()
+        cmd.cpunumber = services["cpunumber"]
+        cmd.cpuspeed = services["cpuspeed"]
+        cmd.displaytext = services["displaytext"]
+        cmd.memory = services["memory"]
+        cmd.name = services["name"]
+        if "storagetype" in services:
+            cmd.storagetype = services["storagetype"]
+
+        if "systemvmtype" in services:
+            cmd.systemvmtype = services['systemvmtype']
+
+        if "issystem" in services:
+            cmd.issystem = services['issystem']
+
+        if "tags" in services:
+            cmd.tags = services["tags"]
+
+        if "deploymentplanner" in services:
+            cmd.deploymentplanner = services["deploymentplanner"]
+
+        # Service Offering private to that domain
+        if domainid:
+            cmd.domainid = domainid
+
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return ServiceOffering(apiclient.createServiceOffering(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Service offering"""
+        cmd = deleteServiceOffering.deleteServiceOfferingCmd()
+        cmd.id = self.id
+        apiclient.deleteServiceOffering(cmd)
+        return
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists all available service offerings."""
+
+        cmd = listServiceOfferings.listServiceOfferingsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listServiceOfferings(cmd))
+
+
+class DiskOffering:
+    """Manage disk offerings cycle"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, custom=False, domainid=None):
+        """Create Disk offering"""
+        cmd = createDiskOffering.createDiskOfferingCmd()
+        cmd.displaytext = services["displaytext"]
+        cmd.name = services["name"]
+        if custom:
+            cmd.customized = True
+        else:
+            cmd.disksize = services["disksize"]
+
+        if domainid:
+            cmd.domainid = domainid
+
+        if "storagetype" in services:
+            cmd.storagetype = services["storagetype"]
+
+        return DiskOffering(apiclient.createDiskOffering(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Disk offering"""
+        cmd = deleteDiskOffering.deleteDiskOfferingCmd()
+        cmd.id = self.id
+        apiclient.deleteDiskOffering(cmd)
+        return
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists all available disk offerings."""
+
+        cmd = listDiskOfferings.listDiskOfferingsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listDiskOfferings(cmd))
+
+
+class NetworkOffering:
+    """Manage network offerings cycle"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, **kwargs):
+        """Create network offering"""
+
+        cmd = createNetworkOffering.createNetworkOfferingCmd()
+        cmd.displaytext = "-".join([services["displaytext"], random_gen()])
+        cmd.name = "-".join([services["name"], random_gen()])
+        cmd.guestiptype = services["guestiptype"]
+        cmd.supportedservices = ''
+        if "supportedservices" in services:
+            cmd.supportedservices = services["supportedservices"]
+        cmd.traffictype = services["traffictype"]
+
+        if "useVpc" in services:
+            cmd.useVpc = services["useVpc"]
+        cmd.serviceproviderlist = []
+        if "serviceProviderList" in services:
+            for service, provider in services["serviceProviderList"].items():
+                cmd.serviceproviderlist.append({
+                                            'service': service,
+                                            'provider': provider
+                                           })
+        if "serviceCapabilityList" in services:
+            cmd.servicecapabilitylist = []
+            for service, capability in services["serviceCapabilityList"].items():
+                for ctype, value in capability.items():
+                    cmd.servicecapabilitylist.append({
+                                            'service': service,
+                                            'capabilitytype': ctype,
+                                            'capabilityvalue': value
+                                           })
+        if "specifyVlan" in services:
+            cmd.specifyVlan = services["specifyVlan"]
+        if "specifyIpRanges" in services:
+            cmd.specifyIpRanges = services["specifyIpRanges"]
+
+        if "egress_policy" in services:
+            cmd.egressdefaultpolicy = services["egress_policy"]
+
+        cmd.availability = 'Optional'
+
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+
+        return NetworkOffering(apiclient.createNetworkOffering(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete network offering"""
+        cmd = deleteNetworkOffering.deleteNetworkOfferingCmd()
+        cmd.id = self.id
+        apiclient.deleteNetworkOffering(cmd)
+        return
+
+    def update(self, apiclient, **kwargs):
+        """Lists all available network offerings."""
+
+        cmd = updateNetworkOffering.updateNetworkOfferingCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.updateNetworkOffering(cmd))
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists all available network offerings."""
+
+        cmd = listNetworkOfferings.listNetworkOfferingsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listNetworkOfferings(cmd))
+
+
+class SnapshotPolicy:
+    """Manage snapshot policies"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, volumeid, services):
+        """Create Snapshot policy"""
+        cmd = createSnapshotPolicy.createSnapshotPolicyCmd()
+        cmd.intervaltype = services["intervaltype"]
+        cmd.maxsnaps = services["maxsnaps"]
+        cmd.schedule = services["schedule"]
+        cmd.timezone = services["timezone"]
+        cmd.volumeid = volumeid
+        return SnapshotPolicy(apiclient.createSnapshotPolicy(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Snapshot policy"""
+        cmd = deleteSnapshotPolicies.deleteSnapshotPoliciesCmd()
+        cmd.id = self.id
+        apiclient.deleteSnapshotPolicies(cmd)
+        return
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists snapshot policies."""
+
+        cmd = listSnapshotPolicies.listSnapshotPoliciesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listSnapshotPolicies(cmd))
+
+
+class LoadBalancerRule:
+    """Manage Load Balancer rule"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, ipaddressid=None, accountid=None,
+               networkid=None, vpcid=None, projectid=None, domainid=None):
+        """Create Load balancing Rule"""
+
+        cmd = createLoadBalancerRule.createLoadBalancerRuleCmd()
+
+        if ipaddressid:
+            cmd.publicipid = ipaddressid
+        elif "ipaddressid" in services:
+            cmd.publicipid = services["ipaddressid"]
+
+        if accountid:
+            cmd.account = accountid
+        elif "account" in services:
+            cmd.account = services["account"]
+
+        if domainid:
+            cmd.domainid = domainid
+
+        if vpcid:
+            cmd.vpcid = vpcid
+        cmd.name = services["name"]
+        cmd.algorithm = services["alg"]
+        cmd.privateport = services["privateport"]
+        cmd.publicport = services["publicport"]
+
+        if "openfirewall" in services:
+            cmd.openfirewall = services["openfirewall"]
+
+        if projectid:
+            cmd.projectid = projectid
+
+        if networkid:
+            cmd.networkid = networkid
+        return LoadBalancerRule(apiclient.createLoadBalancerRule(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete load balancing rule"""
+        cmd = deleteLoadBalancerRule.deleteLoadBalancerRuleCmd()
+        cmd.id = self.id
+        apiclient.deleteLoadBalancerRule(cmd)
+        return
+
+    def assign(self, apiclient, vms):
+        """Assign virtual machines to load balancing rule"""
+        cmd = assignToLoadBalancerRule.assignToLoadBalancerRuleCmd()
+        cmd.id = self.id
+        cmd.virtualmachineids = [str(vm.id) for vm in vms]
+        apiclient.assignToLoadBalancerRule(cmd)
+        return
+
+    def remove(self, apiclient, vms):
+        """Remove virtual machines from load balancing rule"""
+        cmd = removeFromLoadBalancerRule.removeFromLoadBalancerRuleCmd()
+        cmd.id = self.id
+        cmd.virtualmachineids = [str(vm.id) for vm in vms]
+        apiclient.removeFromLoadBalancerRule(cmd)
+        return
+
+    def update(self, apiclient, algorithm=None, description=None, name=None, **kwargs):
+        """Updates the load balancing rule"""
+        cmd = updateLoadBalancerRule.updateLoadBalancerRuleCmd()
+        cmd.id = self.id
+        if algorithm:
+            cmd.algorithm = algorithm
+        if description:
+            cmd.description = description
+        if name:
+            cmd.name = name
+
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return apiclient.updateLoadBalancerRule(cmd)
+
+    def createSticky(self, apiclient, methodname, name, description=None, param=None):
+        """Creates a sticky policy for the LB rule"""
+
+        cmd = createLBStickinessPolicy.createLBStickinessPolicyCmd()
+        cmd.lbruleid = self.id
+        cmd.methodname = methodname
+        cmd.name = name
+        if description:
+            cmd.description = description
+        if param:
+            cmd.param = []
+            for name, value in param.items():
+                cmd.param.append({'name': name, 'value': value})
+        return apiclient.createLBStickinessPolicy(cmd)
+
+    def deleteSticky(self, apiclient, id):
+        """Deletes stickyness policy"""
+
+        cmd = deleteLBStickinessPolicy.deleteLBStickinessPolicyCmd()
+        cmd.id = id
+        return apiclient.deleteLBStickinessPolicy(cmd)
+
+    @classmethod
+    def listStickyPolicies(cls, apiclient, lbruleid, **kwargs):
+        """Lists stickiness policies for load balancing rule"""
+
+        cmd = listLBStickinessPolicies.listLBStickinessPoliciesCmd()
+        cmd.lbruleid = lbruleid
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return apiclient.listLBStickinessPolicies(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all Load balancing rules matching criteria"""
+
+        cmd = listLoadBalancerRules.listLoadBalancerRulesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listLoadBalancerRules(cmd))
+
+
+class Cluster:
+    """Manage Cluster life cycle"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, zoneid=None, podid=None):
+        """Create Cluster"""
+        cmd = addCluster.addClusterCmd()
+        cmd.clustertype = services["clustertype"]
+        cmd.hypervisor = apiclient.hypervisor
+
+        if zoneid:
+            cmd.zoneid = zoneid
+        else:
+            cmd.zoneid = services["zoneid"]
+
+        if podid:
+            cmd.podid = podid
+        else:
+            cmd.podid = services["podid"]
+
+        if "username" in services:
+            cmd.username = services["username"]
+        if "password" in services:
+            cmd.password = services["password"]
+        if "url" in services:
+            cmd.url = services["url"]
+        if "clustername" in services:
+            cmd.clustername = services["clustername"]
+
+        return Cluster(apiclient.addCluster(cmd)[0].__dict__)
+
+    def delete(self, apiclient):
+        """Delete Cluster"""
+        cmd = deleteCluster.deleteClusterCmd()
+        cmd.id = self.id
+        apiclient.deleteCluster(cmd)
+        return
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all Clusters matching criteria"""
+
+        cmd = listClusters.listClustersCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listClusters(cmd))
+
+
+class Host:
+    """Manage Host life cycle"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, cluster, services, zoneid=None, podid=None):
+        """Create Host in cluster"""
+
+        cmd = addHost.addHostCmd()
+        cmd.hypervisor = apiclient.hypervisor
+        cmd.url = services["url"]
+        cmd.clusterid = cluster.id
+
+        if zoneid:
+            cmd.zoneid = zoneid
+        else:
+            cmd.zoneid = services["zoneid"]
+
+        if podid:
+            cmd.podid = podid
+        else:
+            cmd.podid = services["podid"]
+
+        if "clustertype" in services:
+            cmd.clustertype = services["clustertype"]
+        if "username" in services:
+            cmd.username = services["username"]
+        if "password" in services:
+            cmd.password = services["password"]
+
+        # Add host
+        host = apiclient.addHost(cmd)
+
+        if isinstance(host, list):
+            return Host(host[0].__dict__)
+
+    def delete(self, apiclient):
+        """Delete Host"""
+        # Host must be in maintenance mode before deletion
+        cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
+        cmd.id = self.id
+        apiclient.prepareHostForMaintenance(cmd)
+        time.sleep(30)
+
+        cmd = deleteHost.deleteHostCmd()
+        cmd.id = self.id
+        apiclient.deleteHost(cmd)
+        return
+
+    def enableMaintenance(self, apiclient):
+        """enables maintenance mode Host"""
+
+        cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
+        cmd.id = self.id
+        return apiclient.prepareHostForMaintenance(cmd)
+
+    @classmethod
+    def enableMaintenance(cls, apiclient, id):
+        """enables maintenance mode Host"""
+
+        cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
+        cmd.id = id
+        return apiclient.prepareHostForMaintenance(cmd)
+
+    def cancelMaintenance(self, apiclient):
+        """Cancels maintenance mode Host"""
+
+        cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
+        cmd.id = self.id
+        return apiclient.cancelHostMaintenance(cmd)
+
+    @classmethod
+    def cancelMaintenance(cls, apiclient, id):
+        """Cancels maintenance mode Host"""
+
+        cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
+        cmd.id = id
+        return apiclient.cancelHostMaintenance(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all Hosts matching criteria"""
+
+        cmd = listHosts.listHostsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listHosts(cmd))
+
+    @classmethod
+    def listForMigration(cls, apiclient, **kwargs):
+        """List all Hosts for migration matching criteria"""
+
+        cmd = findHostsForMigration.findHostsForMigrationCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.findHostsForMigration(cmd))
+
+
+class StoragePool:
+    """Manage Storage pools (Primary Storage)"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, clusterid=None,
+                                        zoneid=None, podid=None):
+        """Create Storage pool (Primary Storage)"""
+
+        cmd = createStoragePool.createStoragePoolCmd()
+        cmd.name = services["name"]
+
+        if podid:
+            cmd.podid = podid
+        else:
+            cmd.podid = services["podid"]
+
+        cmd.url = services["url"]
+        if clusterid:
+            cmd.clusterid = clusterid
+        elif "clusterid" in services:
+            cmd.clusterid = services["clusterid"]
+
+        if zoneid:
+            cmd.zoneid = zoneid
+        else:
+            cmd.zoneid = services["zoneid"]
+
+        return StoragePool(apiclient.createStoragePool(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Storage pool (Primary Storage)"""
+
+        # Storage pool must be in maintenance mode before deletion
+        cmd = enableStorageMaintenance.enableStorageMaintenanceCmd()
+        cmd.id = self.id
+        apiclient.enableStorageMaintenance(cmd)
+        time.sleep(30)
+        cmd = deleteStoragePool.deleteStoragePoolCmd()
+        cmd.id = self.id
+        apiclient.deleteStoragePool(cmd)
+        return
+
+    def enableMaintenance(self, apiclient):
+        """enables maintenance mode Storage pool"""
+
+        cmd = enableStorageMaintenance.enableStorageMaintenanceCmd()
+        cmd.id = self.id
+        return apiclient.enableStorageMaintenance(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all storage pools matching criteria"""
+
+        cmd = listStoragePools.listStoragePoolsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listStoragePools(cmd))
+
+    @classmethod
+    def listForMigration(cls, apiclient, **kwargs):
+        """List all storage pools for migration matching criteria"""
+
+        cmd = findStoragePoolsForMigration.findStoragePoolsForMigrationCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.findStoragePoolsForMigration(cmd))
+
+class Network:
+    """Manage Network pools"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, accountid=None, domainid=None,
+               networkofferingid=None, projectid=None,
+               subdomainaccess=None, zoneid=None,
+               gateway=None, netmask=None, vpcid=None, aclid=None):
+        """Create Network for account"""
+        cmd = createNetwork.createNetworkCmd()
+        cmd.name = services["name"]
+        cmd.displaytext = services["displaytext"]
+
+        if networkofferingid:
+            cmd.networkofferingid = networkofferingid
+        elif "networkoffering" in services:
+            cmd.networkofferingid = services["networkoffering"]
+
+        if zoneid:
+            cmd.zoneid = zoneid
+        elif "zoneid" in services:
+            cmd.zoneid = services["zoneid"]
+
+        if subdomainaccess is not None:
+            cmd.subdomainaccess = subdomainaccess
+
+        if gateway:
+            cmd.gateway = gateway
+        elif "gateway" in services:
+            cmd.gateway = services["gateway"]
+        if netmask:
+            cmd.netmask = netmask
+        elif "netmask" in services:
+            cmd.netmask = services["netmask"]
+        if "startip" in services:
+            cmd.startip = services["startip"]
+        if "endip" in services:
+            cmd.endip = services["endip"]
+        if "vlan" in services:
+            cmd.vlan = services["vlan"]
+        if "acltype" in services:
+            cmd.acltype = services["acltype"]
+
+        if accountid:
+            cmd.account = accountid
+        if domainid:
+            cmd.domainid = domainid
+        if projectid:
+            cmd.projectid = projectid
+        if vpcid:
+            cmd.vpcid = vpcid
+        if aclid:
+            cmd.aclid = aclid
+        return Network(apiclient.createNetwork(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Account"""
+
+        cmd = deleteNetwork.deleteNetworkCmd()
+        cmd.id = self.id
+        apiclient.deleteNetwork(cmd)
+
+    def update(self, apiclient, **kwargs):
+        """Updates network with parameters passed"""
+
+        cmd = updateNetwork.updateNetworkCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.updateNetwork(cmd))
+
+    def restart(self, apiclient, cleanup=None):
+        """Restarts the network"""
+
+        cmd = restartNetwork.restartNetworkCmd()
+        cmd.id = self.id
+        if cleanup:
+            cmd.cleanup = cleanup
+        return(apiclient.restartNetwork(cmd))
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all Networks matching criteria"""
+
+        cmd = listNetworks.listNetworksCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listNetworks(cmd))
+
+
+class NetworkACL:
+    """Manage Network ACL lifecycle"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, networkid=None, protocol=None,
+               number=None, aclid=None, action='Allow', traffictype=None, cidrlist=[]):
+        """Create network ACL rules(Ingress/Egress)"""
+
+        cmd = createNetworkACL.createNetworkACLCmd()
+        if "networkid" in services:
+            cmd.networkid = services["networkid"]
+        elif networkid:
+            cmd.networkid = networkid
+
+        if "protocol" in services:
+            cmd.protocol = services["protocol"]
+            if services["protocol"] == 'ICMP':
+                cmd.icmptype = -1
+                cmd.icmpcode = -1
+        elif protocol:
+            cmd.protocol = protocol
+
+        if "startport" in services:
+            cmd.startport = services["startport"]
+        if "endport" in services:
+            cmd.endport = services["endport"]
+
+        if "cidrlist" in services:
+            cmd.cidrlist = services["cidrlist"]
+        elif cidrlist:
+            cmd.cidrlist = cidrlist
+
+        if "traffictype" in services:
+            cmd.traffictype = services["traffictype"]
+        elif traffictype:
+            cmd.traffictype = traffictype
+
+        if "action" in services:
+            cmd.action = services["action"]
+        elif action:
+            cmd.action = action
+
+        if "number" in services:
+            cmd.number = services["number"]
+        elif number:
+            cmd.number = number
+
+        if "aclid" in services:
+            cmd.aclid = services["aclid"]
+        elif aclid:
+            cmd.aclid = aclid
+
+        # Defaulted to Ingress
+        return NetworkACL(apiclient.createNetworkACL(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete network acl"""
+
+        cmd = deleteNetworkACL.deleteNetworkACLCmd()
+        cmd.id = self.id
+        return apiclient.deleteNetworkACL(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List Network ACLs"""
+
+        cmd = listNetworkACLs.listNetworkACLsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listNetworkACLs(cmd))
+
+
+class NetworkACLList:
+    """Manage Network ACL lists lifecycle"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, name=None, description=None, vpcid=None):
+        """Create network ACL container list"""
+
+        cmd = createNetworkACLList.createNetworkACLListCmd()
+        if "name" in services:
+            cmd.name = services["name"]
+        elif name:
+            cmd.name = name
+
+        if "description" in services:
+            cmd.description = services["description"]
+        elif description:
+            cmd.description = description
+
+        if "vpcid" in services:
+            cmd.vpcid = services["vpcid"]
+        elif vpcid:
+            cmd.vpcid = vpcid
+
+        return NetworkACLList(apiclient.createNetworkACLList(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete network acl list"""
+
+        cmd = deleteNetworkACLList.deleteNetworkACLListCmd()
+        cmd.id = self.id
+        return apiclient.deleteNetworkACLList(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List Network ACL lists"""
+
+        cmd = listNetworkACLLists.listNetworkACLListsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listNetworkACLLists(cmd))
+
+
+class Vpn:
+    """Manage VPN life cycle"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, publicipid, account=None, domainid=None,
+                        projectid=None, networkid=None, vpcid=None):
+        """Create VPN for Public IP address"""
+        cmd = createRemoteAccessVpn.createRemoteAccessVpnCmd()
+        cmd.publicipid = publicipid
+        if account:
+            cmd.account = account
+        if domainid:
+            cmd.domainid = domainid
+        if projectid:
+            cmd.projectid = projectid
+        if networkid:
+            cmd.networkid = networkid
+        if vpcid:
+            cmd.vpcid = vpcid
+        return Vpn(apiclient.createRemoteAccessVpn(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete remote VPN access"""
+
+        cmd = deleteRemoteAccessVpn.deleteRemoteAccessVpnCmd()
+        cmd.publicipid = self.publicipid
+        apiclient.deleteRemoteAccessVpn(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all VPN matching criteria"""
+
+        cmd = listRemoteAccessVpns.listRemoteAccessVpnsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listRemoteAccessVpns(cmd))
+
+
+class VpnUser:
+    """Manage VPN user"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, username, password, account=None, domainid=None,
+               projectid=None, rand_name=True):
+        """Create VPN user"""
+        cmd = addVpnUser.addVpnUserCmd()
+        cmd.username = "-".join([username,
+                                 random_gen()]) if rand_name else username
+        cmd.password = password
+
+        if account:
+            cmd.account = account
+        if domainid:
+            cmd.domainid = domainid
+        if projectid:
+            cmd.projectid = projectid
+        return VpnUser(apiclient.addVpnUser(cmd).__dict__)
+
+    def delete(self, apiclient, projectid=None):
+        """Remove VPN user"""
+
+        cmd = removeVpnUser.removeVpnUserCmd()
+        cmd.username = self.username
+        if projectid:
+            cmd.projectid = projectid
+        else:
+            cmd.account = self.account
+            cmd.domainid = self.domainid
+        apiclient.removeVpnUser(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all VPN Users matching criteria"""
+
+        cmd = listVpnUsers.listVpnUsersCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listVpnUsers(cmd))
+
+
+class Zone:
+    """Manage Zone"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, domainid=None):
+        """Create zone"""
+        cmd = createZone.createZoneCmd()
+        cmd.dns1 = services["dns1"]
+        cmd.internaldns1 = services["internaldns1"]
+        cmd.name = services["name"]
+        cmd.networktype = services["networktype"]
+
+        if "dns2" in services:
+            cmd.dns2 = services["dns2"]
+        if "internaldns2" in services:
+            cmd.internaldns2 = services["internaldns2"]
+        if domainid:
+            cmd.domainid = domainid
+
+        return Zone(apiclient.createZone(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Zone"""
+
+        cmd = deleteZone.deleteZoneCmd()
+        cmd.id = self.id
+        apiclient.deleteZone(cmd)
+
+    def update(self, apiclient, **kwargs):
+        """Update the zone"""
+
+        cmd = updateZone.updateZoneCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return apiclient.updateZone(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """List all Zones matching criteria"""
+
+        cmd = listZones.listZonesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listZones(cmd))
+
+
+class Pod:
+    """Manage Pod"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services):
+        """Create Pod"""
+        cmd = createPod.createPodCmd()
+        cmd.gateway = services["gateway"]
+        cmd.netmask = services["netmask"]
+        cmd.name = services["name"]
+        cmd.startip = services["startip"]
+        cmd.endip = services["endip"]
+        cmd.zoneid = services["zoneid"]
+
+        return Pod(apiclient.createPod(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Pod"""
+
+        cmd = deletePod.deletePodCmd()
+        cmd.id = self.id
+        apiclient.deletePod(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        "Returns a default pod for specified zone"
+
+        cmd = listPods.listPodsCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return apiclient.listPods(cmd)
+
+
+class PublicIpRange:
+    """Manage VlanIpRange"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services):
+        """Create VlanIpRange"""
+
+        cmd = createVlanIpRange.createVlanIpRangeCmd()
+        cmd.gateway = services["gateway"]
+        cmd.netmask = services["netmask"]
+        cmd.forvirtualnetwork = services["forvirtualnetwork"]
+        cmd.startip = services["startip"]
+        cmd.endip = services["endip"]
+        cmd.zoneid = services["zoneid"]
+        cmd.podid = services["podid"]
+        cmd.vlan = services["vlan"]
+
+        return PublicIpRange(apiclient.createVlanIpRange(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete VlanIpRange"""
+
+        cmd = deleteVlanIpRange.deleteVlanIpRangeCmd()
+        cmd.id = self.vlan.id
+        apiclient.deleteVlanIpRange(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists all VLAN IP ranges."""
+
+        cmd = listVlanIpRanges.listVlanIpRangesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listVlanIpRanges(cmd))
+
+    @classmethod
+    def dedicate(cls, apiclient, id, account=None, domainid=None, projectid=None):
+        """Dedicate VLAN IP range"""
+
+        cmd = dedicatePublicIpRange.dedicatePublicIpRangeCmd()
+        cmd.id = id
+        cmd.account = account
+        cmd.domainid = domainid
+        cmd.projectid = projectid
+        return PublicIpRange(apiclient.dedicatePublicIpRange(cmd).__dict__)
+
+    def release(self, apiclient):
+        """Release VLAN IP range"""
+
+        cmd = releasePublicIpRange.releasePublicIpRangeCmd()
+        cmd.id = self.vlan.id
+        return apiclient.releasePublicIpRange(cmd)
+
+
+class PortablePublicIpRange:
+    """Manage portable public Ip Range"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services):
+        """Create portable public Ip Range"""
+
+        cmd = createPortableIpRange.createPortableIpRangeCmd()
+        cmd.gateway = services["gateway"]
+        cmd.netmask = services["netmask"]
+        cmd.startip = services["startip"]
+        cmd.endip = services["endip"]
+        cmd.regionid = services["regionid"]
+
+        if "vlan" in services:
+            cmd.vlan = services["vlan"]
+
+        return PortablePublicIpRange(apiclient.createPortableIpRange(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete portable IpRange"""
+
+        cmd = deletePortableIpRange.deletePortableIpRangeCmd()
+        cmd.id = self.id
+        apiclient.deletePortableIpRange(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists all portable public IP ranges."""
+
+        cmd = listPortableIpRanges.listPortableIpRangesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listPortableIpRanges(cmd))
+
+class SecondaryStagingStore:
+    """Manage Staging Store"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, url, provider, services=None):
+        """Create Staging Storage"""
+        cmd = createSecondaryStagingStore.createSecondaryStagingStoreCmd()
+        cmd.url = url
+        cmd.provider = provider
+        if services:
+            if "zoneid" in services:
+                cmd.zoneid = services["zoneid"]
+            if "details" in services:
+                cmd.details = services["details"]
+            if "scope" in services:
+                cmd.scope = services["scope"]
+
+        return SecondaryStagingStore(apiclient.createSecondaryStagingStore(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Staging Storage"""
+        cmd = deleteSecondaryStagingStore.deleteSecondaryStagingStoreCmd()
+        cmd.id = self.id
+        apiclient.deleteSecondaryStagingStore(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        cmd = listSecondaryStagingStores.listSecondaryStagingStoresCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listSecondaryStagingStores(cmd))
+
+
+class ImageStore:
+    """Manage image stores"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, url, provider, services=None):
+        """Add Image Store"""
+        cmd = addImageStore.addImageStoreCmd()
+        cmd.url = url
+        cmd.provider = provider
+        if services:
+            if "zoneid" in services:
+                cmd.zoneid = services["zoneid"]
+            if "details" in services:
+                cmd.details = services["details"]
+            if "scope" in services:
+                cmd.scope = services["scope"]
+
+        return ImageStore(apiclient.addImageStore(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Image Store"""
+        cmd = deleteImageStore.deleteImageStoreCmd()
+        cmd.id = self.id
+        apiclient.deleteImageStore(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        cmd = listImageStores.listImageStoresCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return(apiclient.listImageStores(cmd))
+
+
+class PhysicalNetwork:
+    """Manage physical network storage"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, zoneid, domainid=None):
+        """Create physical network"""
+        cmd = createPhysicalNetwork.createPhysicalNetworkCmd()
+
+        cmd.name = services["name"]
+        cmd.zoneid = zoneid
+        if domainid:
+            cmd.domainid = domainid
+        return PhysicalNetwork(apiclient.createPhysicalNetwork(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Physical Network"""
+
+        cmd = deletePhysicalNetwork.deletePhysicalNetworkCmd()
+        cmd.id = self.id
+        apiclient.deletePhysicalNetwork(cmd)
+
+    def update(self, apiclient, **kwargs):
+        """Update Physical network state"""
+
+        cmd = updatePhysicalNetwork.updatePhysicalNetworkCmd()
+        cmd.id = self.id
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return apiclient.updatePhysicalNetwork(cmd)
+
+    def addTrafficType(self, apiclient, type):
+        """Add Traffic type to Physical network"""
+
+        cmd = addTrafficType.addTrafficTypeCmd()
+        cmd.physicalnetworkid = self.id
+        cmd.traffictype = type
+        return apiclient.addTrafficType(cmd)
+
+    @classmethod
+    def dedicate(cls, apiclient, vlanrange, physicalnetworkid, account=None, domainid=None, projectid=None):
+        """Dedicate guest vlan range"""
+
+        cmd = dedicateGuestVlanRange.dedicateGuestVlanRangeCmd()
+        cmd.vlanrange = vlanrange
+        cmd.physicalnetworkid = physicalnetworkid
+        cmd.account = account
+        cmd.domainid = domainid
+        cmd.projectid = projectid
+        return PhysicalNetwork(apiclient.dedicateGuestVlanRange(cmd).__dict__)
+
+    def release(self, apiclient):
+        """Release guest vlan range"""
+
+        cmd = releaseDedicatedGuestVlanRange.releaseDedicatedGuestVlanRangeCmd()
+        cmd.id = self.id
+        return apiclient.releaseDedicatedGuestVlanRange(cmd)
+
+    @classmethod
+    def listDedicated(cls, apiclient, **kwargs):
+        """Lists all dedicated guest vlan ranges"""
+
+        cmd = listDedicatedGuestVlanRanges.listDedicatedGuestVlanRangesCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return apiclient.listDedicatedGuestVlanRanges(cmd)
+
+    @classmethod
+    def list(cls, apiclient, **kwargs):
+        """Lists all physical networks"""
+
+        cmd = listPhysicalNetworks.listPhysicalNetworksCmd()
+        [setattr(cmd, k, v) for k, v in kwargs.items()]
+        return map(lambda pn : PhysicalNetwork(pn.__dict__), apiclient.listPhysicalNetworks(cmd))
+
+
+class SecurityGroup:
+    """Manage Security Groups"""
+
+    def __init__(self, items):
+        self.__dict__.update(items)
+
+    @classmethod
+    def create(cls, apiclient, services, account=None, domainid=None,
+               description=None, projectid=None):
+        """Create security group"""
+        cmd = createSecurityGroup.createSecurityGroupCmd()
+
+        cmd.name = services["name"]
+        if account:
+            cmd.account = account
+        if domainid:
+            cmd.domainid = domainid
+        if description:
+            cmd.description = description
+        if projectid:
+            cmd.projectid = projectid
+
+        return SecurityGroup(apiclient.createSecurityGroup(cmd).__dict__)
+
+    def delete(self, apiclient):
+        """Delete Security Group"""
+
+        cmd = deleteSecurityGroup.deleteSecurityGroupCmd()
+        cmd.id = self.id
+        apiclient.deleteSecurityGroup(cmd)
+
+    def authorize(self, apiclient, services,
+                  account=None, domainid=None, projectid=None):
+        """Authorize Ingress Rule"""
+
+        cmd = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd()
+
+        if domainid:
+            cmd.domainid = domainid
+        if account:
+            cmd.account = account
+
+        if projectid:
+            cmd.projectid = projectid
+        cmd.securitygroupid = self.id
+        cmd.protocol = services["protocol"]
+
+        if services["protocol"] == 'ICMP':
+            cmd.icmptype = -1
+            cmd.icmpcode = -1
+        else:
+            cmd.startport = services["startport"]
+            cmd.endport = services["endport"]
+
+        cmd.cidrlist = services["cidrlist"]
+        return (apiclient.authorizeSecurityGroupIngress(cmd).__dict__)
+
+    def revoke(self, apiclient, id):
+        """Revoke ingress rule"""
+
+        cmd = revokeSecurityGroupIngress.revokeSecurityGroupIngressCmd()
+        cmd.id = id
+        return apiclient.revokeSecurityGroupIngress(cmd)
+
+    def authorizeEgress(self, apiclient, services, account=None, domainid=None,
+                        projectid=None, user_secgrp_list={}):
+        """Authorize Egress Rule"""
+
+        cmd = authorizeSecurityGroupEgress.authorizeSecurityGroupEgressCmd()
+
+        if domainid:
+            cmd.domainid = domainid
+        if account:
+            cmd.account = account
+
+        if projectid:
+            cmd.projectid = projectid
+        cmd.securitygroupid = self.id
+        cmd.protocol = services["protocol"]
+
+        if services["protocol"] == 'ICMP':
+            cmd.icmptype = -1
+            cmd.icmpcode = -1
+        else:
+            cmd.startport = services["startport"]
+            cmd.endport = services["endport"]
+
+        cmd.cidrlist = services["cidrlist"]
+
+        cmd.usersecuritygrouplist = []
+        for account, group in user_secgrp_list.items():
+            cmd.usersecuritygrouplist.append({
+                                            'account': account,
+                                            'group

<TRUNCATED>

[02/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: cloudConnection is CloudConnection

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/215ac11e
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/215ac11e
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/215ac11e

Branch: refs/heads/marvin-refactor
Commit: 215ac11e51636103968d301e0d3c64692ff196aa
Parents: 291a35d
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Tue Sep 3 16:54:39 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:04 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/cloudstackTestClient.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/215ac11e/tools/marvin/marvin/cloudstackTestClient.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cloudstackTestClient.py b/tools/marvin/marvin/cloudstackTestClient.py
index 36f7f8d..c49ee72 100644
--- a/tools/marvin/marvin/cloudstackTestClient.py
+++ b/tools/marvin/marvin/cloudstackTestClient.py
@@ -29,7 +29,7 @@ class cloudstackTestClient(object):
                  apiKey=None, securityKey=None, asyncTimeout=3600,
                  defaultWorkerThreads=10, logging=None):
         self.connection = \
-            cloudstackConnection.cloudConnection(mgtSvr, port, user, passwd,
+            cloudstackConnection.CloudConnection(mgtSvr, port, user, passwd,
                                                  apiKey, securityKey,
                                                  asyncTimeout, logging)
         self.apiClient =\


[06/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: some project cleanup.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/a81600b9
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/a81600b9
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/a81600b9

Branch: refs/heads/marvin-refactor
Commit: a81600b9e9ff2d9183243135a35040d235ec4fb3
Parents: 15d4d3f
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Tue Sep 3 22:17:51 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:14 2013 +0530

----------------------------------------------------------------------
 tools/marvin/CHANGES.txt                        | 18 ----------------
 tools/marvin/DISCLAIMER.txt                     |  7 -------
 tools/marvin/docs/errata.md                     | 22 ++++++++++++++++++++
 tools/marvin/marvin/docs/__init__.py            | 16 --------------
 tools/marvin/marvin/docs/errata.md              | 22 --------------------
 tools/marvin/marvin/factory/data/account.py     |  2 +-
 tools/marvin/marvin/factory/data/cluster.py     |  2 +-
 .../marvin/marvin/factory/data/diskoffering.py  |  2 +-
 .../marvin/marvin/factory/data/firewallrule.py  |  2 +-
 tools/marvin/marvin/factory/data/host.py        |  2 +-
 .../marvin/factory/data/networkoffering.py      |  2 +-
 .../marvin/factory/data/serviceoffering.py      |  2 +-
 tools/marvin/marvin/factory/data/template.py    |  2 +-
 tools/marvin/marvin/factory/data/user.py        |  2 +-
 tools/marvin/marvin/factory/data/vm.py          |  2 +-
 tools/marvin/marvin/factory/data/zone.py        |  2 +-
 tools/marvin/marvin/test/test_factories.py      |  2 +-
 tools/marvin/setup.py                           |  5 +++--
 18 files changed, 37 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/CHANGES.txt
----------------------------------------------------------------------
diff --git a/tools/marvin/CHANGES.txt b/tools/marvin/CHANGES.txt
deleted file mode 100644
index 262c884..0000000
--- a/tools/marvin/CHANGES.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-v0.1.0 Tuesday, April 10 2012 -- Packaging Marvin

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/DISCLAIMER.txt
----------------------------------------------------------------------
diff --git a/tools/marvin/DISCLAIMER.txt b/tools/marvin/DISCLAIMER.txt
deleted file mode 100644
index fa1e926..0000000
--- a/tools/marvin/DISCLAIMER.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Apache CloudStack is an effort undergoing incubation at The Apache Software Foundation (ASF), 
-sponsored by the Apache Incubator. Incubation is required of all newly accepted 
-projects until a further review indicates that the infrastructure, communications, and 
-decision making process have stabilized in a manner consistent with other successful ASF 
-projects. While incubation status is not necessarily a reflection of the completeness or 
-stability of the code, it does indicate that the project has yet to be fully endorsed by 
-the ASF.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/docs/errata.md
----------------------------------------------------------------------
diff --git a/tools/marvin/docs/errata.md b/tools/marvin/docs/errata.md
new file mode 100644
index 0000000..f626069
--- /dev/null
+++ b/tools/marvin/docs/errata.md
@@ -0,0 +1,22 @@
+## Idea Stack
+
+### Bugs
+
+- **marvin.sync and xml compilation produce different versions of cloudstackAPI**
+- marvin build now requires inflect which will cause -Pdeveloper profile to break for the first time
+- Entities should include @docstring for optional arguments in their actions() methods. **kwargs is confusing
+- Dissociate the grammar list to make it extensible via a properties file
+- Handle APIs that need parameters but dont have a required args list because multiple sets of args form a required list
+	- eg: disableAccount (either provide id (account) or accoutname and domainid)
+- XML precache required for factory and base generation [CLOUDSTACK-4589](https://issues.apache.org/jira//browse/CLOUDSTACK-4589)
+- Remove marvin dependency with apidoc build. Provide precache json [CLOUDSTACK-4589](https://issues.apache.org/jira//browse/CLOUDSTACK-4589)
+- Better sync functionality
+- Bump up version to 0.2.0
+- Improved cleanup support
+
+### Features
+- Export deployment to JSON [CLOUDSTACK-4590](https://issues.apache.org/jira//browse/CLOUDSTACK-4590)
+- nose2 and unittest2 support [CLOUDSTACK-4591](https://issues.apache.org/jira//browse/CLOUDSTACK-4591)
+- Use distutils
+- Python pip repository for cloudstack-marvin
+- DSL for marvin using Behave [CLOUDSTACK-1952](https://issues.apache.org/jira/browse/CLOUDSTACK-1952)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/marvin/docs/__init__.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/docs/__init__.py b/tools/marvin/marvin/docs/__init__.py
deleted file mode 100644
index d216be4..0000000
--- a/tools/marvin/marvin/docs/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/marvin/docs/errata.md
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/docs/errata.md b/tools/marvin/marvin/docs/errata.md
deleted file mode 100644
index f626069..0000000
--- a/tools/marvin/marvin/docs/errata.md
+++ /dev/null
@@ -1,22 +0,0 @@
-## Idea Stack
-
-### Bugs
-
-- **marvin.sync and xml compilation produce different versions of cloudstackAPI**
-- marvin build now requires inflect which will cause -Pdeveloper profile to break for the first time
-- Entities should include @docstring for optional arguments in their actions() methods. **kwargs is confusing
-- Dissociate the grammar list to make it extensible via a properties file
-- Handle APIs that need parameters but dont have a required args list because multiple sets of args form a required list
-	- eg: disableAccount (either provide id (account) or accoutname and domainid)
-- XML precache required for factory and base generation [CLOUDSTACK-4589](https://issues.apache.org/jira//browse/CLOUDSTACK-4589)
-- Remove marvin dependency with apidoc build. Provide precache json [CLOUDSTACK-4589](https://issues.apache.org/jira//browse/CLOUDSTACK-4589)
-- Better sync functionality
-- Bump up version to 0.2.0
-- Improved cleanup support
-
-### Features
-- Export deployment to JSON [CLOUDSTACK-4590](https://issues.apache.org/jira//browse/CLOUDSTACK-4590)
-- nose2 and unittest2 support [CLOUDSTACK-4591](https://issues.apache.org/jira//browse/CLOUDSTACK-4591)
-- Use distutils
-- Python pip repository for cloudstack-marvin
-- DSL for marvin using Behave [CLOUDSTACK-1952](https://issues.apache.org/jira/browse/CLOUDSTACK-1952)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/marvin/factory/data/account.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/account.py b/tools/marvin/marvin/factory/data/account.py
index 1041cfe..b0fcd7b 100644
--- a/tools/marvin/marvin/factory/data/account.py
+++ b/tools/marvin/marvin/factory/data/account.py
@@ -16,7 +16,7 @@
 # under the License.
 
 import factory
-from marvin.factory.AccountFactory import AccountFactory
+from marvin.factory.account import AccountFactory
 from marvin.utils import random_gen
 
 class UserAccountFactory(AccountFactory):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/marvin/factory/data/cluster.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/cluster.py b/tools/marvin/marvin/factory/data/cluster.py
index f4641cf..321252b 100644
--- a/tools/marvin/marvin/factory/data/cluster.py
+++ b/tools/marvin/marvin/factory/data/cluster.py
@@ -17,7 +17,7 @@
 
 import factory
 from marvin.utils import random_gen
-from marvin.factory.ClusterFactory import ClusterFactory
+from marvin.factory.cluster import ClusterFactory
 
 class XenClusterFactory(ClusterFactory):
     clustername = factory.Sequence(lambda n: "xencluster" + random_gen())

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/marvin/factory/data/diskoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/diskoffering.py b/tools/marvin/marvin/factory/data/diskoffering.py
index 88ae7cb..ee58c27 100644
--- a/tools/marvin/marvin/factory/data/diskoffering.py
+++ b/tools/marvin/marvin/factory/data/diskoffering.py
@@ -16,7 +16,7 @@
 # under the License.
 
 import factory
-from marvin.factory.DiskOfferingFactory import DiskOfferingFactory
+from marvin.factory.diskoffering import DiskOfferingFactory
 from marvin.utils import random_gen
 
 class SharedDiskOfferingFactory(DiskOfferingFactory):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/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 1707347..da6284a 100644
--- a/tools/marvin/marvin/factory/data/firewallrule.py
+++ b/tools/marvin/marvin/factory/data/firewallrule.py
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-from marvin.factory.FirewallRuleFactory import FirewallRuleFactory
+from marvin.factory.firewallrule import FirewallRuleFactory
 
 class SshFirewallRuleFactory(FirewallRuleFactory):
     protocol = 'tcp'

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/marvin/factory/data/host.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/host.py b/tools/marvin/marvin/factory/data/host.py
index c8b4ab7..726ceb7 100644
--- a/tools/marvin/marvin/factory/data/host.py
+++ b/tools/marvin/marvin/factory/data/host.py
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-from marvin.factory.HostFactory import HostFactory
+from marvin.factory.host import HostFactory
 
 class XenserverHostFactory(HostFactory):
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/marvin/factory/data/networkoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/networkoffering.py b/tools/marvin/marvin/factory/data/networkoffering.py
index 8d80631..4e54c4b 100644
--- a/tools/marvin/marvin/factory/data/networkoffering.py
+++ b/tools/marvin/marvin/factory/data/networkoffering.py
@@ -16,7 +16,7 @@
 # under the License.
 
 import factory
-from marvin.factory.NetworkOfferingFactory import NetworkOfferingFactory
+from marvin.factory.networkoffering import NetworkOfferingFactory
 from marvin.utils import random_gen
 
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/marvin/factory/data/serviceoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/serviceoffering.py b/tools/marvin/marvin/factory/data/serviceoffering.py
index a56d4e5..b3a7639 100644
--- a/tools/marvin/marvin/factory/data/serviceoffering.py
+++ b/tools/marvin/marvin/factory/data/serviceoffering.py
@@ -16,7 +16,7 @@
 # under the License.
 
 import factory
-from marvin.factory.ServiceOfferingFactory import ServiceOfferingFactory
+from marvin.factory.serviceoffering import ServiceOfferingFactory
 from marvin.utils import random_gen
 
 class SmallServiceOfferingFactory(ServiceOfferingFactory):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/marvin/factory/data/template.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/template.py b/tools/marvin/marvin/factory/data/template.py
index 033835b..4c576fb 100644
--- a/tools/marvin/marvin/factory/data/template.py
+++ b/tools/marvin/marvin/factory/data/template.py
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-from marvin.factory.TemplateFactory import TemplateFactory
+from marvin.factory.template import TemplateFactory
 
 class DefaultBuiltInTemplateFactory(TemplateFactory):
     ostype = 'CentOS 5.3 (64-bit)'

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/marvin/factory/data/user.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/user.py b/tools/marvin/marvin/factory/data/user.py
index ee84644..d3bde0d 100644
--- a/tools/marvin/marvin/factory/data/user.py
+++ b/tools/marvin/marvin/factory/data/user.py
@@ -16,7 +16,7 @@
 # under the License.
 
 import factory
-from marvin.factory.UserFactory import UserFactory
+from marvin.factory.user import UserFactory
 from marvin.factory.data.account import UserAccountFactory
 from marvin.utils import random_gen
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/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 66f15a3..a938603 100644
--- a/tools/marvin/marvin/factory/data/vm.py
+++ b/tools/marvin/marvin/factory/data/vm.py
@@ -16,7 +16,7 @@
 # under the License.
 
 import factory
-from marvin.factory.VirtualMachineFactory import VirtualMachineFactory
+from marvin.factory.virtualmachine import VirtualMachineFactory
 from marvin.utils import random_gen
 
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/marvin/factory/data/zone.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/zone.py b/tools/marvin/marvin/factory/data/zone.py
index f4a278a..2936c0b 100644
--- a/tools/marvin/marvin/factory/data/zone.py
+++ b/tools/marvin/marvin/factory/data/zone.py
@@ -16,7 +16,7 @@
 # under the License.
 
 import factory
-from marvin.factory.ZoneFactory import ZoneFactory
+from marvin.factory.zone import ZoneFactory
 from marvin.utils import random_gen
 
 class AdvancedZoneFactory(ZoneFactory):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/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 5ce8c13..e415231 100644
--- a/tools/marvin/marvin/test/test_factories.py
+++ b/tools/marvin/marvin/test/test_factories.py
@@ -26,7 +26,7 @@ from marvin.factory.data.template import *
 from marvin.factory.data.user import *
 from marvin.factory.data.networkoffering import *
 
-from marvin.factory.VirtualMachineFactory import *
+from marvin.factory.virtualmachine import *
 
 from marvin.entity.serviceoffering import ServiceOffering
 from marvin.entity.zone import Zone

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a81600b9/tools/marvin/setup.py
----------------------------------------------------------------------
diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py
index b499671..cbaa157 100644
--- a/tools/marvin/setup.py
+++ b/tools/marvin/setup.py
@@ -43,14 +43,15 @@ setup(name="Marvin",
     long_description="Marvin is the Apache CloudStack python client written around the unittest framework",
     platforms=("Any",),
     packages=["marvin", "marvin.cloudstackAPI", "marvin.entity", "marvin.factory", "marvin.factory.data",
-              "marvin.docs", "marvin.generate", "marvin.legacy", "marvin.sandbox",
-              "marvin.sandbox.advanced", "marvin.sandbox.advancedsg", "marvin.sandbox.basic"],
+              "marvin.generate", "marvin.legacy", "marvin.sandbox", "marvin.sandbox.advanced",
+              "marvin.sandbox.advancedsg", "marvin.sandbox.basic"],
     license="LICENSE.txt",
     install_requires=[
         "mysql-connector-python",
         "requests",
         "paramiko",
         "nose",
+        "simplejson",
         "factory_boy",
         "should-dsl",
         "inflect",


[22/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: Fix marvin build and maven pom

- maven pom pointer codegenerator->xmltoapi
- regression in apidocxmlwriter fixed NPE
- fixed imports in generate module


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/f8958bd1
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/f8958bd1
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/f8958bd1

Branch: refs/heads/marvin-refactor
Commit: f8958bd1ba9bcf21f36b078bbcaffd22398881c2
Parents: 0e2e5ed
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Sun Sep 8 13:31:25 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:37 2013 +0530

----------------------------------------------------------------------
 server/src/com/cloud/api/doc/ApiXmlDocWriter.java | 10 ++++++----
 tools/marvin/marvin/generate/apitoentity.py       |  6 +++---
 tools/marvin/marvin/generate/linguist.py          |  2 +-
 tools/marvin/marvin/generate/xmltoapi.py          |  2 +-
 tools/marvin/pom.xml                              |  2 +-
 5 files changed, 12 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f8958bd1/server/src/com/cloud/api/doc/ApiXmlDocWriter.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/doc/ApiXmlDocWriter.java b/server/src/com/cloud/api/doc/ApiXmlDocWriter.java
index b981abb..dc3009f 100644
--- a/server/src/com/cloud/api/doc/ApiXmlDocWriter.java
+++ b/server/src/com/cloud/api/doc/ApiXmlDocWriter.java
@@ -608,9 +608,11 @@ public class ApiXmlDocWriter {
         try {
             ObjectOutputStream out = xs.createObjectOutputStream(new FileWriter(dirName + "/alert_types.xml"), "alerts");
             for (Field f : AlertManager.class.getFields()) {
-                String name = f.getName().substring(11);
-                Alert alert = new Alert(name, f.getInt(null));
-                out.writeObject(alert);
+                if (f.getClass().isAssignableFrom(Number.class)) {
+                    String name = f.getName().substring(11);
+                    Alert alert = new Alert(name, f.getInt(null));
+                    out.writeObject(alert);
+                }
             }
             out.close();
         } catch (IOException e) {
@@ -636,4 +638,4 @@ public class ApiXmlDocWriter {
         }
     }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f8958bd1/tools/marvin/marvin/generate/apitoentity.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/apitoentity.py b/tools/marvin/marvin/generate/apitoentity.py
index 4a05ebf..0be5d9a 100644
--- a/tools/marvin/marvin/generate/apitoentity.py
+++ b/tools/marvin/marvin/generate/apitoentity.py
@@ -16,9 +16,9 @@
 # under the License.
 
 import os
-from marvin.generate.entity import Entity
-from marvin.generate.factory import Factory
-from marvin.generate.linguist import *
+from entity import Entity
+from factory import Factory
+from linguist import *
 
 LICENSE = """# Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f8958bd1/tools/marvin/marvin/generate/linguist.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/linguist.py b/tools/marvin/marvin/generate/linguist.py
index 82a7bfc..fd2729e 100644
--- a/tools/marvin/marvin/generate/linguist.py
+++ b/tools/marvin/marvin/generate/linguist.py
@@ -19,7 +19,7 @@ try:
     import inflect
 except ImportError:
     raise Exception("inflect installation not found. use pip install inflect to continue")
-from marvin.generate.verbs import grammar
+from verbs import grammar
 
 def singularize(word, num=0):
     """Use the inflect engine to make singular nouns of the entities

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f8958bd1/tools/marvin/marvin/generate/xmltoapi.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/xmltoapi.py b/tools/marvin/marvin/generate/xmltoapi.py
index 22a2786..458873a 100644
--- a/tools/marvin/marvin/generate/xmltoapi.py
+++ b/tools/marvin/marvin/generate/xmltoapi.py
@@ -23,7 +23,7 @@ import urllib2
 from argparse import ArgumentParser
 from textwrap import dedent
 from os import path
-from marvin.generate.apitoentity import generate, get_entity_action_map
+from apitoentity import generate, get_entity_action_map
 
 class cmdParameterProperty(object):
     def __init__(self):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f8958bd1/tools/marvin/pom.xml
----------------------------------------------------------------------
diff --git a/tools/marvin/pom.xml b/tools/marvin/pom.xml
index 25909b3..872921d 100644
--- a/tools/marvin/pom.xml
+++ b/tools/marvin/pom.xml
@@ -55,7 +55,7 @@
               <workingDirectory>${basedir}/marvin</workingDirectory>
               <executable>python</executable>
               <arguments>
-                <argument>codegenerator.py</argument>
+                <argument>generate/xmltoapi.py</argument>
                 <argument>-s</argument>
                 <argument>${basedir}/commands.xml</argument>
               </arguments>


[16/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: generation of code is in the generate module

CloudStack's API DSL is converted into marvin's modules using the
generate module.

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/8cdac504
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8cdac504
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8cdac504

Branch: refs/heads/marvin-refactor
Commit: 8cdac5040ba79356cf19492e2dc760e411300cc5
Parents: ff8dfe1
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Sat Sep 7 10:57:11 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:25 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/codegenerator.py        | 490 -----------------------
 tools/marvin/marvin/cs_entity_generator.py  | 384 ------------------
 tools/marvin/marvin/generate/apitoentity.py | 131 ++++++
 tools/marvin/marvin/generate/entity.py      | 166 ++++++++
 tools/marvin/marvin/generate/factory.py     |  59 +++
 tools/marvin/marvin/generate/linguist.py    | 158 ++++++++
 tools/marvin/marvin/generate/verbs.py       |  27 ++
 tools/marvin/marvin/generate/xmltoapi.py    | 488 ++++++++++++++++++++++
 8 files changed, 1029 insertions(+), 874 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8cdac504/tools/marvin/marvin/codegenerator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/codegenerator.py b/tools/marvin/marvin/codegenerator.py
deleted file mode 100644
index 28ec4dd..0000000
--- a/tools/marvin/marvin/codegenerator.py
+++ /dev/null
@@ -1,490 +0,0 @@
-# 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.
-
-import xml.dom.minidom
-import json
-import os
-import sys
-import urllib2
-from argparse import ArgumentParser
-from textwrap import dedent
-from os import path
-from cs_entity_generator import write_entity_classes, get_actionable_entities
-
-
-
-class cmdParameterProperty(object):
-    def __init__(self):
-        self.name = None
-        self.required = False
-        self.entity = ""
-        self.desc = ""
-        self.type = "planObject"
-        self.subProperties = []
-
-
-class cloudStackCmd(object):
-    def __init__(self):
-        self.name = ""
-        self.desc = ""
-        self.async = "false"
-        self.entity = ""
-        self.request = []
-        self.response = []
-
-
-class codeGenerator(object):
-    """
-    Apache CloudStack- marvin python classes can be generated from the json
-    returned by API discovery or from the xml spec of commands generated by
-    the ApiDocWriter. This class provides helper methods for these uses.
-    """
-    space = '    '
-    newline = '\n'
-    cmdsName = []
-
-    def __init__(self, outputFolder):
-        self.cmd = None
-        self.code = ""
-        self.required = []
-        self.subclass = []
-        self.outputFolder = outputFolder
-        lic = """\
-          # 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.
-
-          """
-        self.license = dedent(lic)
-
-    def addAttribute(self, attr, pro):
-        value = pro.value
-        if pro.required:
-            self.required.append(attr)
-        desc = pro.desc
-        if desc is not None:
-            self.code += self.space
-            self.code += "''' " + pro.desc + " '''"
-            self.code += self.newline
-
-        self.code += self.space
-        self.code += attr + " = " + str(value)
-        self.code += self.newline
-
-    def generateSubClass(self, name, properties):
-        """Generate code for sub objects
-        """
-        subclass = 'class %s:\n'%name
-        subclass += self.space + "def __init__(self):\n"
-        for pro in properties:
-            if pro.desc is not None:
-                subclass += self.space + self.space + '""""%s"""\n' % pro.desc
-            if len(pro.subProperties) > 0:
-                subclass += self.space + self.space
-                subclass += 'self.%s = []\n' % pro.name
-                self.generateSubClass(pro.name, pro.subProperties)
-            else:
-                subclass += self.space + self.space
-                subclass += 'self.%s = None\n' % pro.name
-
-        self.subclass.append(subclass)
-
-    def generateApiCmd(self, cmd):
-        """Given an API cmd module generate the cloudstack cmd class in python
-        """
-        self.code = ""
-        self.subclass = []
-        self.cmd = cmd
-        self.cmdsName.append(self.cmd.name)
-        self.code = self.license
-        self.code += self.newline
-        self.code += '"""%s"""\n' % self.cmd.desc
-        self.code += 'from baseCmd import *\n'
-        self.code += 'from baseResponse import *\n'
-        self.code += "class %sCmd (baseCmd):\n" % self.cmd.name
-        self.code += self.space + "def __init__(self):\n"
-        self.code += self.space + self.space
-        self.code += 'self.isAsync = "%s"\n' % str(self.cmd.async).lower()
-        self.code += self.space*2 + 'self.entity = "%s"\n' % self.cmd.entity
-
-        for req in self.cmd.request:
-            if req.desc is not None:
-                self.code += self.space + self.space + '"""%s"""\n' % req.desc
-            if req.required:
-                self.code += self.space + self.space + '"""Required"""\n'
-
-            value = "None"
-            if req.type == "list" or req.type == "map":
-                value = "[]"
-
-            self.code += self.space + self.space
-            self.code += 'self.%s = %s\n' % (req.name, value)
-            if req.required:
-                self.required.append(req.name)
-
-        self.code += self.space + self.space + "self.required = ["
-        for require in self.required:
-            self.code += '"' + require + '",'
-        self.code += "]\n"
-        #print cmd.name, self.required
-        self.required = []
-
-        """generate response code"""
-        subItems = {}
-        self.code += self.newline
-        self.code += 'class %sResponse (baseResponse):\n' % self.cmd.name
-        self.code += self.space + "def __init__(self):\n"
-        if len(self.cmd.response) == 0:
-            self.code += self.space + self.space + "pass"
-        else:
-            for res in self.cmd.response:
-                if res.desc is not None:
-                    self.code += self.space + self.space
-                    self.code += '"""%s"""\n' % res.desc
-
-                if len(res.subProperties) > 0:
-                    self.code += self.space + self.space
-                    self.code += 'self.%s = []\n' % res.name
-                    self.generateSubClass(res.name, res.subProperties)
-                else:
-                    self.code += self.space + self.space
-                    self.code += 'self.%s = None\n' % res.name
-        self.code += self.newline
-
-        for subclass in self.subclass:
-            self.code += subclass + "\n"
-        return self.code
-
-    def write(self, out, modulename, code):
-        """
-        writes the generated code for `modulename` in the `out.cloudstackAPI` package
-        @param out: absolute path where all api cmds are written to
-        @param modulename: name of the module being written: eg: createNetwork
-        @param code: Generated code
-        @return: None
-        """
-        final_path = path.join(out, modulename)
-        module = final_path + '.py' #eg: out/cloudstackAPI/modulename.py
-        with open(module, "w") as fp:
-            fp.write(code)
-
-    def finalize(self):
-        """Generate an api call
-        """
-        header = '"""Marvin TestClient for CloudStack"""\n'
-        imports = "import copy\n"
-        initCmdsList = '__all__ = ['
-        body = ''
-        body += "class CloudStackAPIClient(object):\n"
-        body += self.space + 'def __init__(self, connection):\n'
-        body += self.space + self.space + 'self.connection = connection\n'
-        body += self.space + self.space + 'self._id = None\n'
-        body += self.newline
-
-        body += self.space + 'def __copy__(self):\n'
-        body += self.space + self.space
-        body += 'return CloudStackAPIClient(copy.copy(self.connection))\n'
-        body += self.newline
-
-        # The `id` property will be used to link the test with the cloud
-        # resource being created
-        #            @property
-        #            def id(self):
-        #                return self._id
-        #
-        #            @id.setter
-        #            def id(self, identifier):
-        #                self._id = identifier
-
-        body += self.space + '@property' + self.newline
-        body += self.space + 'def id(self):' + self.newline
-        body += self.space*2 + 'return self._id' + self.newline
-        body += self.newline
-
-        body += self.space + '@id.setter' + self.newline
-        body += self.space + 'def id(self, identifier):' + self.newline
-        body += self.space*2 + 'self._id = identifier' + self.newline
-        body += self.newline
-
-        for cmdName in self.cmdsName:
-            body += self.space
-            body += 'def %s(self, command, method="GET"):\n' % cmdName
-            body += self.space + self.space
-            body += 'response = %sResponse()\n' % cmdName
-            body += self.space + self.space
-            body += 'response = self.connection.marvin_request(command,'
-            body += ' response_type=response, method=method)\n'
-            body += self.space + self.space + 'return response\n'
-            body += self.newline
-
-            imports += 'from %s import %sResponse\n' % (cmdName, cmdName)
-            initCmdsList += '"%s",' % cmdName
-
-        cloudstackApiClient = self.license + header + imports + body
-        self.write(out=self.outputFolder, modulename='cloudstackAPIClient', code=cloudstackApiClient)
-
-        '''generate __init__.py'''
-        initCmdsList = self.license + initCmdsList + '"cloudstackAPIClient"]'
-        self.write(out=self.outputFolder, modulename='__init__', code=initCmdsList)
-
-        basecmd = self.license
-        basecmd += '"""Base Command"""\n'
-        basecmd += 'class baseCmd(object):\n'
-        basecmd += self.space + 'pass\n'
-        self.write(out=self.outputFolder, modulename='baseCmd', code=basecmd)
-
-        baseResponse = self.license
-        baseResponse += '"""Base Response"""\n'
-        baseResponse += 'class baseResponse:\n'
-        baseResponse += self.space + 'pass\n'
-        self.write(out=self.outputFolder, modulename='baseResponse', code=baseResponse)
-
-    def constructResponseFromXML(self, response):
-        paramProperty = cmdParameterProperty()
-        paramProperty.name = getText(response.getElementsByTagName('name'))
-        paramProperty.desc = getText(response.
-                                     getElementsByTagName('description'))
-        if paramProperty.name.find('(*)') != -1:
-            '''This is a list'''
-            paramProperty.name = paramProperty.name.split('(*)')[0]
-            argList = response.getElementsByTagName('arguments')[0].\
-                getElementsByTagName('arg')
-            for subresponse in argList:
-                subProperty = self.constructResponseFromXML(subresponse)
-                paramProperty.subProperties.append(subProperty)
-        return paramProperty
-
-    def loadCmdFromXML(self, dom):
-        cmds = []
-        for cmd in dom.getElementsByTagName("command"):
-            csCmd = cloudStackCmd()
-            csCmd.name = getText(cmd.getElementsByTagName('name'))
-            assert csCmd.name
-            if csCmd.name in ['login', 'logout']:
-                continue
-
-            csCmd.entity = getText(cmd.getElementsByTagName('entity'))
-            assert csCmd.entity
-
-            desc = getText(cmd.getElementsByTagName('description'))
-            if desc:
-                csCmd.desc = desc
-
-            async = getText(cmd.getElementsByTagName('isAsync'))
-            if async:
-                csCmd.async = async
-
-            argList = cmd.getElementsByTagName("request")[0].\
-                getElementsByTagName("arg")
-            for param in argList:
-                paramProperty = cmdParameterProperty()
-
-                paramProperty.name =\
-                    getText(param.getElementsByTagName('name'))
-                assert paramProperty.name
-
-                required = param.getElementsByTagName('required')
-                if getText(required) == "true":
-                    paramProperty.required = getText(required)
-
-                requestDescription = param.getElementsByTagName('description')
-                if requestDescription:
-                    paramProperty.desc = getText(requestDescription)
-
-                type = param.getElementsByTagName("type")
-                if type:
-                    paramProperty.type = getText(type)
-
-                csCmd.request.append(paramProperty)
-
-            responseEle = cmd.getElementsByTagName("response")[0]
-            for response in responseEle.getElementsByTagName("arg"):
-                if response.parentNode != responseEle:
-                    continue
-
-                paramProperty = self.constructResponseFromXML(response)
-                csCmd.response.append(paramProperty)
-
-            cmds.append(csCmd)
-        return cmds
-
-    def generateCodeFromXML(self, apiSpecFile):
-        dom = xml.dom.minidom.parse(apiSpecFile)
-        cmds = self.loadCmdFromXML(dom)
-        for cmd in cmds:
-            code = self.generateApiCmd(cmd)
-            self.write(out=self.outputFolder, modulename=cmd.name, code=code)
-        self.finalize()
-
-    def constructResponseFromJSON(self, response):
-        paramProperty = cmdParameterProperty()
-        if 'name' in response:
-            paramProperty.name = response['name']
-        assert paramProperty.name, "%s has no property name" % response
-
-        if 'description' in response:
-            paramProperty.desc = response['description']
-        if 'type' in response:
-            if response['type'] in ['list', 'map', 'set']:
-            #Here list becomes a subproperty
-                if 'response' in response:
-                    for innerResponse in response['response']:
-                        subProperty =\
-                            self.constructResponseFromJSON(innerResponse)
-                        paramProperty.subProperties.append(subProperty)
-            paramProperty.type = response['type']
-        return paramProperty
-
-    def loadCmdFromJSON(self, apiStream):
-        if apiStream is None:
-            raise Exception("No APIs found through discovery")
-
-        jsonOut = apiStream.readlines()
-        assert len(jsonOut) > 0
-        apiDict = json.loads(jsonOut[0])
-        if not 'listapisresponse' in apiDict:
-            raise Exception("API discovery plugin response failed")
-        if not 'count' in apiDict['listapisresponse']:
-            raise Exception("Malformed api response")
-
-        apilist = apiDict['listapisresponse']['api']
-        cmds = []
-        for cmd in apilist:
-            csCmd = cloudStackCmd()
-            if 'name' in cmd:
-                csCmd.name = cmd['name']
-            assert csCmd.name
-            if csCmd.name in ['login', 'logout']:
-                continue
-
-            if cmd.has_key('entity'):
-                csCmd.entity = cmd['entity']
-            else:
-                print csCmd.name + " has no entity"
-
-            if 'description' in cmd:
-                csCmd.desc = cmd['description']
-
-            if 'isasync' in cmd:
-                csCmd.async = cmd['isasync']
-
-            for param in cmd['params']:
-                paramProperty = cmdParameterProperty()
-
-                if 'name' in param:
-                    paramProperty.name = param['name']
-                assert paramProperty.name
-
-                if 'required' in param:
-                    paramProperty.required = param['required']
-
-                if 'description' in param:
-                    paramProperty.desc = param['description']
-
-                if 'type' in param:
-                    paramProperty.type = param['type']
-
-                csCmd.request.append(paramProperty)
-
-            for response in cmd['response']:
-            #FIXME: ExtractImage related APIs return empty dicts in response
-                if len(response) > 0:
-                    paramProperty = self.constructResponseFromJSON(response)
-                    csCmd.response.append(paramProperty)
-
-            cmds.append(csCmd)
-        return cmds
-
-    def generateCodeFromJSON(self, endpointUrl):
-        """
-        Api Discovery plugin returns the supported APIs of a CloudStack
-        endpoint.
-        @return: The classes in cloudstackAPI/ formed from api discovery json
-        """
-        if endpointUrl.find('response=json') >= 0:
-            apiStream = urllib2.urlopen(endpointUrl)
-            cmds = self.loadCmdFromJSON(apiStream)
-            for cmd in cmds:
-                code = self.generateApiCmd(cmd)
-                self.write(out=self.outputFolder, modulename=cmd.name, code=code)
-            self.finalize()
-
-
-def getText(elements):
-    return elements[0].childNodes[0].nodeValue.strip()
-
-if __name__ == "__main__":
-    parser = ArgumentParser()
-    parser.add_argument("-o", "--output", dest="output",
-                      help="The path to the generated code entities, default\
- is .")
-    parser.add_argument("-s", "--specfile", dest="spec",
-                      help="The path and name of the api spec xml file,\
- default is /etc/cloud/cli/commands.xml")
-    parser.add_argument("-e", "--endpoint", dest="endpoint",
-                      help="The endpoint mgmt server (with open 8096) where\
- apis are discovered, default is localhost")
-    parser.add_argument("-y", "--entity", dest="entity", action="store_true",
-                      help="Generate entity based classes")
-
-    options = parser.parse_args()
-
-    folder = "."
-    if options.output is not None:
-        folder = options.output
-    apiModule = folder + "/cloudstackAPI"
-    if not os.path.exists(apiModule):
-        try:
-            os.mkdir(apiModule)
-        except:
-            print "Failed to create folder %s, due to %s" % (apiModule,
-                                                             sys.exc_info())
-            print parser.print_help()
-            exit(2)
-
-    apiSpecFile = "/etc/cloud/cli/commands.xml"
-    if options.spec is not None:
-        apiSpecFile = options.spec
-        if not os.path.exists(apiSpecFile):
-            print "the spec file %s does not exists" % apiSpecFile
-            print parser.print_help()
-            exit(1)
-
-    cg = codeGenerator(apiModule)
-    if options.spec is not None:
-        cg.generateCodeFromXML(apiSpecFile)
-    elif options.endpoint is not None:
-        endpointUrl = 'http://%s:8096/client/api?command=listApis&\
-response=json' % options.endpoint
-        cg.generateCodeFromJSON(endpointUrl)
-
-    if options.entity:
-        entities = get_actionable_entities()
-        write_entity_classes(entities, "entity")

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8cdac504/tools/marvin/marvin/cs_entity_generator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cs_entity_generator.py b/tools/marvin/marvin/cs_entity_generator.py
deleted file mode 100644
index c3cda0c..0000000
--- a/tools/marvin/marvin/cs_entity_generator.py
+++ /dev/null
@@ -1,384 +0,0 @@
-# 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.
-
-import os
-try:
-    import inflect
-except ImportError:
-    raise Exception("inflect installation not found. use pip install inflect to continue")
-
-grammar = ['create', 'list', 'delete', 'update', 'ldap', 'login', 'logout',
-           'enable', 'activate', 'disable', 'add', 'remove',
-           'attach', 'detach', 'associate', 'generate', 'assign',
-           'authorize', 'change', 'register', 'configure',
-           'start', 'restart', 'reboot', 'stop', 'reconnect',
-           'cancel', 'destroy', 'revoke', 'mark', 'reset',
-           'copy', 'extract', 'migrate', 'restore', 'suspend',
-           'get', 'query', 'prepare', 'deploy', 'upload', 'lock',
-           'disassociate', 'scale', 'dedicate', 'archive', 'find',
-           'recover', 'release', 'resize', 'revert', 'replace']
-
-LICENSE = """# 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.
-"""
-
-def get_api_cmds():
-    """ Returns the API cmdlet instances
-
-    @return: instances of all the API commands exposed by CloudStack
-    """
-    namespace = {}
-    execfile('cloudstackAPI/__init__.py', namespace)
-    api_classes = __import__('cloudstackAPI', globals().update(namespace), fromlist=['*'], level=-1)
-
-
-    cmdlist = map(
-        lambda f: getattr(api_classes, f),
-        filter(
-            lambda t: t.startswith('__') == False,
-            dir(api_classes)
-        )
-    )
-    cmdlist = filter(
-        lambda g: g is not None,
-        cmdlist
-    )
-    clslist = map(
-        lambda g: getattr(g, g.__name__.split('.')[-1] + 'Cmd'),
-        filter(
-            lambda h: h.__name__.split('.')[-1] not in ['baseCmd', 'baseResponse', 'cloudstackAPIClient'],
-            cmdlist
-        )
-    )
-    cmdlets = map(lambda t: t(), clslist)
-    return cmdlets
-
-def singularize(word, num=0):
-    """Use the inflect engine to make singular nouns of the entities
-    @return: singular of `word`
-    """
-    inflector = inflect.engine()
-    return inflector.singular_noun(word)
-
-def transform_api(api):
-    """Brute-force transform for entities that don't match other transform rules
-    """
-    if api == 'ldapConfig':
-        return 'configure', 'Ldap'
-    elif api == 'ldapRemove':
-        return 'remove', 'Ldap'
-    elif api == 'login':
-        return 'login', 'CloudStack'
-    elif api == 'logout':
-        return 'logout', 'CloudStack'
-    return api, None
-
-def verb_adjust(api, entity):
-    """
-    Considers the prefix as the verb when no preposition transformers have been found in the API
-    Only if the entity is contained in the API string
-    """
-    index = api.lower().find(entity.lower())
-    if index > 0:
-        return api[:index]
-    else:
-        return api
-
-def entity_adjust(entity):
-    """
-    Some entities are managed within CloudStack where they don't bear any resemblance to the API.
-    Adjust such entities to a more sensible client side entity
-
-    #BUG: Inflect engine returns IpAddress => IpAddres as singular
-    """
-    if entity == 'IpAddres' or entity == 'IPAddres':
-        return 'IpAddress'
-    elif entity == 'SecurityGroupIngres':
-        return 'SecurityGroupIngress'
-    elif entity == 'SecurityGroupEgres':
-        return 'SecurityGroupEgress'
-    elif entity == 'GuestO':
-        return 'GuestOS'
-    elif entity == 'LBStickines':
-        return 'LBStickiness'
-    #CloudStack denotes VirtualRouter as DomainRouter
-    elif entity == 'DomainRouter':
-        return 'VirtualRouter'
-    #CloudStack denotes VirtualMachine as UserVm
-    elif entity == 'UserVm':
-        return 'VirtualMachine'
-    #CloudStack denotes aliased NIC (with IP) as NicSecondaryIp
-    elif entity == 'NicSecondaryIp':
-        return 'Nic'
-    elif entity == 'Site2SiteVpnConnection':
-        return 'VpnConnection'
-    elif entity == 'Site2SiteVpnGateway':
-        return 'VpnGateway'
-    elif entity == 'Site2SiteCustomerGateway':
-        return 'VpnCustomerGateway'
-    #Cloudstack returns Register entity for registerUserKeys
-    elif entity == 'Register':
-        return 'UserKeys'
-    #Cloudstack maintains Template/ISO/Volume as single Image type
-    #elif entity in ['Template', 'Volume']:
-    #    return 'Image'
-    #extractImage returns an Extract response but is a property of Image
-    elif entity == 'Extract':
-        return 'Template'
-    return entity
-
-def prepositon_transformer(preposition=None):
-    """Returns a transformer for the entity if it has a doXPrepositionY style API
-
-    @param entity: The entity eg: resetPasswordForVirtualMachine, preposition=For
-    @return: transformed entity, Y is the entity and doX is the verb, eg: VirtualMachine, resetPassword
-    """
-    def transform_api_with_preposition(api):
-        if api.find(preposition) > 0:
-            if api[api.find(preposition) + len(preposition)].isupper():
-                return api[:api.find(preposition)], api[api.find(preposition) + len(preposition):]
-        return api, None
-    return transform_api_with_preposition
-
-def skip_list():
-    """APIs that we will not auto-generate
-    """
-    return ['cleanVMReservationsCmd']
-
-def get_transformers():
-    """ List of transform rules as lambdas
-    """
-    transformers = [prepositon_transformer('Of'),
-                    prepositon_transformer('For'),
-                    prepositon_transformer('To'),
-                    prepositon_transformer('From'),
-                    prepositon_transformer('With'),
-                    transform_api]
-    return transformers
-
-def get_verb_and_entity(cmd):
-    """Break down the API cmd instance in to `verb` and `Entity`
-    @return: verb, Entity tuple
-    """
-    api = cmd.__class__.__name__
-    api = api.replace('Cmd', '')
-    #apply known list of transformations
-    matching_verbs = filter(lambda v: api.startswith(v), grammar)
-    if len(matching_verbs) > 0:
-        for transformer in get_transformers():
-            if transformer(api)[1]:
-                verb = transformer(api)[0]
-                if cmd.entity:
-                    entity = singularize(cmd.entity) if singularize(cmd.entity) else cmd.entity
-                else:
-                    entity = verb, \
-                                singularize(transformer(api)[1]) if singularize(transformer(api)[1]) else transformer(api)[1]
-                entity = entity_adjust(entity)
-                break
-        else:
-            verb = matching_verbs[0]
-            entity = api.replace(verb, '')
-            if cmd.entity:
-                entity = singularize(cmd.entity) if singularize(cmd.entity) else cmd.entity
-            else:
-                entity = singularize(entity) if singularize(entity) else entity
-            entity = entity_adjust(entity)
-            verb = verb_adjust(api, entity)
-        #print "%s => (verb, entity) = (%s, %s)" % (api, verb, entity)
-        return verb, entity
-    else:
-        print "No matching verb, entity breakdown for api %s" % api
-
-def get_actionable_entities():
-    """
-    Inspect all entities and return a map of the Entity against the actions
-    along with the required arguments to satisfy the action
-
-    @return: Dictionary of Entity { "verb" : [required] }
-    """
-    cmdlets = sorted(filter(lambda api: api.__class__.__name__ not in skip_list(), get_api_cmds()),
-        key=lambda k: get_verb_and_entity(k)[1])
-
-    entities = {}
-    for cmd in cmdlets:
-        requireds = getattr(cmd, 'required')
-        optionals = filter(lambda x: '__' not in x and x not in ['required', 'isAsync', 'entity'], dir(cmd))
-        api = cmd.__class__.__name__
-        if api in skip_list():
-            continue
-        verb, entity = get_verb_and_entity(cmd)
-        if entity not in entities:
-            entities[entity] = {}
-        entities[entity][verb] = {}
-        entities[entity][verb]['args'] = requireds
-        entities[entity][verb]['optionals'] = optionals
-        entities[entity][verb]['apimodule'] = cmd.__class__.__module__.split('.')[-1]
-        entities[entity][verb]['apicmd'] = api
-    print "Transformed %s APIs to %s entities successfully" % (len(cmdlets), len(entities)) \
-            if len(cmdlets) > 0 \
-            else "No transformations occurred"
-    return entities
-
-
-def write_entity_classes(entities, module=None):
-    """
-    Writes the collected entity classes into `path`
-
-    @param entities: dictionary of entities and the verbs acting on them
-    @param module: top level module to the generated classes
-    @return:
-    """
-    tabspace = '    '
-    entitydict = {}
-    for entity, actions in entities.iteritems():
-        body = []
-        imports = []
-        imports.append('from cloudstackentity import CloudStackEntity')
-        body.append('class %s(CloudStackEntity):' % entity)
-        body.append('\n\n')
-        body.append(tabspace + 'def __init__(self, items):')
-        body.append(tabspace * 2 + 'self.__dict__.update(items)')
-        body.append('\n')
-        for action, details in actions.iteritems():
-            imports.append('from marvin.cloudstackAPI import %s' % details['apimodule'])
-            if action.startswith('create') or action.startswith('list') or action.startswith(
-                'register') or action.startswith('deploy'):
-                body.append(tabspace + '@classmethod')
-            if action not in ['create', 'deploy']:
-                no_id_args = filter(lambda arg: arg!= 'id', details['args'])
-                if len(no_id_args) > 0:
-                    body.append(tabspace + 'def %s(self, apiclient, %s, **kwargs):' % (
-                        action, ', '.join(list(set(no_id_args)))))
-                else:
-                    body.append(tabspace + 'def %s(self, apiclient, **kwargs):' % (action))
-                #TODO: Add docs for entity
-                # doc to explain what possible args go into **kwargs
-                body.append(tabspace * 2 + '"""Placeholder for docstring')
-                body.append(tabspace * 2 + 'optional arguments (**kwargs): [%s]"""' % ', '.join(details['optionals']))
-
-                body.append(tabspace * 2 + 'cmd = %(module)s.%(command)s()' % {"module": details["apimodule"],
-                                                                               "command": details["apicmd"]})
-                if 'id' in details['args']:
-                    body.append(tabspace * 2 + 'cmd.id = self.id')
-                for arg in no_id_args:
-                    body.append(tabspace * 2 + 'cmd.%s = %s' % (arg, arg))
-                body.append(tabspace * 2 + '[setattr(cmd, key, value) for key,value in kwargs.iteritems()]')
-                body.append(tabspace * 2 + '%s = apiclient.%s(cmd)' % (entity.lower(), details['apimodule']))
-                if action.startswith('list'):
-                    body.append(
-                        tabspace * 2 + 'return map(lambda e: %s(e.__dict__), %s) if %s and len(%s) > 0 else None' % (
-                            entity, entity.lower(), entity.lower(), entity.lower()))
-                else:
-                    body.append(tabspace * 2 + 'return %s if %s else None' % (entity.lower(), entity.lower()))
-            else:
-                if len(details['args']) > 0:
-                    body.append(tabspace + 'def %s(cls, apiclient, %s, factory=None, **kwargs):' % (
-                        action, ', '.join(map(lambda arg: arg + '=None', list(set(details['args']))))))
-                else:
-                    body.append(tabspace + 'def %s(cls, apiclient, factory=None, **kwargs):' % action)
-                    #TODO: Add docs for actions
-                # doc to explain what possible args go into **kwargs
-                body.append(tabspace * 2 + '"""Placeholder for docstring')
-                body.append(tabspace * 2 + 'optional arguments (**kwargs): [%s]"""' % ', '.join(details['optionals']))
-
-                body.append(tabspace * 2 + 'cmd = %(module)s.%(command)s()' % {"module": details["apimodule"],
-                                                                               "command": details["apicmd"]})
-                body.append(tabspace * 2 + 'if factory:')
-                body.append(
-                    tabspace * 3 + '[setattr(cmd, factoryKey, factoryValue) for factoryKey, factoryValue in factory.__dict__.iteritems()]')
-                if len(details["args"]) > 0:
-                    body.append(tabspace * 2 + 'else:')
-                    for arg in details["args"]:
-                        body.append(tabspace * 3 + "cmd.%s = %s" % (arg, arg))
-                body.append(tabspace * 2 + '[setattr(cmd, key, value) for key, value in kwargs.iteritems()]')
-                body.append(tabspace * 2 + '%s = apiclient.%s(cmd)' % (entity.lower(), details['apimodule']))
-                body.append(
-                    tabspace * 2 + 'return %s(%s.__dict__) if %s else None' % (entity, entity.lower(), entity.lower()))
-            body.append('\n')
-
-        imports = '\n'.join(imports)
-        body = '\n'.join(body)
-        code = imports + '\n\n' + body
-
-        entitydict[entity] = code
-        write_entity_factory(entity, actions, module='factory')
-        module_path = './' + '/'.join(module.split('.'))
-        if not os.path.exists("%s" % module_path):
-            os.makedirs("%s" % module_path)
-        with open("%s/__init__.py" % (module_path), "w") as writer:
-            writer.write(LICENSE)
-        with open("%s/%s.py" % (module_path, entity.lower()), "w") as writer:
-            writer.write(LICENSE)
-            writer.write(code)
-
-def write_entity_factory(entity, actions, module=None):
-    """Data factories for each entity
-    """
-
-    tabspace = '    '
-    code = ''
-    factory_defaults = []
-    keys = actions.keys()
-    for key in keys:
-        if key.startswith('create'):
-            factory_defaults.extend(actions[key]['args'])
-        elif key.startswith('deploy'):
-            factory_defaults.extend(actions[key]['args'])
-        elif key.startswith('associate'):
-            factory_defaults.extend(actions[key]['args'])
-        elif key.startswith('register'):
-            factory_defaults.extend(actions[key]['args'])
-        else:
-            continue
-            #print '%s is not suitable for factory creation for entity %s' %(key, entity)
-
-    factory_defaults = set(factory_defaults)
-    module_path = './' + '/'.join(module.split('.'))
-    if not os.path.exists(module_path):
-        os.makedirs(module_path)
-
-    code += 'from marvin.entity.%s import %s\n' % (entity.lower(), entity)
-    code += 'from cloudstackbasefactory import CloudStackBaseFactory'
-    code += '\n'
-    code += 'class %sFactory(CloudStackBaseFactory):' % entity
-    code += '\n\n'
-    code += tabspace + 'FACTORY_FOR = %s\n\n' % entity
-    for arg in factory_defaults:
-        code += tabspace + '%s = None\n' % arg
-    with open("%s/__init__.py" % (module_path), "w") as writer:
-        writer.write(LICENSE)
-    with open("%s/%s.py" % (module_path, entity.lower()), "w") as writer:
-        writer.write(LICENSE)
-        writer.write(code)
-
-if __name__ == '__main__':
-    entities = get_actionable_entities()
-    write_entity_classes(entities, 'entity')

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8cdac504/tools/marvin/marvin/generate/apitoentity.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/apitoentity.py b/tools/marvin/marvin/generate/apitoentity.py
new file mode 100644
index 0000000..4a05ebf
--- /dev/null
+++ b/tools/marvin/marvin/generate/apitoentity.py
@@ -0,0 +1,131 @@
+# 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.
+
+import os
+from marvin.generate.entity import Entity
+from marvin.generate.factory import Factory
+from marvin.generate.linguist import *
+
+LICENSE = """# 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.
+"""
+
+def get_api_cmds():
+    """ Returns the API cmdlet instances
+
+    @return: instances of all the API commands exposed by CloudStack
+    """
+    namespace = {}
+    execfile('cloudstackAPI/__init__.py', namespace)
+    api_classes = __import__('cloudstackAPI', globals().update(namespace), fromlist=['*'], level=-1)
+
+
+    cmdlist = map(
+        lambda f: getattr(api_classes, f),
+        filter(
+            lambda t: t.startswith('__') == False,
+            dir(api_classes)
+        )
+    )
+    cmdlist = filter(
+        lambda g: g is not None,
+        cmdlist
+    )
+    clslist = map(
+        lambda g: getattr(g, g.__name__.split('.')[-1] + 'Cmd'),
+        filter(
+            lambda h: h.__name__.split('.')[-1] not in ['baseCmd', 'baseResponse', 'cloudstackAPIClient'],
+            cmdlist
+        )
+    )
+    cmdlets = map(lambda t: t(), clslist)
+    return cmdlets
+
+def get_entity_action_map():
+    """ Inspect cloudstack api and return a map of the Entity against the actions
+    along with the required arguments to make the action call
+
+    @return: Dictionary of Entity { "verb" : [required] }
+    eg: VirtualMachine { "deploy" : [templateid, serviceoffering, zoneid, etc] }
+    """
+    cmdlets = sorted(filter(lambda api: api.__class__.__name__ not in skip_list(), get_api_cmds()),
+        key=lambda k: get_verb_and_entity(k)[1])
+
+    entities = {}
+    for cmd in cmdlets:
+        requireds = getattr(cmd, 'required')
+        optionals = filter(lambda x: '__' not in x and x not in ['required', 'isAsync', 'entity'], dir(cmd))
+        api = cmd.__class__.__name__
+        if api in skip_list():
+            continue
+        verb, entity = get_verb_and_entity(cmd)
+        if entity not in entities:
+            entities[entity] = {}
+        entities[entity][verb] = {}
+        entities[entity][verb]['args'] = requireds
+        entities[entity][verb]['optionals'] = optionals
+        entities[entity][verb]['apimodule'] = cmd.__class__.__module__.split('.')[-1]
+        entities[entity][verb]['apicmd'] = api
+    print "Transformed %s APIs to %s entities successfully" % (len(cmdlets), len(entities)) \
+            if len(cmdlets) > 0 \
+            else "No transformations occurred"
+    return entities
+
+def write(entity_or_factory, module):
+    module_path = './' + '/'.join(module.split('.'))
+    if not os.path.exists("%s" % module_path):
+        os.makedirs("%s" % module_path)
+    with open("%s/__init__.py" % (module_path), "w") as writer:
+        writer.write(LICENSE)
+    with open("%s/%s.py" % (module_path, entity_or_factory.name.lower()), "w") as writer:
+        writer.write(LICENSE)
+        writer.write(entity_or_factory.__str__())
+
+def generate(entities):
+    """
+    Writes the collected entity classes
+
+    @param entities: dictionary of entities and the verbs acting on them
+    @return:
+    """
+    for entity, actions in entities.iteritems():
+        e = Entity()
+        f = Factory()
+
+        e.generate_entity(entity, actions)
+        f.generate_factory(entity, actions)
+
+        write(e, module='entity')
+        write(f, module='factory')
+
+if __name__ == '__main__':
+    entities = get_entity_action_map()
+    generate(entities)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8cdac504/tools/marvin/marvin/generate/entity.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/entity.py b/tools/marvin/marvin/generate/entity.py
new file mode 100644
index 0000000..76316ef
--- /dev/null
+++ b/tools/marvin/marvin/generate/entity.py
@@ -0,0 +1,166 @@
+# 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.
+
+
+class Entity(object):
+    """Defines a cloudstack entity and associated actions
+    """
+    def __init__(self):
+        self.name = None
+        self.classname = None
+        self.imports = []
+        self.methods = []
+        self.creator = None
+        self.enumerator = None
+        self.lines = []
+        self.tabspace = '    '
+        self.methods.append(self.update_method())
+
+    def __str__(self):
+        w = '\n'.join(self.imports)
+        w = w + '\n\n'
+        w = w + self.classname
+        w = w + '\n\n'
+        for m in self.methods:
+            if m.is_enumerator():
+                w = w + self.tabspace + '@classmethod'
+                w = w + '\n'
+            w = w + self.tabspace + m.signature
+            w = w + '\n'
+            for line in m.body:
+                w = w + self.tabspace + line
+                w = w + '\n'
+            w = w + '\n'
+        return w
+
+    def update_method(self):
+        """Defines the update builtin method on cloudstack entity
+        """
+        update = Method('__update__')
+        update.signature = 'def __update__(self, items):'
+        update.body = [self.tabspace + 'for key, value in items.iteritems():']
+        update.body.append(self.tabspace * 2 + 'setattr(self, key, value)')
+        update.body.append(self.tabspace + 'return self')
+        return  update
+
+    def generate_entity(self, entity, actions):
+        self.imports.append('from cloudstackentity import CloudStackEntity')
+        self.name = entity
+        self.classname = 'class %s(CloudStackEntity):' % entity
+        for action, details in actions.iteritems():
+            self.imports.append('from marvin.cloudstackAPI import %s' % details['apimodule'])
+            m = Method(action)
+            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(
+                details['optionals'])
+            if not m.is_creator():
+                # remove the id arg as id is the self (object) itself
+                no_id_args = filter(lambda arg: arg != 'id', details['args'])
+                if len(no_id_args) > 0: # at least one required non-id argument
+                    m.signature = 'def %s(self, apiclient, %s, **kwargs):'\
+                    % (action, ', '.join(list(set(no_id_args))))
+                else:
+                    m.signature = 'def %s(self, apiclient, **kwargs):' % (action)
+                m.body.append(self.tabspace + 'cmd = %(module)s.%(command)s()' % {"module": details["apimodule"],
+                                                                                 "command": details["apicmd"]})
+                if 'id' in details['args']:
+                    m.body.append(self.tabspace + 'cmd.id = self.id')
+                for arg in no_id_args:
+                    m.body.append(self.tabspace + 'cmd.%s = %s' % (arg, arg))
+                m.body.append(self.tabspace + '[setattr(cmd, key, value) for key, value in kwargs.iteritems()]')
+                m.body.append(self.tabspace + '%s = apiclient.%s(cmd)' % (entity.lower(), details['apimodule']))
+                if m.is_enumerator():
+                    m.body.append(self.tabspace +
+                                  'return map(lambda e: %s().__update__(e.__dict__), %s) '
+                                  'if %s and len(%s) > 0 else None' % (
+                                  entity, entity.lower(), entity.lower(), entity.lower()))
+                else:
+                    m.body.append(self.tabspace + 'return %s if %s else None' % (entity.lower(), entity.lower()))
+            else:
+                if len(details['args']) > 0: #has required arguments
+                    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=None, factory=None, **kwargs):' % action
+
+                m.body.append(self.tabspace + 'if not apiclient:')
+                m.body.append(self.tabspace * 2 + 'self.__update__(kwargs)')
+                m.body.append(self.tabspace*2 + 'return')
+
+                m.body.append(self.tabspace + 'cmd = %(module)s.%(command)s()' % {"module": details["apimodule"],
+                                                                               "command": details["apicmd"]})
+                m.body.append(self.tabspace + 'if factory:')
+                m.body.append(
+                    self.tabspace * 2 + '[setattr(cmd, factoryKey, factoryValue) for factoryKey, factoryValue in factory.__dict__.iteritems()]')
+                if len(details['args']) > 0: #has required arguments
+                    m.body.append(self.tabspace + 'else:')
+                    for arg in details['args']:
+                        m.body.append(self.tabspace * 2 + "cmd.%s = %s" % (arg, arg))
+                m.body.append(self.tabspace + '[setattr(cmd, key, value) for key, value in kwargs.iteritems()]')
+                m.body.append(self.tabspace + '%s = apiclient.%s(cmd)' % (entity.lower(), details['apimodule']))
+                m.body.append(
+                    self.tabspace + 'self.__update__(%s.__dict__) if %s else None' % (entity.lower(), entity.lower()))
+
+class Method(object):
+    """A method object defining action on an entity
+
+    - contains attributes, signature, docstring and body
+    """
+    def __init__(self, action):
+        self.action = action
+        self.docstring = None
+        self.signature = None
+        self.body = []
+
+    def is_creator(self):
+        """ Any action that results in the creation of the entity is an entity creator
+
+        eg: createNetwork, deployVirtualMachine or registerIso
+        @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'):
+            return True
+        return False
+
+    def is_enumerator(self):
+        """ Any action that lists existing entities is an entity enumerator
+
+        eg: listXxx APIs
+        @param action: action verb
+        @return: True if enumerator False otherwise
+        """
+        if self.action.startswith('list'):
+            return True
+        return False
+
+
+class Creator(Method):
+    """A creator method - typically one that creates the entity
+    """
+    def __init__(self):
+        self.decorators = ["@classmethod"]
+
+
+class Enumerator(Method):
+    """An enumerator method  - typically one that lists entities
+    """
+    def __init__(self):
+        self.decorators = ["@classmethod"]

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8cdac504/tools/marvin/marvin/generate/factory.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/factory.py b/tools/marvin/marvin/generate/factory.py
new file mode 100644
index 0000000..d31f916
--- /dev/null
+++ b/tools/marvin/marvin/generate/factory.py
@@ -0,0 +1,59 @@
+# 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.
+
+class Factory(object):
+    """Defines a cloudstack factory object
+    """
+    def __init__(self):
+        self.name = None
+        self.code = None
+
+    def __str__(self):
+        return self.code
+
+    def generate_factory(self, entity, actions):
+        """Data factories for each entity
+        """
+
+        tabspace = '    '
+        code = ''
+        factory_defaults = []
+        keys = actions.keys()
+        for key in keys:
+            if key.startswith('create'):
+                factory_defaults.extend(actions[key]['args'])
+            elif key.startswith('deploy'):
+                factory_defaults.extend(actions[key]['args'])
+            elif key.startswith('associate'):
+                factory_defaults.extend(actions[key]['args'])
+            elif key.startswith('register'):
+                factory_defaults.extend(actions[key]['args'])
+            else:
+                continue
+                #print '%s is not suitable for factory creation for entity %s' %(key, entity)
+
+        factory_defaults = set(factory_defaults)
+        code += 'from marvin.entity.%s import %s\n' % (entity.lower(), entity)
+        code += 'from factory import Factory'
+        code += '\n\n'
+        code += 'class %sFactory(Factory):' % entity
+        code += '\n\n'
+        code += tabspace + 'FACTORY_FOR = %s\n\n' % entity
+        for arg in factory_defaults:
+            code += tabspace + '%s = None\n' % arg
+        self.name = entity
+        self.code = code
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8cdac504/tools/marvin/marvin/generate/linguist.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/linguist.py b/tools/marvin/marvin/generate/linguist.py
new file mode 100644
index 0000000..82a7bfc
--- /dev/null
+++ b/tools/marvin/marvin/generate/linguist.py
@@ -0,0 +1,158 @@
+# 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.
+
+try:
+    import inflect
+except ImportError:
+    raise Exception("inflect installation not found. use pip install inflect to continue")
+from marvin.generate.verbs import grammar
+
+def singularize(word, num=0):
+    """Use the inflect engine to make singular nouns of the entities
+    @return: singular of `word`
+    """
+    inflector = inflect.engine()
+    return inflector.singular_noun(word)
+
+def transform_api(api):
+    """Brute-force transform for entities that don't match other transform rules
+    """
+    if api == 'ldapConfig':
+        return 'configure', 'Ldap'
+    elif api == 'ldapRemove':
+        return 'remove', 'Ldap'
+    elif api == 'login':
+        return 'login', 'CloudStack'
+    elif api == 'logout':
+        return 'logout', 'CloudStack'
+    return api, None
+
+def verb_adjust(api, entity):
+    """
+    Considers the prefix as the verb when no preposition transformers have been found in the API
+    Only if the entity is contained in the API string
+    """
+    index = api.lower().find(entity.lower())
+    if index > 0:
+        return api[:index]
+    else:
+        return api
+
+def entity_adjust(entity):
+    """
+    Some entities are managed within CloudStack where they don't bear any resemblance to the API.
+    Adjust such entities to a more sensible client side entity
+
+    #BUG: Inflect engine returns IpAddress => IpAddres as singular
+    """
+    if entity == 'IpAddres' or entity == 'IPAddres':
+        return 'IpAddress'
+    elif entity == 'SecurityGroupIngres':
+        return 'SecurityGroupIngress'
+    elif entity == 'SecurityGroupEgres':
+        return 'SecurityGroupEgress'
+    elif entity == 'GuestO':
+        return 'GuestOS'
+    elif entity == 'LBStickines':
+        return 'LBStickiness'
+    #CloudStack denotes VirtualRouter as DomainRouter
+    elif entity == 'DomainRouter':
+        return 'VirtualRouter'
+    #CloudStack denotes VirtualMachine as UserVm
+    elif entity == 'UserVm':
+        return 'VirtualMachine'
+    #CloudStack denotes aliased NIC (with IP) as NicSecondaryIp
+    elif entity == 'NicSecondaryIp':
+        return 'Nic'
+    elif entity == 'Site2SiteVpnConnection':
+        return 'VpnConnection'
+    elif entity == 'Site2SiteVpnGateway':
+        return 'VpnGateway'
+    elif entity == 'Site2SiteCustomerGateway':
+        return 'VpnCustomerGateway'
+    #Cloudstack returns Register entity for registerUserKeys
+    elif entity == 'Register':
+        return 'UserKeys'
+    #Cloudstack maintains Template/ISO/Volume as single Image type
+    #elif entity in ['Template', 'Volume']:
+    #    return 'Image'
+    #extractImage returns an Extract response but is a property of Image
+    elif entity == 'Extract':
+        return 'Template'
+    return entity
+
+def prepositon_transformer(preposition=None):
+    """Returns a transformer for the entity if it has a doXPrepositionY style API
+
+    @param entity: The entity eg: resetPasswordForVirtualMachine, preposition=For
+    @return: transformed entity, Y is the entity and doX is the verb, eg: VirtualMachine, resetPassword
+    """
+    def transform_api_with_preposition(api):
+        if api.find(preposition) > 0:
+            if api[api.find(preposition) + len(preposition)].isupper():
+                return api[:api.find(preposition)], api[api.find(preposition) + len(preposition):]
+        return api, None
+    return transform_api_with_preposition
+
+def skip_list():
+    """APIs that we will not auto-generate
+    """
+    return ['cleanVMReservationsCmd']
+
+def get_transformers():
+    """ List of transform rules as lambdas
+    """
+    transformers = [prepositon_transformer('Of'),
+                    prepositon_transformer('For'),
+                    prepositon_transformer('To'),
+                    prepositon_transformer('From'),
+                    prepositon_transformer('With'),
+                    transform_api]
+    return transformers
+
+def get_verb_and_entity(cmd):
+    """Break down the API cmd instance in to `verb` and `Entity`
+    @return: verb, Entity tuple
+    """
+    api = cmd.__class__.__name__
+    api = api.replace('Cmd', '')
+    #apply known list of transformations
+    matching_verbs = filter(lambda v: api.startswith(v), grammar)
+    if len(matching_verbs) > 0:
+        for transformer in get_transformers():
+            if transformer(api)[1]:
+                verb = transformer(api)[0]
+                if cmd.entity:
+                    entity = singularize(cmd.entity) if singularize(cmd.entity) else cmd.entity
+                else:
+                    entity = verb, \
+                                singularize(transformer(api)[1]) if singularize(transformer(api)[1]) else transformer(api)[1]
+                entity = entity_adjust(entity)
+                break
+        else:
+            verb = matching_verbs[0]
+            entity = api.replace(verb, '')
+            if cmd.entity:
+                entity = singularize(cmd.entity) if singularize(cmd.entity) else cmd.entity
+            else:
+                entity = singularize(entity) if singularize(entity) else entity
+            entity = entity_adjust(entity)
+            verb = verb_adjust(api, entity)
+        #print "%s => (verb, entity) = (%s, %s)" % (api, verb, entity)
+        return verb, entity
+    else:
+        print "No matching verb, entity breakdown for api %s" % api
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8cdac504/tools/marvin/marvin/generate/verbs.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/verbs.py b/tools/marvin/marvin/generate/verbs.py
new file mode 100644
index 0000000..2051f2d
--- /dev/null
+++ b/tools/marvin/marvin/generate/verbs.py
@@ -0,0 +1,27 @@
+# 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.
+
+grammar = ['create', 'list', 'delete', 'update', 'ldap', 'login', 'logout',
+           'enable', 'activate', 'disable', 'add', 'remove',
+           'attach', 'detach', 'associate', 'generate', 'assign',
+           'authorize', 'change', 'register', 'configure',
+           'start', 'restart', 'reboot', 'stop', 'reconnect',
+           'cancel', 'destroy', 'revoke', 'mark', 'reset',
+           'copy', 'extract', 'migrate', 'restore', 'suspend',
+           'get', 'query', 'prepare', 'deploy', 'upload', 'lock',
+           'disassociate', 'scale', 'dedicate', 'archive', 'find',
+           'recover', 'release', 'resize', 'revert', 'replace']

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8cdac504/tools/marvin/marvin/generate/xmltoapi.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/xmltoapi.py b/tools/marvin/marvin/generate/xmltoapi.py
new file mode 100644
index 0000000..22a2786
--- /dev/null
+++ b/tools/marvin/marvin/generate/xmltoapi.py
@@ -0,0 +1,488 @@
+# 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.
+
+import xml.dom.minidom
+import json
+import os
+import sys
+import urllib2
+from argparse import ArgumentParser
+from textwrap import dedent
+from os import path
+from marvin.generate.apitoentity import generate, get_entity_action_map
+
+class cmdParameterProperty(object):
+    def __init__(self):
+        self.name = None
+        self.required = False
+        self.entity = ""
+        self.desc = ""
+        self.type = "planObject"
+        self.subProperties = []
+
+
+class cloudStackCmd(object):
+    def __init__(self):
+        self.name = ""
+        self.desc = ""
+        self.async = "false"
+        self.entity = ""
+        self.request = []
+        self.response = []
+
+
+class codeGenerator(object):
+    """
+    Apache CloudStack- marvin python classes can be generated from the json
+    returned by API discovery or from the xml spec of commands generated by
+    the ApiDocWriter. This class provides helper methods for these uses.
+    """
+    space = '    '
+    newline = '\n'
+    cmdsName = []
+
+    def __init__(self, outputFolder):
+        self.cmd = None
+        self.code = ""
+        self.required = []
+        self.subclass = []
+        self.outputFolder = outputFolder
+        lic = """\
+          # 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.
+
+          """
+        self.license = dedent(lic)
+
+    def addAttribute(self, attr, pro):
+        value = pro.value
+        if pro.required:
+            self.required.append(attr)
+        desc = pro.desc
+        if desc is not None:
+            self.code += self.space
+            self.code += "''' " + pro.desc + " '''"
+            self.code += self.newline
+
+        self.code += self.space
+        self.code += attr + " = " + str(value)
+        self.code += self.newline
+
+    def generateSubClass(self, name, properties):
+        """Generate code for sub objects
+        """
+        subclass = 'class %s:\n'%name
+        subclass += self.space + "def __init__(self):\n"
+        for pro in properties:
+            if pro.desc is not None:
+                subclass += self.space + self.space + '""""%s"""\n' % pro.desc
+            if len(pro.subProperties) > 0:
+                subclass += self.space + self.space
+                subclass += 'self.%s = []\n' % pro.name
+                self.generateSubClass(pro.name, pro.subProperties)
+            else:
+                subclass += self.space + self.space
+                subclass += 'self.%s = None\n' % pro.name
+
+        self.subclass.append(subclass)
+
+    def generateApiCmd(self, cmd):
+        """Given an API cmd module generate the cloudstack cmd class in python
+        """
+        self.code = ""
+        self.subclass = []
+        self.cmd = cmd
+        self.cmdsName.append(self.cmd.name)
+        self.code = self.license
+        self.code += self.newline
+        self.code += '"""%s"""\n' % self.cmd.desc
+        self.code += 'from baseCmd import *\n'
+        self.code += 'from baseResponse import *\n'
+        self.code += "class %sCmd (baseCmd):\n" % self.cmd.name
+        self.code += self.space + "def __init__(self):\n"
+        self.code += self.space + self.space
+        self.code += 'self.isAsync = "%s"\n' % str(self.cmd.async).lower()
+        self.code += self.space*2 + 'self.entity = "%s"\n' % self.cmd.entity
+
+        for req in self.cmd.request:
+            if req.desc is not None:
+                self.code += self.space + self.space + '"""%s"""\n' % req.desc
+            if req.required:
+                self.code += self.space + self.space + '"""Required"""\n'
+
+            value = "None"
+            if req.type == "list" or req.type == "map":
+                value = "[]"
+
+            self.code += self.space + self.space
+            self.code += 'self.%s = %s\n' % (req.name, value)
+            if req.required:
+                self.required.append(req.name)
+
+        self.code += self.space + self.space + "self.required = ["
+        for require in self.required:
+            self.code += '"' + require + '",'
+        self.code += "]\n"
+        #print cmd.name, self.required
+        self.required = []
+
+        """generate response code"""
+        subItems = {}
+        self.code += self.newline
+        self.code += 'class %sResponse (baseResponse):\n' % self.cmd.name
+        self.code += self.space + "def __init__(self):\n"
+        if len(self.cmd.response) == 0:
+            self.code += self.space + self.space + "pass"
+        else:
+            for res in self.cmd.response:
+                if res.desc is not None:
+                    self.code += self.space + self.space
+                    self.code += '"""%s"""\n' % res.desc
+
+                if len(res.subProperties) > 0:
+                    self.code += self.space + self.space
+                    self.code += 'self.%s = []\n' % res.name
+                    self.generateSubClass(res.name, res.subProperties)
+                else:
+                    self.code += self.space + self.space
+                    self.code += 'self.%s = None\n' % res.name
+        self.code += self.newline
+
+        for subclass in self.subclass:
+            self.code += subclass + "\n"
+        return self.code
+
+    def write(self, out, modulename, code):
+        """
+        writes the generated code for `modulename` in the `out.cloudstackAPI` package
+        @param out: absolute path where all api cmds are written to
+        @param modulename: name of the module being written: eg: createNetwork
+        @param code: Generated code
+        @return: None
+        """
+        final_path = path.join(out, modulename)
+        module = final_path + '.py' #eg: out/cloudstackAPI/modulename.py
+        with open(module, "w") as fp:
+            fp.write(code)
+
+    def finalize(self):
+        """Generate an api call
+        """
+        header = '"""Marvin TestClient for CloudStack"""\n'
+        imports = "import copy\n"
+        initCmdsList = '__all__ = ['
+        body = ''
+        body += "class CloudStackAPIClient(object):\n"
+        body += self.space + 'def __init__(self, connection):\n'
+        body += self.space + self.space + 'self.connection = connection\n'
+        body += self.space + self.space + 'self._id = None\n'
+        body += self.newline
+
+        body += self.space + 'def __copy__(self):\n'
+        body += self.space + self.space
+        body += 'return CloudStackAPIClient(copy.copy(self.connection))\n'
+        body += self.newline
+
+        # The `id` property will be used to link the test with the cloud
+        # resource being created
+        #            @property
+        #            def id(self):
+        #                return self._id
+        #
+        #            @id.setter
+        #            def id(self, identifier):
+        #                self._id = identifier
+
+        body += self.space + '@property' + self.newline
+        body += self.space + 'def id(self):' + self.newline
+        body += self.space*2 + 'return self._id' + self.newline
+        body += self.newline
+
+        body += self.space + '@id.setter' + self.newline
+        body += self.space + 'def id(self, identifier):' + self.newline
+        body += self.space*2 + 'self._id = identifier' + self.newline
+        body += self.newline
+
+        for cmdName in self.cmdsName:
+            body += self.space
+            body += 'def %s(self, command, method="GET"):\n' % cmdName
+            body += self.space + self.space
+            body += 'response = %sResponse()\n' % cmdName
+            body += self.space + self.space
+            body += 'response = self.connection.marvin_request(command,'
+            body += ' response_type=response, method=method)\n'
+            body += self.space + self.space + 'return response\n'
+            body += self.newline
+
+            imports += 'from %s import %sResponse\n' % (cmdName, cmdName)
+            initCmdsList += '"%s",' % cmdName
+
+        cloudstackApiClient = self.license + header + imports + body
+        self.write(out=self.outputFolder, modulename='cloudstackAPIClient', code=cloudstackApiClient)
+
+        '''generate __init__.py'''
+        initCmdsList = self.license + initCmdsList + '"cloudstackAPIClient"]'
+        self.write(out=self.outputFolder, modulename='__init__', code=initCmdsList)
+
+        basecmd = self.license
+        basecmd += '"""Base Command"""\n'
+        basecmd += 'class baseCmd(object):\n'
+        basecmd += self.space + 'pass\n'
+        self.write(out=self.outputFolder, modulename='baseCmd', code=basecmd)
+
+        baseResponse = self.license
+        baseResponse += '"""Base Response"""\n'
+        baseResponse += 'class baseResponse:\n'
+        baseResponse += self.space + 'pass\n'
+        self.write(out=self.outputFolder, modulename='baseResponse', code=baseResponse)
+
+    def constructResponseFromXML(self, response):
+        paramProperty = cmdParameterProperty()
+        paramProperty.name = getText(response.getElementsByTagName('name'))
+        paramProperty.desc = getText(response.
+                                     getElementsByTagName('description'))
+        if paramProperty.name.find('(*)') != -1:
+            '''This is a list'''
+            paramProperty.name = paramProperty.name.split('(*)')[0]
+            argList = response.getElementsByTagName('arguments')[0].\
+                getElementsByTagName('arg')
+            for subresponse in argList:
+                subProperty = self.constructResponseFromXML(subresponse)
+                paramProperty.subProperties.append(subProperty)
+        return paramProperty
+
+    def loadCmdFromXML(self, dom):
+        cmds = []
+        for cmd in dom.getElementsByTagName("command"):
+            csCmd = cloudStackCmd()
+            csCmd.name = getText(cmd.getElementsByTagName('name'))
+            assert csCmd.name
+            if csCmd.name in ['login', 'logout']:
+                continue
+
+            csCmd.entity = getText(cmd.getElementsByTagName('entity'))
+            assert csCmd.entity
+
+            desc = getText(cmd.getElementsByTagName('description'))
+            if desc:
+                csCmd.desc = desc
+
+            async = getText(cmd.getElementsByTagName('isAsync'))
+            if async:
+                csCmd.async = async
+
+            argList = cmd.getElementsByTagName("request")[0].\
+                getElementsByTagName("arg")
+            for param in argList:
+                paramProperty = cmdParameterProperty()
+
+                paramProperty.name =\
+                    getText(param.getElementsByTagName('name'))
+                assert paramProperty.name
+
+                required = param.getElementsByTagName('required')
+                if getText(required) == "true":
+                    paramProperty.required = getText(required)
+
+                requestDescription = param.getElementsByTagName('description')
+                if requestDescription:
+                    paramProperty.desc = getText(requestDescription)
+
+                type = param.getElementsByTagName("type")
+                if type:
+                    paramProperty.type = getText(type)
+
+                csCmd.request.append(paramProperty)
+
+            responseEle = cmd.getElementsByTagName("response")[0]
+            for response in responseEle.getElementsByTagName("arg"):
+                if response.parentNode != responseEle:
+                    continue
+
+                paramProperty = self.constructResponseFromXML(response)
+                csCmd.response.append(paramProperty)
+
+            cmds.append(csCmd)
+        return cmds
+
+    def generateCodeFromXML(self, apiSpecFile):
+        dom = xml.dom.minidom.parse(apiSpecFile)
+        cmds = self.loadCmdFromXML(dom)
+        for cmd in cmds:
+            code = self.generateApiCmd(cmd)
+            self.write(out=self.outputFolder, modulename=cmd.name, code=code)
+        self.finalize()
+
+    def constructResponseFromJSON(self, response):
+        paramProperty = cmdParameterProperty()
+        if 'name' in response:
+            paramProperty.name = response['name']
+        assert paramProperty.name, "%s has no property name" % response
+
+        if 'description' in response:
+            paramProperty.desc = response['description']
+        if 'type' in response:
+            if response['type'] in ['list', 'map', 'set']:
+            #Here list becomes a subproperty
+                if 'response' in response:
+                    for innerResponse in response['response']:
+                        subProperty =\
+                            self.constructResponseFromJSON(innerResponse)
+                        paramProperty.subProperties.append(subProperty)
+            paramProperty.type = response['type']
+        return paramProperty
+
+    def loadCmdFromJSON(self, apiStream):
+        if apiStream is None:
+            raise Exception("No APIs found through discovery")
+
+        jsonOut = apiStream.readlines()
+        assert len(jsonOut) > 0
+        apiDict = json.loads(jsonOut[0])
+        if not 'listapisresponse' in apiDict:
+            raise Exception("API discovery plugin response failed")
+        if not 'count' in apiDict['listapisresponse']:
+            raise Exception("Malformed api response")
+
+        apilist = apiDict['listapisresponse']['api']
+        cmds = []
+        for cmd in apilist:
+            csCmd = cloudStackCmd()
+            if 'name' in cmd:
+                csCmd.name = cmd['name']
+            assert csCmd.name
+            if csCmd.name in ['login', 'logout']:
+                continue
+
+            if cmd.has_key('entity'):
+                csCmd.entity = cmd['entity']
+            else:
+                print csCmd.name + " has no entity"
+
+            if 'description' in cmd:
+                csCmd.desc = cmd['description']
+
+            if 'isasync' in cmd:
+                csCmd.async = cmd['isasync']
+
+            for param in cmd['params']:
+                paramProperty = cmdParameterProperty()
+
+                if 'name' in param:
+                    paramProperty.name = param['name']
+                assert paramProperty.name
+
+                if 'required' in param:
+                    paramProperty.required = param['required']
+
+                if 'description' in param:
+                    paramProperty.desc = param['description']
+
+                if 'type' in param:
+                    paramProperty.type = param['type']
+
+                csCmd.request.append(paramProperty)
+
+            for response in cmd['response']:
+            #FIXME: ExtractImage related APIs return empty dicts in response
+                if len(response) > 0:
+                    paramProperty = self.constructResponseFromJSON(response)
+                    csCmd.response.append(paramProperty)
+
+            cmds.append(csCmd)
+        return cmds
+
+    def generateCodeFromJSON(self, endpointUrl):
+        """
+        Api Discovery plugin returns the supported APIs of a CloudStack
+        endpoint.
+        @return: The classes in cloudstackAPI/ formed from api discovery json
+        """
+        if endpointUrl.find('response=json') >= 0:
+            apiStream = urllib2.urlopen(endpointUrl)
+            cmds = self.loadCmdFromJSON(apiStream)
+            for cmd in cmds:
+                code = self.generateApiCmd(cmd)
+                self.write(out=self.outputFolder, modulename=cmd.name, code=code)
+            self.finalize()
+
+
+def getText(elements):
+    return elements[0].childNodes[0].nodeValue.strip()
+
+if __name__ == "__main__":
+    parser = ArgumentParser()
+    parser.add_argument("-o", "--output", dest="output",
+                      help="The path to the generated code entities, default\
+ is .")
+    parser.add_argument("-s", "--specfile", dest="spec",
+                      help="The path and name of the api spec xml file,\
+ default is /etc/cloud/cli/commands.xml")
+    parser.add_argument("-e", "--endpoint", dest="endpoint",
+                      help="The endpoint mgmt server (with open 8096) where\
+ apis are discovered, default is localhost")
+    parser.add_argument("-y", "--entity", dest="entity", action="store_true",
+                      help="Generate entity based classes")
+
+    options = parser.parse_args()
+
+    folder = "."
+    if options.output is not None:
+        folder = options.output
+    apiModule = folder + "/cloudstackAPI"
+    if not os.path.exists(apiModule):
+        try:
+            os.mkdir(apiModule)
+        except:
+            print "Failed to create folder %s, due to %s" % (apiModule,
+                                                             sys.exc_info())
+            print parser.print_help()
+            exit(2)
+
+    apiSpecFile = "/etc/cloud/cli/commands.xml"
+    if options.spec is not None:
+        apiSpecFile = options.spec
+        if not os.path.exists(apiSpecFile):
+            print "the spec file %s does not exists" % apiSpecFile
+            print parser.print_help()
+            exit(1)
+
+    cg = codeGenerator(apiModule)
+    if options.spec is not None:
+        cg.generateCodeFromXML(apiSpecFile)
+    elif options.endpoint is not None:
+        endpointUrl = 'http://%s:8096/client/api?command=listApis&\
+response=json' % options.endpoint
+        cg.generateCodeFromJSON(endpointUrl)
+
+    if options.entity:
+        entities = get_entity_action_map()
+        generate(entities, "entity")


[29/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: update the object during non-create transforms

When an entity is updated/ the object attributes should be updated.
Previously we only updated the attributes when creating the entity.

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/5eebce19
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/5eebce19
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/5eebce19

Branch: refs/heads/marvin-refactor
Commit: 5eebce194d2c77d09c0e8c4a3885f6d4217bf614
Parents: 5055acd
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Fri Sep 13 15:57:05 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:48 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/generate/entity.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5eebce19/tools/marvin/marvin/generate/entity.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/entity.py b/tools/marvin/marvin/generate/entity.py
index dc96a14..b9f825b 100644
--- a/tools/marvin/marvin/generate/entity.py
+++ b/tools/marvin/marvin/generate/entity.py
@@ -90,7 +90,7 @@ class Entity(object):
                                   'if %s and len(%s) > 0 else None' % (
                                   entity, entity.lower(), entity.lower(), entity.lower()))
                 else:
-                    m.body.append(self.tabspace + 'return %s if %s else None' % (entity.lower(), entity.lower()))
+                    m.body.append(self.tabspace + 'return self.__update__(%s.__dict__) if %s else None' % (entity.lower(), entity.lower()))
             else:
                 if len(details['args']) > 0: #has required arguments
                     m.signature = 'def __init__(self, apiclient=None, %s, factory=None, **kwargs):' % (


[31/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: include an example with should-dsl

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/c640a328
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/c640a328
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/c640a328

Branch: refs/heads/marvin-refactor
Commit: c640a328d55f5a19d737585a74df5c11cfc8477f
Parents: 1b82d7c
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Fri Sep 13 15:58:33 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:51 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/test/test_factories.py | 110 +++++++++++++-----------
 1 file changed, 62 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c640a328/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 81e78a7..c2c823c 100644
--- a/tools/marvin/marvin/test/test_factories.py
+++ b/tools/marvin/marvin/test/test_factories.py
@@ -18,6 +18,7 @@
 import unittest
 import logging
 from nose.plugins.attrib import attr
+from should_dsl import should, should_not
 
 from marvin.cloudstackTestClient import cloudstackTestClient
 
@@ -31,16 +32,15 @@ from marvin.factory.data.network import *
 from marvin.factory.virtualmachine import *
 
 from marvin.entity.serviceoffering import ServiceOffering
+from marvin.entity.networkoffering import NetworkOffering
 from marvin.entity.zone import Zone
 from marvin.entity.account import Account
 from marvin.entity.template import Template
 from marvin.entity.user import User
 from marvin.entity.network import Network
-
 from marvin.entity.ipaddress import IpAddress
 
 
-
 class BuildVsCreateStrategyTest(unittest.TestCase):
     def setUp(self):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
@@ -115,6 +115,65 @@ class NetworkOfferingFactoryTest(unittest.TestCase):
         pass
 
 
+class UserFactorySubFactoryTest(unittest.TestCase):
+    def setUp(self):
+        self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
+
+    def tearDown(self):
+        pass
+
+    @unittest.skip("This is a chicken and egg problem")
+    def test_userSubFactory(self):
+        """
+        Skip because users are contained in accounts but
+        cannot be created until accounts exist
+
+        A subfactory is unsuitable as the semantics of the
+        caller is not to create the user before creating the account
+        @return:
+        """
+        uf = UserFactory(apiclient=self.apiClient)
+        user = User.list(apiclient=self.apiClient, username=uf.username)
+        self.assert_(uf.username == user[0].username, msg="Usernames don't match")
+
+
+class NetworkFactoryTest(unittest.TestCase):
+    def setUp(self):
+        self.apiClient = cloudstackTestClient(mgtSvr='localhost',
+            logging=logging.getLogger('factory.cloudstack')).getApiClient()
+
+    def tearDown(self):
+        self.accnt.delete(apiclient=self.apiClient)
+
+    @attr(tags='network')
+    def test_isolatedGuestNetwork(self):
+        """Test to create a network within a guest account
+        @return:
+        """
+        self.accnt = UserAccountFactory(apiclient=self.apiClient)
+        zones = Zone.list(apiclient=self.apiClient)
+        network = GuestIsolatedNetworkFactory(
+            apiclient=self.apiClient,
+            zoneid=zones[0].id
+            )
+        logging.getLogger('factory.cloudstack').debug("network created with id %s, name %s" %(network.id, network.name))
+
+
+class NetworkOfferingFactoryWithMultiplePostHooksTest(unittest.TestCase):
+    def setUp(self):
+        self.apiClient = cloudstackTestClient(mgtSvr='localhost',
+            logging=logging.getLogger('factory.cloudstack')).getApiClient()
+
+    @attr(tags='post')
+    def test_multiplePostHooksNetworkOffering(self):
+        sharedOffering = DefaultSharedNetworkOfferingFactory(apiclient=self.apiClient)
+        sharedOffering |should| be_instance_of(NetworkOffering)
+        sharedOffering |should_not| equal_to(None)
+        sharedOffering.state |should| equal_to('Enabled')
+        logging.getLogger('factory.cloudstack').debug("networkoffering created with id %s, name %s, state %s"
+                                                      %(sharedOffering.id, sharedOffering.name, sharedOffering.state))
+
+
 class VirtualMachineFactoryTest(unittest.TestCase):
     def setUp(self):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
@@ -139,29 +198,6 @@ class VirtualMachineFactoryTest(unittest.TestCase):
                                           domainid = accnt.domainid)
 
 
-
-class UserFactorySubFactoryTest(unittest.TestCase):
-    def setUp(self):
-        self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
-
-    def tearDown(self):
-        pass
-
-    @unittest.skip("This is a chicken and egg problem")
-    def test_userSubFactory(self):
-        """
-        Skip because users are contained in accounts but
-        cannot be created until accounts exist
-
-        A subfactory is unsuitable as the semantics of the
-        caller is not to create the user before creating the account
-        @return:
-        """
-        uf = UserFactory(apiclient=self.apiClient)
-        user = User.list(apiclient=self.apiClient, username=uf.username)
-        self.assert_(uf.username == user[0].username, msg="Usernames don't match")
-
-
 class IpAddressFactoryTest(unittest.TestCase):
     def setUp(self):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost',
@@ -192,26 +228,4 @@ 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)
-
-
-class NetworkFactoryTest(unittest.TestCase):
-    def setUp(self):
-        self.apiClient = cloudstackTestClient(mgtSvr='localhost',
-            logging=logging.getLogger('factory.cloudstack')).getApiClient()
-
-    def tearDown(self):
-        self.accnt.delete(apiclient=self.apiClient)
-
-    @attr(tags='network')
-    def test_isolatedGuestNetwork(self):
-        """Test to create a network within a guest account
-        @return:
-        """
-        self.accnt = UserAccountFactory(apiclient=self.apiClient)
-        zones = Zone.list(apiclient=self.apiClient)
-        network = GuestIsolatedNetworkFactory(
-            apiclient=self.apiClient,
-            zoneid=zones[0].id
-            )
-        logging.getLogger('factory.cloudstack').debug("network created with id %s, name %s" %(network.id, network.name))
\ No newline at end of file
+        firstip.associate(apiclient=self.apiClient, networkid = networks[0].id)
\ No newline at end of file


[50/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: setup/teardown per test for the vpc lifecycle test

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/bbaf3546
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/bbaf3546
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/bbaf3546

Branch: refs/heads/marvin-refactor
Commit: bbaf354689dad7dae737438996277783c03c48bf
Parents: 167e5f6
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Oct 2 20:17:40 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:19 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/test/test_vpc_life_cycle.py | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bbaf3546/tools/marvin/marvin/test/test_vpc_life_cycle.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/test/test_vpc_life_cycle.py b/tools/marvin/marvin/test/test_vpc_life_cycle.py
index d247673..8dbc797 100644
--- a/tools/marvin/marvin/test/test_vpc_life_cycle.py
+++ b/tools/marvin/marvin/test/test_vpc_life_cycle.py
@@ -25,14 +25,13 @@ from nose.plugins.attrib import attr
 
 class TestVpcLifeCycle(cloudstackTestCase):
 
-    @classmethod
-    def setUpClass(cls):
-        cls.apiclient = super(TestVpcLifeCycle, cls).getClsTestClient().getApiClient()
-        cls.zoneid = get_zone(cls.apiclient).id
-        cls.templateid = get_template(cls.apiclient).id,
-        cls.serviceofferingid = get_service_offering(cls.apiclient).id,
-        cls.account = UserAccount(
-            apiclient=cls.apiclient
+    def setUp(self):
+        self.apiclient = super(TestVpcLifeCycle, self).getClsTestClient().getApiClient()
+        self.zoneid = get_zone(self.apiclient).id
+        self.templateid = get_template(self.apiclient).id
+        self.serviceofferingid = get_service_offering(self.apiclient).id
+        self.account = UserAccount(
+            apiclient=self.apiclient
         )
 
     @attr(tags='debug')
@@ -96,6 +95,5 @@ class TestVpcLifeCycle(cloudstackTestCase):
         vm.destroy()
         vm.state | should | equal_to('Destroyed')
 
-    @classmethod
-    def tearDownClass(cls):
-        cls.account.delete()
\ No newline at end of file
+    def tearDown(self):
+        self.account.delete()
\ No newline at end of file


[24/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: remove the newly generated sources

- in factory and entity
- MUST NOT remove factory.data

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/e58cd115
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/e58cd115
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/e58cd115

Branch: refs/heads/marvin-refactor
Commit: e58cd115797da8b7114b3a972ed4c0ec0e61c9ed
Parents: 7085916
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Tue Sep 10 14:01:08 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:40 2013 +0530

----------------------------------------------------------------------
 tools/marvin/pom.xml | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e58cd115/tools/marvin/pom.xml
----------------------------------------------------------------------
diff --git a/tools/marvin/pom.xml b/tools/marvin/pom.xml
index 25909b3..9876122 100644
--- a/tools/marvin/pom.xml
+++ b/tools/marvin/pom.xml
@@ -34,7 +34,11 @@
             <configuration>
               <target>
                 <delete dir="marvin/cloudstackAPI" />
-                <echo>Deleting ${project.artifactId} API sources</echo>
+                <delete>
+                  <fileset dir="marvin/factory/" includes="*.py" />
+                  <fileset dir="marvin/entity/" includes="*.py" />
+                </delete>
+                <echo>Deleting generated ${project.artifactId} sources</echo>
               </target>
             </configuration>
           </execution>


[15/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin-refactor: move the deployment helpers to deployer module

deployer module will contain all the helper modules used for json
description of data center and will also feature the export module for
exporting a datacenter in to json

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/ff8dfe1c
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/ff8dfe1c
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/ff8dfe1c

Branch: refs/heads/marvin-refactor
Commit: ff8dfe1cb5ca1b69a903239e2f453d5975e9ece1
Parents: 79a1591
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Sat Sep 7 10:55:12 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:23 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/configGenerator.py          | 870 -------------------
 tools/marvin/marvin/deployDataCenter.py         | 625 -------------
 tools/marvin/marvin/deployer/__init__.py        |  16 +
 tools/marvin/marvin/deployer/configGenerator.py | 870 +++++++++++++++++++
 .../marvin/marvin/deployer/deployDataCenter.py  | 625 +++++++++++++
 5 files changed, 1511 insertions(+), 1495 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ff8dfe1c/tools/marvin/marvin/configGenerator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/configGenerator.py b/tools/marvin/marvin/configGenerator.py
deleted file mode 100644
index a966ae0..0000000
--- a/tools/marvin/marvin/configGenerator.py
+++ /dev/null
@@ -1,870 +0,0 @@
-# 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.
-
-import json
-import os
-from optparse import OptionParser
-import jsonHelper
-
-
-class managementServer(object):
-    def __init__(self):
-        self.mgtSvrIp = None
-        self.port = 8096
-        self.apiKey = None
-        self.securityKey = None
-
-
-class dbServer(object):
-    def __init__(self):
-        self.dbSvr = None
-        self.port = 3306
-        self.user = "cloud"
-        self.passwd = "cloud"
-        self.db = "cloud"
-
-
-class configuration(object):
-    def __init__(self):
-        self.name = None
-        self.value = None
-
-
-class logger(object):
-    def __init__(self):
-        '''TestCase/TestClient'''
-        self.name = None
-        self.file = None
-
-
-class cloudstackConfiguration(object):
-    def __init__(self):
-        self.zones = []
-        self.mgtSvr = []
-        self.dbSvr = None
-        self.globalConfig = []
-        self.logger = []
-
-
-class zone(object):
-    def __init__(self):
-        self.dns1 = None
-        self.internaldns1 = None
-        self.name = None
-        '''Basic or Advanced'''
-        self.networktype = None
-        self.dns2 = None
-        self.internaldns2 = None
-        self.securitygroupenabled = None
-        self.localstorageenabled = None
-        '''default public network, in advanced mode'''
-        self.ipranges = []
-        self.physical_networks = []
-        self.pods = []
-        self.secondaryStorages = []
-        self.cacheStorages = []
-
-
-class traffictype(object):
-    def __init__(self, typ, labeldict=None):
-        self.typ = typ  # Guest/Management/Public
-        if labeldict:
-            self.xen = labeldict['xen'] if 'xen' in labeldict.keys() else None
-            self.kvm = labeldict['kvm'] if 'kvm' in labeldict.keys() else None
-            self.vmware = labeldict['vmware']\
-                if 'vmware' in labeldict.keys() else None
-            self.simulator = labeldict['simulator']\
-                if 'simulator' in labeldict.keys() else None
-        #{
-        #    'xen' : 'cloud-xen',
-        #    'kvm' : 'cloud-kvm',
-        #    'vmware' : 'cloud-vmware'
-        #}
-
-
-class pod(object):
-    def __init__(self):
-        self.gateway = None
-        self.name = None
-        self.netmask = None
-        self.startip = None
-        self.endip = None
-        self.zoneid = None
-        self.clusters = []
-        self.vmwaredc = []
-        '''Used in basic network mode'''
-        self.guestIpRanges = []
-
-
-class VmwareDc(object):
-    def __init__(self):
-        self.zoneid = None
-        self.name = None
-        self.vcenter = None
-        self.username = None
-        self.password = None
-
-
-class cluster(object):
-    def __init__(self):
-        self.clustername = None
-        self.clustertype = None
-        self.hypervisor = None
-        self.zoneid = None
-        self.podid = None
-        self.password = None
-        self.url = None
-        self.username = None
-        self.hosts = []
-        self.primaryStorages = []
-
-
-class host(object):
-    def __init__(self):
-        self.hypervisor = None
-        self.password = None
-        self.url = None
-        self.username = None
-        self.zoneid = None
-        self.podid = None
-        self.clusterid = None
-        self.clustername = None
-        self.cpunumber = None
-        self.cpuspeed = None
-        self.hostmac = None
-        self.hosttags = None
-        self.memory = None
-
-
-class physical_network(object):
-    def __init__(self):
-        self.name = None
-        self.tags = []
-        self.traffictypes = []
-        self.broadcastdomainrange = 'Zone'
-        self.vlan = None
-        self.isolationmethods = []
-        '''enable default virtual router provider'''
-        vrouter = provider()
-        vrouter.name = 'VirtualRouter'
-        self.providers = [vrouter]
-
-
-class provider(object):
-    def __init__(self, name=None):
-        self.name = name
-        self.state = None
-        self.broadcastdomainrange = 'ZONE'
-        self.zoneid = None
-        self.servicelist = []
-        self.devices = []
-
-
-class network(object):
-    def __init__(self):
-        self.displaytext = None
-        self.name = None
-        self.zoneid = None
-        self.acltype = None
-        self.domainid = None
-        self.networkdomain = None
-        self.networkofferingid = None
-        self.ipranges = []
-
-
-class iprange(object):
-    def __init__(self):
-        '''tagged/untagged'''
-        self.gateway = None
-        self.netmask = None
-        self.startip = None
-        self.endip = None
-        self.vlan = None
-        '''for account specific '''
-        self.account = None
-        self.domain = None
-
-
-class primaryStorage(object):
-    def __init__(self):
-        self.name = None
-        self.url = None
-
-
-class secondaryStorage(object):
-    def __init__(self):
-        self.url = None
-        self.provider = None
-        self.details = None
-
-
-class cacheStorage(object):
-    def __init__(self):
-        self.url = None
-        self.provider = None
-        self.details = None
-
-
-class s3(object):
-    def __init__(self):
-        self.accesskey = None
-        self.secretkey = None
-        self.bucket = None
-        self.endpoint = None
-        self.sockettimeout = None
-        self.connectiontimeout = None
-        self.maxerrorrety = None
-        self.usehttps = None
-
-
-class netscaler(object):
-    def __init__(self, hostname=None, username='nsroot', password='nsroot'):
-        self.hostname = hostname
-        self.username = username
-        self.password = password
-        self.networkdevicetype = 'NetscalerVPXLoadBalancer'
-        self.publicinterface = '1/1'
-        self.privateinterface = '1/1'
-        self.numretries = '2'
-        self.lbdevicecapacity = '50'
-        self.lbdevicededicated = 'false'
-
-    def getUrl(self):
-        return repr(self)
-
-    def __repr__(self):
-        req = zip(self.__dict__.keys(), self.__dict__.values())
-        return self.hostname+"?" + "&".join(["=".join([r[0], r[1]])
-                                             for r in req])
-
-
-class srx(object):
-    def __init__(self, hostname=None, username='root', password='admin'):
-        self.hostname = hostname
-        self.username = username
-        self.password = password
-        self.networkdevicetype = 'JuniperSRXFirewall'
-        self.publicinterface = '1/1'
-        self.privateinterface = '1/1'
-        self.numretries = '2'
-        self.fwdevicededicated = 'false'
-        self.timeout = '300'
-        self.publicnetwork = 'untrusted'
-        self.privatenetwork = 'trusted'
-
-    def getUrl(self):
-        return repr(self)
-
-    def __repr__(self):
-        req = zip(self.__dict__.keys(), self.__dict__.values())
-        return self.hostname+"?" + "&".join(["=".join([r[0], r[1]])
-                                             for r in req])
-
-
-class bigip(object):
-    def __init__(self, hostname=None, username='root', password='default'):
-        self.hostname = hostname
-        self.username = username
-        self.password = password
-        self.networkdevicetype = 'F5BigIpLoadBalancer'
-        self.publicinterface = '1/1'
-        self.privateinterface = '1/1'
-        self.numretries = '2'
-        self.lbdevicededicated = 'false'
-        self.lbdevicecapacity = '50'
-
-    def getUrl(self):
-        return repr(self)
-
-    def __repr__(self):
-        req = zip(self.__dict__.keys(), self.__dict__.values())
-        return self.hostname+"?" + "&".join(["=".join([r[0], r[1]])
-                                             for r in req])
-
-
-def getDeviceUrl(obj):
-    req = zip(obj.__dict__.keys(), obj.__dict__.values())
-    if obj.hostname:
-        return "http://" + obj.hostname+"?" + "&".join(["=".join([r[0],
-                                                                  r[1]])
-                                                        for r in req])
-    else:
-        return None
-
-
-def describe_setup_in_basic_mode():
-    '''sample code to generate setup configuration file'''
-    zs = cloudstackConfiguration()
-
-    for l in range(1):
-        z = zone()
-        z.dns1 = "8.8.8.8"
-        z.dns2 = "8.8.4.4"
-        z.internaldns1 = "192.168.110.254"
-        z.internaldns2 = "192.168.110.253"
-        z.name = "test"+str(l)
-        z.networktype = 'Basic'
-        z.securitygroupenabled = 'True'
-
-        #If security groups are reqd
-        sgprovider = provider()
-        sgprovider.broadcastdomainrange = 'Pod'
-        sgprovider.name = 'SecurityGroupProvider'
-
-        pn = physical_network()
-        pn.name = "test-network"
-        pn.traffictypes = [traffictype("Guest"), traffictype("Management")]
-        pn.providers.append(sgprovider)
-
-        z.physical_networks.append(pn)
-
-        '''create 10 pods'''
-        for i in range(2):
-            p = pod()
-            p.name = "test" + str(l) + str(i)
-            p.gateway = "192.168.%d.1" % i
-            p.netmask = "255.255.255.0"
-            p.startip = "192.168.%d.150" % i
-            p.endip = "192.168.%d.220" % i
-
-            '''add two pod guest ip ranges'''
-            for j in range(2):
-                ip = iprange()
-                ip.gateway = p.gateway
-                ip.netmask = p.netmask
-                ip.startip = "192.168.%d.%d" % (i, j*20)
-                ip.endip = "192.168.%d.%d" % (i, j*20+10)
-
-                p.guestIpRanges.append(ip)
-
-            '''add 10 clusters'''
-            for j in range(2):
-                c = cluster()
-                c.clustername = "test"+str(l)+str(i) + str(j)
-                c.clustertype = "CloudManaged"
-                c.hypervisor = "Simulator"
-
-                '''add 10 hosts'''
-                for k in range(2):
-                    h = host()
-                    h.username = "root"
-                    h.password = "password"
-                    memory = 8*1024*1024*1024
-                    localstorage = 1*1024*1024*1024*1024
-                    h.url = "http://sim/%d%d%d%d" % (l, i, j, k)
-                    c.hosts.append(h)
-
-                '''add 2 primary storages'''
-                for m in range(2):
-                    primary = primaryStorage()
-                    primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
-                    primary.url = "nfs://localhost/path%s" % (str(l) + str(i) +
-                                                              str(j) + str(m))
-                    c.primaryStorages.append(primary)
-
-                p.clusters.append(c)
-
-            z.pods.append(p)
-
-        '''add two secondary'''
-        for i in range(5):
-            secondary = secondaryStorage()
-            secondary.url = "nfs://localhost/path"+str(l) + str(i)
-            z.secondaryStorages.append(secondary)
-
-        zs.zones.append(z)
-
-    '''Add one mgt server'''
-    mgt = managementServer()
-    mgt.mgtSvrIp = "localhost"
-    zs.mgtSvr.append(mgt)
-
-    '''Add a database'''
-    db = dbServer()
-    db.dbSvr = "localhost"
-
-    zs.dbSvr = db
-
-    '''add global configuration'''
-    global_settings = {'expunge.delay': '60',
-                       'expunge.interval': '60',
-                       'expunge.workers': '3',
-                       }
-    for k, v in global_settings.iteritems():
-        cfg = configuration()
-        cfg.name = k
-        cfg.value = v
-        zs.globalConfig.append(cfg)
-
-    ''''add loggers'''
-    testClientLogger = logger()
-    testClientLogger.name = "TestClient"
-    testClientLogger.file = "/tmp/testclient.log"
-
-    testCaseLogger = logger()
-    testCaseLogger.name = "TestCase"
-    testCaseLogger.file = "/tmp/testcase.log"
-
-    zs.logger.append(testClientLogger)
-    zs.logger.append(testCaseLogger)
-
-    return zs
-
-
-def describe_setup_in_eip_mode():
-    """
-    Setting up an EIP/ELB enabled zone with netscaler provider
-    """
-    zs = cloudstackConfiguration()
-
-    for l in range(1):
-        z = zone()
-        z.dns1 = "8.8.8.8"
-        z.dns2 = "8.8.4.4"
-        z.internaldns1 = "192.168.110.254"
-        z.internaldns2 = "192.168.110.253"
-        z.name = "test"+str(l)
-        z.networktype = 'Basic'
-
-        ips = iprange()
-        ips.vlan = "49"
-        ips.startip = "10.147.49.200"
-        ips.endip = "10.147.49.250"
-        ips.gateway = "10.147.49.1"
-        ips.netmask = "255.255.255.0"
-        z.ipranges.append(ips)
-
-        #If security groups are reqd
-        sgprovider = provider()
-        sgprovider.broadcastdomainrange = 'Pod'
-        sgprovider.name = 'SecurityGroupProvider'
-
-        nsprovider = provider()
-        nsprovider.name = 'Netscaler'
-        ns = netscaler()
-        ns.hostname = '10.147.40.100'
-        nsprovider.devices.append(ns)
-
-        pn = physical_network()
-        pn.name = "test-network"
-        pn.traffictypes = [traffictype("Guest",
-                                       {"xen": "cloud-guest"}),
-                           traffictype("Management"),
-                           traffictype("Public", {"xen": "cloud-public"})]
-        pn.providers.extend([sgprovider, nsprovider])
-        z.physical_networks.append(pn)
-
-        '''create 10 pods'''
-        for i in range(2):
-            p = pod()
-            p.name = "test" + str(l) + str(i)
-            p.gateway = "192.168.%d.1" % i
-            p.netmask = "255.255.255.0"
-            p.startip = "192.168.%d.150" % i
-            p.endip = "192.168.%d.220" % i
-
-            '''add two pod guest ip ranges'''
-            for j in range(2):
-                ip = iprange()
-                ip.gateway = p.gateway
-                ip.netmask = p.netmask
-                ip.startip = "192.168.%d.%d" % (i, j*20)
-                ip.endip = "192.168.%d.%d" % (i, j*20+10)
-
-                p.guestIpRanges.append(ip)
-
-            '''add 10 clusters'''
-            for j in range(2):
-                c = cluster()
-                c.clustername = "test"+str(l)+str(i) + str(j)
-                c.clustertype = "CloudManaged"
-                c.hypervisor = "Simulator"
-
-                '''add 10 hosts'''
-                for k in range(2):
-                    h = host()
-                    h.username = "root"
-                    h.password = "password"
-                    h.url = "http://Sim/%d%d%d%d" % (l, i, j, k)
-                    c.hosts.append(h)
-
-                '''add 2 primary storages'''
-                for m in range(2):
-                    primary = primaryStorage()
-                    primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
-                    primary.url = "nfs://localhost/path%s" % (str(l) + str(i)
-                                                              + str(j)
-                                                              + str(m))
-                    c.primaryStorages.append(primary)
-
-                p.clusters.append(c)
-
-            z.pods.append(p)
-
-        '''add two secondary'''
-        for i in range(5):
-            secondary = secondaryStorage()
-            secondary.url = "nfs://localhost/path"+str(l) + str(i)
-            z.secondaryStorages.append(secondary)
-
-        zs.zones.append(z)
-
-    '''Add one mgt server'''
-    mgt = managementServer()
-    mgt.mgtSvrIp = "localhost"
-    zs.mgtSvr.append(mgt)
-
-    '''Add a database'''
-    db = dbServer()
-    db.dbSvr = "localhost"
-
-    zs.dbSvr = db
-
-    '''add global configuration'''
-    global_settings = {'expunge.delay': '60',
-                       'expunge.interval': '60',
-                       'expunge.workers': '3',
-                       }
-    for k, v in global_settings.iteritems():
-        cfg = configuration()
-        cfg.name = k
-        cfg.value = v
-        zs.globalConfig.append(cfg)
-
-    ''''add loggers'''
-    testClientLogger = logger()
-    testClientLogger.name = "TestClient"
-    testClientLogger.file = "/tmp/testclient.log"
-
-    testCaseLogger = logger()
-    testCaseLogger.name = "TestCase"
-    testCaseLogger.file = "/tmp/testcase.log"
-
-    zs.logger.append(testClientLogger)
-    zs.logger.append(testCaseLogger)
-
-    return zs
-
-
-def describe_setup_in_advanced_mode():
-    '''sample code to generate setup configuration file'''
-    zs = cloudstackConfiguration()
-
-    for l in range(1):
-        z = zone()
-        z.dns1 = "8.8.8.8"
-        z.dns2 = "8.8.4.4"
-        z.internaldns1 = "192.168.110.254"
-        z.internaldns2 = "192.168.110.253"
-        z.name = "test"+str(l)
-        z.networktype = 'Advanced'
-        z.guestcidraddress = "10.1.1.0/24"
-        z.vlan = "100-2000"
-
-        pn = physical_network()
-        pn.name = "test-network"
-        pn.traffictypes = [traffictype("Guest"), traffictype("Management"),
-                           traffictype("Public")]
-
-        vpcprovider = provider('VpcVirtualRouter')
-
-        nsprovider = provider('Netscaler')
-        nsprovider.devices.append(netscaler(hostname='10.147.40.100'))
-
-        srxprovider = provider('JuniperSRX')
-        srxprovider.devices.append(srx(hostname='10.147.40.3'))
-
-        f5provider = provider('F5BigIp')
-        f5provider.devices.append(bigip(hostname='10.147.40.3'))
-
-        pn.providers.extend([vpcprovider, nsprovider, srxprovider, f5provider])
-        z.physical_networks.append(pn)
-
-        '''create 10 pods'''
-        for i in range(2):
-            p = pod()
-            p.name = "test" + str(l) + str(i)
-            p.gateway = "192.168.%d.1" % i
-            p.netmask = "255.255.255.0"
-            p.startip = "192.168.%d.200" % i
-            p.endip = "192.168.%d.220" % i
-
-            '''add 10 clusters'''
-            for j in range(2):
-                c = cluster()
-                c.clustername = "test"+str(l)+str(i) + str(j)
-                c.clustertype = "CloudManaged"
-                c.hypervisor = "Simulator"
-
-                '''add 10 hosts'''
-                for k in range(2):
-                    h = host()
-                    h.username = "root"
-                    h.password = "password"
-                    memory = 8 * 1024 * 1024 * 1024
-                    localstorage = 1 * 1024 * 1024 * 1024 * 1024
-                    #h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\
-                    #    memory=%d&localstorage=%d"%(l, i, j, k, memory,
-                    #                                localstorage)
-                    h.url = "http://sim/%d%d%d%d" % (l, i, j, k)
-                    c.hosts.append(h)
-
-                '''add 2 primary storages'''
-                for m in range(2):
-                    primary = primaryStorage()
-                    primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
-                    #primary.url = "nfs://localhost/path%s/size=%d" %
-                    #    (str(l) + str(i) + str(j) + str(m), size)
-                    primary.url = "nfs://localhost/path%s" % (str(l) + str(i)
-                                                              + str(j)
-                                                              + str(m))
-                    c.primaryStorages.append(primary)
-
-                p.clusters.append(c)
-
-            z.pods.append(p)
-
-        '''add two secondary'''
-        for i in range(5):
-            secondary = secondaryStorage()
-            secondary.url = "nfs://localhost/path"+str(l) + str(i)
-            z.secondaryStorages.append(secondary)
-
-        '''add default public network'''
-        ips = iprange()
-        ips.vlan = "26"
-        ips.startip = "172.16.26.2"
-        ips.endip = "172.16.26.100"
-        ips.gateway = "172.16.26.1"
-        ips.netmask = "255.255.255.0"
-        z.ipranges.append(ips)
-
-        zs.zones.append(z)
-
-    '''Add one mgt server'''
-    mgt = managementServer()
-    mgt.mgtSvrIp = "localhost"
-    zs.mgtSvr.append(mgt)
-
-    '''Add a database'''
-    db = dbServer()
-    db.dbSvr = "localhost"
-
-    zs.dbSvr = db
-
-    '''add global configuration'''
-    global_settings = {'expunge.delay': '60',
-                       'expunge.interval': '60',
-                       'expunge.workers': '3',
-                       }
-    for k, v in global_settings.iteritems():
-        cfg = configuration()
-        cfg.name = k
-        cfg.value = v
-        zs.globalConfig.append(cfg)
-
-    ''''add loggers'''
-    testClientLogger = logger()
-    testClientLogger.name = "TestClient"
-    testClientLogger.file = "/tmp/testclient.log"
-
-    testCaseLogger = logger()
-    testCaseLogger.name = "TestCase"
-    testCaseLogger.file = "/tmp/testcase.log"
-
-    zs.logger.append(testClientLogger)
-    zs.logger.append(testCaseLogger)
-
-    return zs
-
-'''sample code to generate setup configuration file'''
-
-
-def describe_setup_in_advancedsg_mode():
-    zs = cloudstackConfiguration()
-
-    for l in range(1):
-        z = zone()
-        z.dns1 = "8.8.8.8"
-        z.dns2 = "8.8.4.4"
-        z.internaldns1 = "192.168.110.254"
-        z.internaldns2 = "192.168.110.253"
-        z.name = "test"+str(l)
-        z.networktype = 'Advanced'
-        z.vlan = "100-2000"
-        z.securitygroupenabled = "true"
-
-        pn = physical_network()
-        pn.name = "test-network"
-        pn.traffictypes = [traffictype("Guest"), traffictype("Management")]
-
-        #If security groups are reqd
-        sgprovider = provider()
-        sgprovider.broadcastdomainrange = 'ZONE'
-        sgprovider.name = 'SecurityGroupProvider'
-
-        pn.providers.append(sgprovider)
-        z.physical_networks.append(pn)
-
-        '''create 10 pods'''
-        for i in range(2):
-            p = pod()
-            p.name = "test" + str(l) + str(i)
-            p.gateway = "192.168.%d.1" % i
-            p.netmask = "255.255.255.0"
-            p.startip = "192.168.%d.200" % i
-            p.endip = "192.168.%d.220" % i
-
-            '''add 10 clusters'''
-            for j in range(2):
-                c = cluster()
-                c.clustername = "test"+str(l)+str(i) + str(j)
-                c.clustertype = "CloudManaged"
-                c.hypervisor = "Simulator"
-
-                '''add 10 hosts'''
-                for k in range(2):
-                    h = host()
-                    h.username = "root"
-                    h.password = "password"
-                    memory = 8 * 1024 * 1024 * 1024
-                    localstorage = 1 * 1024 * 1024 * 1024 * 1024
-                    #h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\
-                        #memory=%d&localstorage=%d" % (l, i, j, k, memory,
-                        #localstorage)
-                    h.url = "http://sim/%d%d%d%d" % (l, i, j, k)
-                    c.hosts.append(h)
-
-                '''add 2 primary storages'''
-                for m in range(2):
-                    primary = primaryStorage()
-                    primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
-                    #primary.url = "nfs://localhost/path%s/size=%d" % \
-                        #(str(l) + str(i) + str(j) + str(m), size)
-                    primary.url = "nfs://localhost/path%s" % \
-                        (str(l) + str(i) + str(j) + str(m))
-                    c.primaryStorages.append(primary)
-
-                p.clusters.append(c)
-
-            z.pods.append(p)
-
-        '''add two secondary'''
-        for i in range(5):
-            secondary = secondaryStorage()
-            secondary.url = "nfs://localhost/path"+str(l) + str(i)
-            z.secondaryStorages.append(secondary)
-
-        '''add default guest network'''
-        ips = iprange()
-        ips.vlan = "26"
-        ips.startip = "172.16.26.2"
-        ips.endip = "172.16.26.100"
-        ips.gateway = "172.16.26.1"
-        ips.netmask = "255.255.255.0"
-        z.ipranges.append(ips)
-
-        zs.zones.append(z)
-
-    '''Add one mgt server'''
-    mgt = managementServer()
-    mgt.mgtSvrIp = "localhost"
-    zs.mgtSvr.append(mgt)
-
-    '''Add a database'''
-    db = dbServer()
-    db.dbSvr = "localhost"
-
-    zs.dbSvr = db
-
-    '''add global configuration'''
-    global_settings = {'expunge.delay': '60',
-                       'expunge.interval': '60',
-                       'expunge.workers': '3',
-                       }
-    for k, v in global_settings.iteritems():
-        cfg = configuration()
-        cfg.name = k
-        cfg.value = v
-        zs.globalConfig.append(cfg)
-
-    ''''add loggers'''
-    testClientLogger = logger()
-    testClientLogger.name = "TestClient"
-    testClientLogger.file = "/tmp/testclient.log"
-
-    testCaseLogger = logger()
-    testCaseLogger.name = "TestCase"
-    testCaseLogger.file = "/tmp/testcase.log"
-
-    zs.logger.append(testClientLogger)
-    zs.logger.append(testCaseLogger)
-
-    return zs
-
-
-def generate_setup_config(config, file=None):
-    describe = config
-    if file is None:
-        return json.dumps(jsonHelper.jsonDump.dump(describe))
-    else:
-        fp = open(file, 'w')
-        json.dump(jsonHelper.jsonDump.dump(describe), fp, indent=4)
-        fp.close()
-
-
-def get_setup_config(file):
-    if not os.path.exists(file):
-        raise IOError("config file %s not found. \
-please specify a valid config file" % file)
-    config = cloudstackConfiguration()
-    configLines = []
-    with open(file, 'r') as fp:
-        for line in fp:
-            ws = line.strip()
-            if not ws.startswith("#"):
-                configLines.append(ws)
-    config = json.loads("\n".join(configLines))
-    return jsonHelper.jsonLoader(config)
-
-if __name__ == "__main__":
-    parser = OptionParser()
-
-    parser.add_option("-i", "--input", action="store", default=None,
-                      dest="inputfile", help="input file")
-    parser.add_option("-a", "--advanced", action="store_true", default=False,
-                      dest="advanced", help="use advanced networking")
-    parser.add_option("-s", "--advancedsg", action="store_true", default=False,
-                      dest="advancedsg", help="use advanced networking \
-with security groups")
-    parser.add_option("-o", "--output", action="store",
-                      default="./datacenterCfg", dest="output",
-                      help="the path where the json config file generated, \
-by default is ./datacenterCfg")
-
-    (options, args) = parser.parse_args()
-
-    if options.inputfile:
-        config = get_setup_config(options.inputfile)
-    if options.advanced:
-        config = describe_setup_in_advanced_mode()
-    elif options.advancedsg:
-        config = describe_setup_in_advancedsg_mode()
-    else:
-        config = describe_setup_in_basic_mode()
-
-    generate_setup_config(config, options.output)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ff8dfe1c/tools/marvin/marvin/deployDataCenter.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py
deleted file mode 100644
index 8cc9cd4..0000000
--- a/tools/marvin/marvin/deployDataCenter.py
+++ /dev/null
@@ -1,625 +0,0 @@
-# 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.
-
-"""Deploy datacenters according to a json configuration file"""
-import configGenerator
-import cloudstackException
-import cloudstackTestClient
-import logging
-from cloudstackAPI import *
-from os import path
-from time import sleep
-from optparse import OptionParser
-
-
-class deployDataCenters(object):
-
-    def __init__(self, cfgFile):
-        if not path.exists(cfgFile) \
-           and not path.exists(path.abspath(cfgFile)):
-            raise IOError("config file %s not found. please \
-specify a valid config file" % cfgFile)
-        self.configFile = cfgFile
-
-    def addHosts(self, hosts, zoneId, podId, clusterId, hypervisor):
-        if hosts is None:
-            return
-        for host in hosts:
-            hostcmd = addHost.addHostCmd()
-            hostcmd.clusterid = clusterId
-            hostcmd.cpunumber = host.cpunumer
-            hostcmd.cpuspeed = host.cpuspeed
-            hostcmd.hostmac = host.hostmac
-            hostcmd.hosttags = host.hosttags
-            hostcmd.hypervisor = host.hypervisor
-            hostcmd.memory = host.memory
-            hostcmd.password = host.password
-            hostcmd.podid = podId
-            hostcmd.url = host.url
-            hostcmd.username = host.username
-            hostcmd.zoneid = zoneId
-            hostcmd.hypervisor = hypervisor
-            self.apiClient.addHost(hostcmd)
-
-    def addVmWareDataCenter(self, vmwareDc):
-        vdc = addVmwareDc.addVmwareDcCmd()
-        vdc.zoneid = vmwareDc.zoneid
-        vdc.name = vmwareDc.name
-        vdc.vcenter = vmwareDc.vcenter
-        vdc.username = vmwareDc.username
-        vdc.password = vmwareDc.password
-        self.apiClient.addVmwareDc(vdc)
-
-    def createClusters(self, clusters, zoneId, podId, vmwareDc=None):
-        if clusters is None:
-            return
-
-        if vmwareDc is not None:
-            vmwareDc.zoneid = zoneId
-            self.addVmWareDataCenter(vmwareDc)
-
-        for cluster in clusters:
-            clustercmd = addCluster.addClusterCmd()
-            clustercmd.clustername = cluster.clustername
-            clustercmd.clustertype = cluster.clustertype
-            clustercmd.hypervisor = cluster.hypervisor
-            clustercmd.password = cluster.password
-            clustercmd.podid = podId
-            clustercmd.url = cluster.url
-            clustercmd.username = cluster.username
-            clustercmd.zoneid = zoneId
-            clusterresponse = self.apiClient.addCluster(clustercmd)
-            clusterId = clusterresponse[0].id
-
-            if cluster.hypervisor.lower() != "vmware":
-                self.addHosts(cluster.hosts, zoneId, podId, clusterId,
-                              cluster.hypervisor)
-            self.wait_for_host(zoneId, clusterId)
-            self.createPrimaryStorages(cluster.primaryStorages, zoneId, podId,
-                                       clusterId)
-
-    def wait_for_host(self, zoneId, clusterId):
-        """
-        Wait for the hosts in the zoneid, clusterid to be up
-
-        2 retries with 30s delay
-        """
-        retry, timeout = 2, 30
-        cmd = listHosts.listHostsCmd()
-        cmd.clusterid, cmd.zoneid = clusterId, zoneId
-        hosts = self.apiClient.listHosts(cmd)
-        while retry != 0:
-            for host in hosts:
-                if host.state != 'Up':
-                    break
-            sleep(timeout)
-            retry = retry - 1
-
-    def createPrimaryStorages(self, primaryStorages, zoneId, podId, clusterId):
-        if primaryStorages is None:
-            return
-        for primary in primaryStorages:
-            primarycmd = createStoragePool.createStoragePoolCmd()
-            primarycmd.details = primary.details
-            primarycmd.name = primary.name
-            primarycmd.podid = podId
-            primarycmd.tags = primary.tags
-            primarycmd.url = primary.url
-            primarycmd.zoneid = zoneId
-            primarycmd.clusterid = clusterId
-            self.apiClient.createStoragePool(primarycmd)
-
-    def createpods(self, pods, zoneId, networkId=None):
-        if pods is None:
-            return
-        for pod in pods:
-            createpod = createPod.createPodCmd()
-            createpod.name = pod.name
-            createpod.gateway = pod.gateway
-            createpod.netmask = pod.netmask
-            createpod.startip = pod.startip
-            createpod.endip = pod.endip
-            createpod.zoneid = zoneId
-            createpodResponse = self.apiClient.createPod(createpod)
-            podId = createpodResponse.id
-
-            if pod.guestIpRanges is not None and networkId is not None:
-                self.createVlanIpRanges("Basic", pod.guestIpRanges, zoneId,
-                                        podId, networkId)
-
-            self.createClusters(pod.clusters, zoneId, podId,
-                                vmwareDc=pod.vmwaredc)
-
-    def createVlanIpRanges(self, mode, ipranges, zoneId, podId=None,
-                           networkId=None, forvirtualnetwork=None):
-        if ipranges is None:
-            return
-        for iprange in ipranges:
-            vlanipcmd = createVlanIpRange.createVlanIpRangeCmd()
-            vlanipcmd.account = iprange.account
-            vlanipcmd.domainid = iprange.domainid
-            vlanipcmd.endip = iprange.endip
-            vlanipcmd.gateway = iprange.gateway
-            vlanipcmd.netmask = iprange.netmask
-            vlanipcmd.networkid = networkId
-            vlanipcmd.podid = podId
-            vlanipcmd.startip = iprange.startip
-            vlanipcmd.zoneid = zoneId
-            vlanipcmd.vlan = iprange.vlan
-            if mode == "Basic":
-                if forvirtualnetwork:
-                    vlanipcmd.forvirtualnetwork = "true"
-                else:
-                    vlanipcmd.forvirtualnetwork = "false"
-            else:
-                vlanipcmd.forvirtualnetwork = "true"
-            self.apiClient.createVlanIpRange(vlanipcmd)
-
-    def createSecondaryStorages(self, secondaryStorages, zoneId):
-        if secondaryStorages is None:
-            return
-        for secondary in secondaryStorages:
-            secondarycmd = addImageStore.addImageStoreCmd()
-            secondarycmd.url = secondary.url
-            secondarycmd.provider = secondary.provider
-            secondarycmd.details = []
-
-            if secondarycmd.provider == 'S3' \
-                    or secondarycmd.provider == "Swift":
-                for key, value in vars(secondary.details).iteritems():
-                    secondarycmd.details.append({
-                                                'key': key,
-                                                'value': value
-                                                })
-            if secondarycmd.provider == "NFS":
-                secondarycmd.zoneid = zoneId
-            self.apiClient.addImageStore(secondarycmd)
-
-    def createCacheStorages(self, cacheStorages, zoneId):
-        if cacheStorages is None:
-            return
-        for cache in cacheStorages:
-            cachecmd = createSecondaryStagingStore.\
-                createSecondaryStagingStoreCmd()
-            cachecmd.url = cache.url
-            cachecmd.provider = cache.provider
-            cachecmd.zoneid = zoneId
-            cachecmd.details = []
-
-            if cache.details:
-                for key, value in vars(cache.details).iteritems():
-                    cachecmd.details.append({
-                                            'key': key,
-                                            'value': value
-                                            })
-            self.apiClient.createSecondaryStagingStore(cachecmd)
-
-    def createnetworks(self, networks, zoneId):
-        if networks is None:
-            return
-        for network in networks:
-            networkcmd = createNetwork.createNetworkCmd()
-            networkcmd.displaytext = network.displaytext
-            networkcmd.name = network.name
-            networkcmd.networkofferingid = network.networkofferingid
-            networkcmd.zoneid = zoneId
-
-            ipranges = network.ipranges
-            if ipranges:
-                iprange = ipranges.pop()
-                networkcmd.startip = iprange.startip
-                networkcmd.endip = iprange.endip
-                networkcmd.gateway = iprange.gateway
-                networkcmd.netmask = iprange.netmask
-
-            networkcmdresponse = self.apiClient.createNetwork(networkcmd)
-            networkId = networkcmdresponse.id
-            return networkId
-
-    def createPhysicalNetwork(self, net, zoneid):
-        phynet = createPhysicalNetwork.createPhysicalNetworkCmd()
-        phynet.zoneid = zoneid
-        phynet.name = net.name
-        phynet.isolationmethods = net.isolationmethods
-        phynetwrk = self.apiClient.createPhysicalNetwork(phynet)
-        self.addTrafficTypes(phynetwrk.id, net.traffictypes)
-        return phynetwrk
-
-    def updatePhysicalNetwork(self, networkid, state="Enabled", vlan=None):
-        upnet = updatePhysicalNetwork.updatePhysicalNetworkCmd()
-        upnet.id = networkid
-        upnet.state = state
-        if vlan:
-            upnet.vlan = vlan
-        return self.apiClient.updatePhysicalNetwork(upnet)
-
-    def enableProvider(self, provider_id):
-        upnetprov =\
-            updateNetworkServiceProvider.updateNetworkServiceProviderCmd()
-        upnetprov.id = provider_id
-        upnetprov.state = "Enabled"
-        self.apiClient.updateNetworkServiceProvider(upnetprov)
-
-    def configureProviders(self, phynetwrk, providers):
-        """
-        We will enable the virtualrouter elements for all zones. Other
-        providers like NetScalers, SRX, etc are explicitly added/configured
-        """
-
-        for provider in providers:
-            pnetprov = listNetworkServiceProviders.\
-                listNetworkServiceProvidersCmd()
-            pnetprov.physicalnetworkid = phynetwrk.id
-            pnetprov.state = "Disabled"
-            pnetprov.name = provider.name
-            pnetprovres = self.apiClient.listNetworkServiceProviders(pnetprov)
-
-            if pnetprovres and len(pnetprovres) > 0:
-                if provider.name == 'VirtualRouter'\
-                   or provider.name == 'VpcVirtualRouter':
-                    vrprov = listVirtualRouterElements.\
-                        listVirtualRouterElementsCmd()
-                    vrprov.nspid = pnetprovres[0].id
-                    vrprovresponse = self.apiClient.\
-                        listVirtualRouterElements(vrprov)
-                    vrprovid = vrprovresponse[0].id
-
-                    vrconfig = \
-                        configureVirtualRouterElement.\
-                        configureVirtualRouterElementCmd()
-                    vrconfig.enabled = "true"
-                    vrconfig.id = vrprovid
-                    self.apiClient.configureVirtualRouterElement(vrconfig)
-                    self.enableProvider(pnetprovres[0].id)
-                elif provider.name == 'InternalLbVm':
-                    internallbprov = listInternalLoadBalancerElements.\
-                        listInternalLoadBalancerElementsCmd()
-                    internallbprov.nspid = pnetprovres[0].id
-                    internallbresponse = self.apiClient.\
-                        listInternalLoadBalancerElements(internallbprov)
-                    internallbid = internallbresponse[0].id
-
-                    internallbconfig = \
-                        configureInternalLoadBalancerElement.\
-                        configureInternalLoadBalancerElementCmd()
-                    internallbconfig.enabled = "true"
-                    internallbconfig.id = internallbid
-                    self.apiClient.\
-                        configureInternalLoadBalancerElement(internallbconfig)
-                    self.enableProvider(pnetprovres[0].id)
-                elif provider.name == 'SecurityGroupProvider':
-                    self.enableProvider(pnetprovres[0].id)
-            elif provider.name in ['Netscaler', 'JuniperSRX', 'F5BigIp']:
-                netprov = addNetworkServiceProvider.\
-                    addNetworkServiceProviderCmd()
-                netprov.name = provider.name
-                netprov.physicalnetworkid = phynetwrk.id
-                result = self.apiClient.addNetworkServiceProvider(netprov)
-                for device in provider.devices:
-                    if provider.name == 'Netscaler':
-                        dev = addNetscalerLoadBalancer.\
-                            addNetscalerLoadBalancerCmd()
-                        dev.username = device.username
-                        dev.password = device.password
-                        dev.networkdevicetype = device.networkdevicetype
-                        dev.url = configGenerator.getDeviceUrl(device)
-                        dev.physicalnetworkid = phynetwrk.id
-                        self.apiClient.addNetscalerLoadBalancer(dev)
-                    elif provider.name == 'JuniperSRX':
-                        dev = addSrxFirewall.addSrxFirewallCmd()
-                        dev.username = device.username
-                        dev.password = device.password
-                        dev.networkdevicetype = device.networkdevicetype
-                        dev.url = configGenerator.getDeviceUrl(device)
-                        dev.physicalnetworkid = phynetwrk.id
-                        self.apiClient.addSrxFirewall(dev)
-                    elif provider.name == 'F5BigIp':
-                        dev = addF5LoadBalancer.addF5LoadBalancerCmd()
-                        dev.username = device.username
-                        dev.password = device.password
-                        dev.networkdevicetype = device.networkdevicetype
-                        dev.url = configGenerator.getDeviceUrl(device)
-                        dev.physicalnetworkid = phynetwrk.id
-                        self.apiClient.addF5LoadBalancer(dev)
-                    else:
-                        raise cloudstackException.\
-                            InvalidParameterException("Device %s doesn't match\
- any know provider type" % device)
-                self.enableProvider(result.id)
-
-    def addTrafficTypes(self, physical_network_id, traffictypes):
-        [self.addTrafficType(physical_network_id, traffic_type)
-            for traffic_type in traffictypes]
-
-    def addTrafficType(self, physical_network_id, traffictype):
-        traffic_type = addTrafficType.addTrafficTypeCmd()
-        traffic_type.physicalnetworkid = physical_network_id
-        traffic_type.traffictype = traffictype.typ
-        traffic_type.kvmnetworklabel = traffictype.kvm\
-            if traffictype.kvm is not None else None
-        traffic_type.xennetworklabel = traffictype.xen\
-            if traffictype.xen is not None else None
-        traffic_type.vmwarenetworklabel = traffictype.vmware\
-            if traffictype.vmware is not None else None
-        traffic_type.simulatorlabel = traffictype.simulator\
-            if traffictype.simulator is not None else None
-        return self.apiClient.addTrafficType(traffic_type)
-
-    def enableZone(self, zoneid, allocation_state="Enabled"):
-        zoneCmd = updateZone.updateZoneCmd()
-        zoneCmd.id = zoneid
-        zoneCmd.allocationstate = allocation_state
-        return self.apiClient.updateZone(zoneCmd)
-
-    def updateZoneDetails(self, zoneid, details):
-        zoneCmd = updateZone.updateZoneCmd()
-        zoneCmd.id = zoneid
-        zoneCmd.details = details
-        return self.apiClient.updateZone(zoneCmd)
-
-    def createZones(self, zones):
-        for zone in zones:
-            createzone = createZone.createZoneCmd()
-            createzone.dns1 = zone.dns1
-            createzone.dns2 = zone.dns2
-            createzone.internaldns1 = zone.internaldns1
-            createzone.internaldns2 = zone.internaldns2
-            createzone.name = zone.name
-            createzone.securitygroupenabled = zone.securitygroupenabled
-            createzone.localstorageenabled = zone.localstorageenabled
-            createzone.networktype = zone.networktype
-            if zone.securitygroupenabled != "true":
-                createzone.guestcidraddress = zone.guestcidraddress
-
-            zoneresponse = self.apiClient.createZone(createzone)
-            zoneId = zoneresponse.id
-
-            for pnet in zone.physical_networks:
-                phynetwrk = self.createPhysicalNetwork(pnet, zoneId)
-                self.configureProviders(phynetwrk, pnet.providers)
-                self.updatePhysicalNetwork(phynetwrk.id, "Enabled",
-                                           vlan=pnet.vlan)
-
-            if zone.networktype == "Basic":
-                listnetworkoffering =\
-                    listNetworkOfferings.listNetworkOfferingsCmd()
-                listnetworkoffering.name =\
-                    "DefaultSharedNetscalerEIPandELBNetworkOffering" \
-                    if len(filter(lambda x:
-                                  x.typ == 'Public',
-                                  zone.physical_networks[0].
-                                  traffictypes)) > 0 \
-                    else "DefaultSharedNetworkOfferingWithSGService"
-                if zone.networkofferingname is not None:
-                    listnetworkoffering.name = zone.networkofferingname
-
-                listnetworkofferingresponse = \
-                    self.apiClient.listNetworkOfferings(listnetworkoffering)
-
-                guestntwrk = configGenerator.network()
-                guestntwrk.displaytext = "guestNetworkForBasicZone"
-                guestntwrk.name = "guestNetworkForBasicZone"
-                guestntwrk.zoneid = zoneId
-                guestntwrk.networkofferingid = \
-                    listnetworkofferingresponse[0].id
-
-                networkid = self.createnetworks([guestntwrk], zoneId)
-                self.createpods(zone.pods, zoneId, networkid)
-                if self.isEipElbZone(zone):
-                    self.createVlanIpRanges(zone.networktype, zone.ipranges,
-                                            zoneId, forvirtualnetwork=True)
-
-            isPureAdvancedZone = (zone.networktype == "Advanced"
-                                  and zone.securitygroupenabled != "true")
-            if isPureAdvancedZone:
-                self.createpods(zone.pods, zoneId)
-                self.createVlanIpRanges(zone.networktype, zone.ipranges,
-                                        zoneId)
-            elif (zone.networktype == "Advanced"
-                  and zone.securitygroupenabled == "true"):
-                listnetworkoffering =\
-                    listNetworkOfferings.listNetworkOfferingsCmd()
-                listnetworkoffering.name =\
-                    "DefaultSharedNetworkOfferingWithSGService"
-                if zone.networkofferingname is not None:
-                    listnetworkoffering.name = zone.networkofferingname
-
-                listnetworkofferingresponse = \
-                    self.apiClient.listNetworkOfferings(listnetworkoffering)
-
-                networkcmd = createNetwork.createNetworkCmd()
-                networkcmd.displaytext = "Shared SG enabled network"
-                networkcmd.name = "Shared SG enabled network"
-                networkcmd.networkofferingid =\
-                    listnetworkofferingresponse[0].id
-                networkcmd.zoneid = zoneId
-
-                ipranges = zone.ipranges
-                if ipranges:
-                    iprange = ipranges.pop()
-                    networkcmd.startip = iprange.startip
-                    networkcmd.endip = iprange.endip
-                    networkcmd.gateway = iprange.gateway
-                    networkcmd.netmask = iprange.netmask
-                    networkcmd.vlan = iprange.vlan
-
-                networkcmdresponse = self.apiClient.createNetwork(networkcmd)
-                networkId = networkcmdresponse.id
-                self.createpods(zone.pods, zoneId, networkId)
-
-            '''Note: Swift needs cache storage first'''
-            self.createCacheStorages(zone.cacheStorages, zoneId)
-            self.createSecondaryStorages(zone.secondaryStorages, zoneId)
-
-            enabled = getattr(zone, 'enabled', 'True')
-            if enabled == 'True' or enabled is None:
-                self.enableZone(zoneId, "Enabled")
-            details = getattr(zone, 'details')
-            if details is not None:
-                det = [d.__dict__ for d in details]
-                self.updateZoneDetails(zoneId, det)
-
-        return
-
-    def isEipElbZone(self, zone):
-        if (zone.networktype == "Basic"
-            and len(filter(lambda x: x.typ == 'Public',
-                           zone.physical_networks[0].traffictypes)) > 0):
-            return True
-        return False
-
-    def registerApiKey(self):
-        listuser = listUsers.listUsersCmd()
-        listuser.account = "admin"
-        listuserRes = self.testClient.getApiClient().listUsers(listuser)
-        userId = listuserRes[0].id
-        apiKey = listuserRes[0].apikey
-        securityKey = listuserRes[0].secretkey
-        if apiKey is None:
-            registerUser = registerUserKeys.registerUserKeysCmd()
-            registerUser.id = userId
-            registerUserRes = \
-                self.testClient.getApiClient().registerUserKeys(registerUser)
-
-            apiKey = registerUserRes.apikey
-            securityKey = registerUserRes.secretkey
-
-        self.config.mgtSvr[0].port = 8080
-        self.config.mgtSvr[0].apiKey = apiKey
-        self.config.mgtSvr[0].securityKey = securityKey
-        return apiKey, securityKey
-
-    def getCfg(self):
-        if self.config is not None:
-            return self.config
-        return None
-
-    def loadCfg(self):
-        try:
-            self.config = configGenerator.get_setup_config(self.configFile)
-        except:
-            raise cloudstackException.InvalidParameterException(
-                "Failed to load config %s" % self.configFile)
-
-        mgt = self.config.mgtSvr[0]
-
-        loggers = self.config.logger
-        testClientLogFile = None
-        self.testCaseLogFile = None
-        self.testResultLogFile = None
-        if loggers is not None and len(loggers) > 0:
-            for log in loggers:
-                if log.name == "TestClient":
-                    testClientLogFile = log.file
-                elif log.name == "TestCase":
-                    self.testCaseLogFile = log.file
-                elif log.name == "TestResult":
-                    self.testResultLogFile = log.file
-
-        testClientLogger = None
-        if testClientLogFile is not None:
-            testClientLogger = logging.getLogger("testclient.testengine.run")
-            fh = logging.FileHandler(testClientLogFile)
-            fh.setFormatter(logging.
-                            Formatter("%(asctime)s - %(levelname)s - %(name)s\
- - %(message)s"))
-            testClientLogger.addHandler(fh)
-            testClientLogger.setLevel(logging.INFO)
-        self.testClientLogger = testClientLogger
-
-        self.testClient = \
-            cloudstackTestClient.\
-            cloudstackTestClient(mgt.mgtSvrIp, mgt.port, mgt.user, mgt.passwd,
-                                 mgt.apiKey, mgt.securityKey,
-                                 logging=self.testClientLogger)
-        if mgt.apiKey is None:
-            apiKey, securityKey = self.registerApiKey()
-            self.testClient = cloudstackTestClient.cloudstackTestClient(
-                mgt.mgtSvrIp, 8080,
-                mgt.user, mgt.passwd,
-                apiKey, securityKey,
-                logging=self.testClientLogger)
-
-        """config database"""
-        dbSvr = self.config.dbSvr
-        if dbSvr is not None:
-            self.testClient.dbConfigure(dbSvr.dbSvr, dbSvr.port, dbSvr.user,
-                                        dbSvr.passwd, dbSvr.db)
-
-        self.apiClient = self.testClient.getApiClient()
-        """set hypervisor"""
-        if mgt.hypervisor:
-            self.apiClient.hypervisor = mgt.hypervisor
-        else:
-            self.apiClient.hypervisor = "XenServer"  # Defaults to Xenserver
-
-    def updateConfiguration(self, globalCfg):
-        if globalCfg is None:
-            return None
-
-        for config in globalCfg:
-            updateCfg = updateConfiguration.updateConfigurationCmd()
-            updateCfg.name = config.name
-            updateCfg.value = config.value
-            self.apiClient.updateConfiguration(updateCfg)
-
-    def copyAttributesToCommand(self, source, command):
-
-        map(lambda attr: setattr(command, attr, getattr(source, attr, None)),
-            filter(lambda attr: not attr.startswith("__") and
-            attr not in ["required", "isAsync"], dir(command)))
-
-    def configureS3(self, s3):
-        if s3 is None:
-            return
-
-        command = addS3.addS3Cmd()
-        self.copyAttributesToCommand(s3, command)
-        self.apiClient.addS3(command)
-
-    def deploy(self):
-        self.loadCfg()
-        self.updateConfiguration(self.config.globalConfig)
-        self.createZones(self.config.zones)
-        self.configureS3(self.config.s3)
-
-if __name__ == "__main__":
-
-    parser = OptionParser()
-
-    parser.add_option("-i", "--input", action="store",
-                      default="./datacenterCfg", dest="input", help="the path \
-                      where the json config file generated, by default is \
-                      ./datacenterCfg")
-
-    (options, args) = parser.parse_args()
-
-    deploy = deployDataCenters(options.input)
-    deploy.deploy()
-
-    """
-    create = createStoragePool.createStoragePoolCmd()
-    create.clusterid = 1
-    create.podid = 2
-    create.name = "fdffdf"
-    create.url = "nfs://jfkdjf/fdkjfkd"
-    create.zoneid = 2
-
-    deploy = deployDataCenters("./datacenterCfg")
-    deploy.loadCfg()
-    deploy.apiClient.createStoragePool(create)
-    """

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ff8dfe1c/tools/marvin/marvin/deployer/__init__.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployer/__init__.py b/tools/marvin/marvin/deployer/__init__.py
new file mode 100644
index 0000000..d216be4
--- /dev/null
+++ b/tools/marvin/marvin/deployer/__init__.py
@@ -0,0 +1,16 @@
+# 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.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ff8dfe1c/tools/marvin/marvin/deployer/configGenerator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployer/configGenerator.py b/tools/marvin/marvin/deployer/configGenerator.py
new file mode 100644
index 0000000..3f20dfd
--- /dev/null
+++ b/tools/marvin/marvin/deployer/configGenerator.py
@@ -0,0 +1,870 @@
+# 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.
+
+import json
+import os
+from optparse import OptionParser
+import jsonHelper
+
+
+class managementServer(object):
+    def __init__(self):
+        self.mgtSvrIp = None
+        self.port = 8096
+        self.apiKey = None
+        self.securityKey = None
+
+
+class dbServer(object):
+    def __init__(self):
+        self.dbSvr = None
+        self.port = 3306
+        self.user = "cloud"
+        self.passwd = "cloud"
+        self.db = "cloud"
+
+
+class configuration(object):
+    def __init__(self):
+        self.name = None
+        self.value = None
+
+
+class logger(object):
+    def __init__(self):
+        '''TestCase/TestClient'''
+        self.name = None
+        self.file = None
+
+
+class cloudstackConfiguration(object):
+    def __init__(self):
+        self.zones = []
+        self.mgtSvr = []
+        self.dbSvr = None
+        self.globalConfig = []
+        self.logger = []
+
+
+class zone(object):
+    def __init__(self):
+        self.dns1 = None
+        self.internaldns1 = None
+        self.name = None
+        '''Basic or Advanced'''
+        self.networktype = None
+        self.dns2 = None
+        self.internaldns2 = None
+        self.securitygroupenabled = None
+        self.localstorageenabled = None
+        '''default public network, in advanced mode'''
+        self.ipranges = []
+        self.physical_networks = []
+        self.pods = []
+        self.secondaryStorages = []
+        self.cacheStorages = []
+
+
+class traffictype(object):
+    def __init__(self, typ, labeldict=None):
+        self.typ = typ  # Guest/Management/Public
+        if labeldict:
+            self.xen = labeldict['xen'] if 'xen' in labeldict.keys() else None
+            self.kvm = labeldict['kvm'] if 'kvm' in labeldict.keys() else None
+            self.vmware = labeldict['vmware']\
+                if 'vmware' in labeldict.keys() else None
+            self.simulator = labeldict['simulator']\
+                if 'simulator' in labeldict.keys() else None
+        #{
+        #    'xen' : 'cloud-xen',
+        #    'kvm' : 'cloud-kvm',
+        #    'vmware' : 'cloud-vmware'
+        #}
+
+
+class pod(object):
+    def __init__(self):
+        self.gateway = None
+        self.name = None
+        self.netmask = None
+        self.startip = None
+        self.endip = None
+        self.zoneid = None
+        self.clusters = []
+        self.vmwaredc = []
+        '''Used in basic network mode'''
+        self.guestIpRanges = []
+
+
+class VmwareDc(object):
+    def __init__(self):
+        self.zoneid = None
+        self.name = None
+        self.vcenter = None
+        self.username = None
+        self.password = None
+
+
+class cluster(object):
+    def __init__(self):
+        self.clustername = None
+        self.clustertype = None
+        self.hypervisor = None
+        self.zoneid = None
+        self.podid = None
+        self.password = None
+        self.url = None
+        self.username = None
+        self.hosts = []
+        self.primaryStorages = []
+
+
+class host(object):
+    def __init__(self):
+        self.hypervisor = None
+        self.password = None
+        self.url = None
+        self.username = None
+        self.zoneid = None
+        self.podid = None
+        self.clusterid = None
+        self.clustername = None
+        self.cpunumber = None
+        self.cpuspeed = None
+        self.hostmac = None
+        self.hosttags = None
+        self.memory = None
+
+
+class physical_network(object):
+    def __init__(self):
+        self.name = None
+        self.tags = []
+        self.traffictypes = []
+        self.broadcastdomainrange = 'Zone'
+        self.vlan = None
+        self.isolationmethods = []
+        '''enable default virtual router provider'''
+        vrouter = provider()
+        vrouter.name = 'VirtualRouter'
+        self.providers = [vrouter]
+
+
+class provider(object):
+    def __init__(self, name=None):
+        self.name = name
+        self.state = None
+        self.broadcastdomainrange = 'ZONE'
+        self.zoneid = None
+        self.servicelist = []
+        self.devices = []
+
+
+class network(object):
+    def __init__(self):
+        self.displaytext = None
+        self.name = None
+        self.zoneid = None
+        self.acltype = None
+        self.domainid = None
+        self.networkdomain = None
+        self.networkofferingid = None
+        self.ipranges = []
+
+
+class iprange(object):
+    def __init__(self):
+        '''tagged/untagged'''
+        self.gateway = None
+        self.netmask = None
+        self.startip = None
+        self.endip = None
+        self.vlan = None
+        '''for account specific '''
+        self.account = None
+        self.domain = None
+
+
+class primaryStorage(object):
+    def __init__(self):
+        self.name = None
+        self.url = None
+
+
+class secondaryStorage(object):
+    def __init__(self):
+        self.url = None
+        self.provider = None
+        self.details = None
+
+
+class cacheStorage(object):
+    def __init__(self):
+        self.url = None
+        self.provider = None
+        self.details = None
+
+
+class s3(object):
+    def __init__(self):
+        self.accesskey = None
+        self.secretkey = None
+        self.bucket = None
+        self.endpoint = None
+        self.sockettimeout = None
+        self.connectiontimeout = None
+        self.maxerrorrety = None
+        self.usehttps = None
+
+
+class netscaler(object):
+    def __init__(self, hostname=None, username='nsroot', password='nsroot'):
+        self.hostname = hostname
+        self.username = username
+        self.password = password
+        self.networkdevicetype = 'NetscalerVPXLoadBalancer'
+        self.publicinterface = '1/1'
+        self.privateinterface = '1/1'
+        self.numretries = '2'
+        self.lbdevicecapacity = '50'
+        self.lbdevicededicated = 'false'
+
+    def getUrl(self):
+        return repr(self)
+
+    def __repr__(self):
+        req = zip(self.__dict__.keys(), self.__dict__.values())
+        return self.hostname+"?" + "&".join(["=".join([r[0], r[1]])
+                                             for r in req])
+
+
+class srx(object):
+    def __init__(self, hostname=None, username='root', password='admin'):
+        self.hostname = hostname
+        self.username = username
+        self.password = password
+        self.networkdevicetype = 'JuniperSRXFirewall'
+        self.publicinterface = '1/1'
+        self.privateinterface = '1/1'
+        self.numretries = '2'
+        self.fwdevicededicated = 'false'
+        self.timeout = '300'
+        self.publicnetwork = 'untrusted'
+        self.privatenetwork = 'trusted'
+
+    def getUrl(self):
+        return repr(self)
+
+    def __repr__(self):
+        req = zip(self.__dict__.keys(), self.__dict__.values())
+        return self.hostname+"?" + "&".join(["=".join([r[0], r[1]])
+                                             for r in req])
+
+
+class bigip(object):
+    def __init__(self, hostname=None, username='root', password='default'):
+        self.hostname = hostname
+        self.username = username
+        self.password = password
+        self.networkdevicetype = 'F5BigIpLoadBalancer'
+        self.publicinterface = '1/1'
+        self.privateinterface = '1/1'
+        self.numretries = '2'
+        self.lbdevicededicated = 'false'
+        self.lbdevicecapacity = '50'
+
+    def getUrl(self):
+        return repr(self)
+
+    def __repr__(self):
+        req = zip(self.__dict__.keys(), self.__dict__.values())
+        return self.hostname+"?" + "&".join(["=".join([r[0], r[1]])
+                                             for r in req])
+
+
+def getDeviceUrl(obj):
+    req = zip(obj.__dict__.keys(), obj.__dict__.values())
+    if obj.hostname:
+        return "http://" + obj.hostname+"?" + "&".join(["=".join([r[0],
+                                                                  r[1]])
+                                                        for r in req])
+    else:
+        return None
+
+
+def describe_setup_in_basic_mode():
+    '''sample code to generate setup configuration file'''
+    zs = cloudstackConfiguration()
+
+    for l in range(1):
+        z = zone()
+        z.dns1 = "8.8.8.8"
+        z.dns2 = "8.8.4.4"
+        z.internaldns1 = "192.168.110.254"
+        z.internaldns2 = "192.168.110.253"
+        z.name = "test"+str(l)
+        z.networktype = 'Basic'
+        z.securitygroupenabled = 'True'
+
+        #If security groups are reqd
+        sgprovider = provider()
+        sgprovider.broadcastdomainrange = 'Pod'
+        sgprovider.name = 'SecurityGroupProvider'
+
+        pn = physical_network()
+        pn.name = "test-network"
+        pn.traffictypes = [traffictype("Guest"), traffictype("Management")]
+        pn.providers.append(sgprovider)
+
+        z.physical_networks.append(pn)
+
+        '''create 10 pods'''
+        for i in range(2):
+            p = pod()
+            p.name = "test" + str(l) + str(i)
+            p.gateway = "192.168.%d.1" % i
+            p.netmask = "255.255.255.0"
+            p.startip = "192.168.%d.150" % i
+            p.endip = "192.168.%d.220" % i
+
+            '''add two pod guest ip ranges'''
+            for j in range(2):
+                ip = iprange()
+                ip.gateway = p.gateway
+                ip.netmask = p.netmask
+                ip.startip = "192.168.%d.%d" % (i, j*20)
+                ip.endip = "192.168.%d.%d" % (i, j*20+10)
+
+                p.guestIpRanges.append(ip)
+
+            '''add 10 clusters'''
+            for j in range(2):
+                c = cluster()
+                c.clustername = "test"+str(l)+str(i) + str(j)
+                c.clustertype = "CloudManaged"
+                c.hypervisor = "Simulator"
+
+                '''add 10 hosts'''
+                for k in range(2):
+                    h = host()
+                    h.username = "root"
+                    h.password = "password"
+                    memory = 8*1024*1024*1024
+                    localstorage = 1*1024*1024*1024*1024
+                    h.url = "http://sim/%d%d%d%d" % (l, i, j, k)
+                    c.hosts.append(h)
+
+                '''add 2 primary storages'''
+                for m in range(2):
+                    primary = primaryStorage()
+                    primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
+                    primary.url = "nfs://localhost/path%s" % (str(l) + str(i) +
+                                                              str(j) + str(m))
+                    c.primaryStorages.append(primary)
+
+                p.clusters.append(c)
+
+            z.pods.append(p)
+
+        '''add two secondary'''
+        for i in range(5):
+            secondary = secondaryStorage()
+            secondary.url = "nfs://localhost/path"+str(l) + str(i)
+            z.secondaryStorages.append(secondary)
+
+        zs.zones.append(z)
+
+    '''Add one mgt server'''
+    mgt = managementServer()
+    mgt.mgtSvrIp = "localhost"
+    zs.mgtSvr.append(mgt)
+
+    '''Add a database'''
+    db = dbServer()
+    db.dbSvr = "localhost"
+
+    zs.dbSvr = db
+
+    '''add global configuration'''
+    global_settings = {'expunge.delay': '60',
+                       'expunge.interval': '60',
+                       'expunge.workers': '3',
+                       }
+    for k, v in global_settings.iteritems():
+        cfg = configuration()
+        cfg.name = k
+        cfg.value = v
+        zs.globalConfig.append(cfg)
+
+    ''''add loggers'''
+    testClientLogger = logger()
+    testClientLogger.name = "TestClient"
+    testClientLogger.file = "/tmp/testclient.log"
+
+    testCaseLogger = logger()
+    testCaseLogger.name = "TestCase"
+    testCaseLogger.file = "/tmp/testcase.log"
+
+    zs.logger.append(testClientLogger)
+    zs.logger.append(testCaseLogger)
+
+    return zs
+
+
+def describe_setup_in_eip_mode():
+    """
+    Setting up an EIP/ELB enabled zone with netscaler provider
+    """
+    zs = cloudstackConfiguration()
+
+    for l in range(1):
+        z = zone()
+        z.dns1 = "8.8.8.8"
+        z.dns2 = "8.8.4.4"
+        z.internaldns1 = "192.168.110.254"
+        z.internaldns2 = "192.168.110.253"
+        z.name = "test"+str(l)
+        z.networktype = 'Basic'
+
+        ips = iprange()
+        ips.vlan = "49"
+        ips.startip = "10.147.49.200"
+        ips.endip = "10.147.49.250"
+        ips.gateway = "10.147.49.1"
+        ips.netmask = "255.255.255.0"
+        z.ipranges.append(ips)
+
+        #If security groups are reqd
+        sgprovider = provider()
+        sgprovider.broadcastdomainrange = 'Pod'
+        sgprovider.name = 'SecurityGroupProvider'
+
+        nsprovider = provider()
+        nsprovider.name = 'Netscaler'
+        ns = netscaler()
+        ns.hostname = '10.147.40.100'
+        nsprovider.devices.append(ns)
+
+        pn = physical_network()
+        pn.name = "test-network"
+        pn.traffictypes = [traffictype("Guest",
+                                       {"xen": "cloud-guest"}),
+                           traffictype("Management"),
+                           traffictype("Public", {"xen": "cloud-public"})]
+        pn.providers.extend([sgprovider, nsprovider])
+        z.physical_networks.append(pn)
+
+        '''create 10 pods'''
+        for i in range(2):
+            p = pod()
+            p.name = "test" + str(l) + str(i)
+            p.gateway = "192.168.%d.1" % i
+            p.netmask = "255.255.255.0"
+            p.startip = "192.168.%d.150" % i
+            p.endip = "192.168.%d.220" % i
+
+            '''add two pod guest ip ranges'''
+            for j in range(2):
+                ip = iprange()
+                ip.gateway = p.gateway
+                ip.netmask = p.netmask
+                ip.startip = "192.168.%d.%d" % (i, j*20)
+                ip.endip = "192.168.%d.%d" % (i, j*20+10)
+
+                p.guestIpRanges.append(ip)
+
+            '''add 10 clusters'''
+            for j in range(2):
+                c = cluster()
+                c.clustername = "test"+str(l)+str(i) + str(j)
+                c.clustertype = "CloudManaged"
+                c.hypervisor = "Simulator"
+
+                '''add 10 hosts'''
+                for k in range(2):
+                    h = host()
+                    h.username = "root"
+                    h.password = "password"
+                    h.url = "http://Sim/%d%d%d%d" % (l, i, j, k)
+                    c.hosts.append(h)
+
+                '''add 2 primary storages'''
+                for m in range(2):
+                    primary = primaryStorage()
+                    primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
+                    primary.url = "nfs://localhost/path%s" % (str(l) + str(i)
+                                                              + str(j)
+                                                              + str(m))
+                    c.primaryStorages.append(primary)
+
+                p.clusters.append(c)
+
+            z.pods.append(p)
+
+        '''add two secondary'''
+        for i in range(5):
+            secondary = secondaryStorage()
+            secondary.url = "nfs://localhost/path"+str(l) + str(i)
+            z.secondaryStorages.append(secondary)
+
+        zs.zones.append(z)
+
+    '''Add one mgt server'''
+    mgt = managementServer()
+    mgt.mgtSvrIp = "localhost"
+    zs.mgtSvr.append(mgt)
+
+    '''Add a database'''
+    db = dbServer()
+    db.dbSvr = "localhost"
+
+    zs.dbSvr = db
+
+    '''add global configuration'''
+    global_settings = {'expunge.delay': '60',
+                       'expunge.interval': '60',
+                       'expunge.workers': '3',
+                       }
+    for k, v in global_settings.iteritems():
+        cfg = configuration()
+        cfg.name = k
+        cfg.value = v
+        zs.globalConfig.append(cfg)
+
+    ''''add loggers'''
+    testClientLogger = logger()
+    testClientLogger.name = "TestClient"
+    testClientLogger.file = "/tmp/testclient.log"
+
+    testCaseLogger = logger()
+    testCaseLogger.name = "TestCase"
+    testCaseLogger.file = "/tmp/testcase.log"
+
+    zs.logger.append(testClientLogger)
+    zs.logger.append(testCaseLogger)
+
+    return zs
+
+
+def describe_setup_in_advanced_mode():
+    '''sample code to generate setup configuration file'''
+    zs = cloudstackConfiguration()
+
+    for l in range(1):
+        z = zone()
+        z.dns1 = "8.8.8.8"
+        z.dns2 = "8.8.4.4"
+        z.internaldns1 = "192.168.110.254"
+        z.internaldns2 = "192.168.110.253"
+        z.name = "test"+str(l)
+        z.networktype = 'Advanced'
+        z.guestcidraddress = "10.1.1.0/24"
+        z.vlan = "100-2000"
+
+        pn = physical_network()
+        pn.name = "test-network"
+        pn.traffictypes = [traffictype("Guest"), traffictype("Management"),
+                           traffictype("Public")]
+
+        vpcprovider = provider('VpcVirtualRouter')
+
+        nsprovider = provider('Netscaler')
+        nsprovider.devices.append(netscaler(hostname='10.147.40.100'))
+
+        srxprovider = provider('JuniperSRX')
+        srxprovider.devices.append(srx(hostname='10.147.40.3'))
+
+        f5provider = provider('F5BigIp')
+        f5provider.devices.append(bigip(hostname='10.147.40.3'))
+
+        pn.providers.extend([vpcprovider, nsprovider, srxprovider, f5provider])
+        z.physical_networks.append(pn)
+
+        '''create 10 pods'''
+        for i in range(2):
+            p = pod()
+            p.name = "test" + str(l) + str(i)
+            p.gateway = "192.168.%d.1" % i
+            p.netmask = "255.255.255.0"
+            p.startip = "192.168.%d.200" % i
+            p.endip = "192.168.%d.220" % i
+
+            '''add 10 clusters'''
+            for j in range(2):
+                c = cluster()
+                c.clustername = "test"+str(l)+str(i) + str(j)
+                c.clustertype = "CloudManaged"
+                c.hypervisor = "Simulator"
+
+                '''add 10 hosts'''
+                for k in range(2):
+                    h = host()
+                    h.username = "root"
+                    h.password = "password"
+                    memory = 8 * 1024 * 1024 * 1024
+                    localstorage = 1 * 1024 * 1024 * 1024 * 1024
+                    #h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\
+                    #    memory=%d&localstorage=%d"%(l, i, j, k, memory,
+                    #                                localstorage)
+                    h.url = "http://sim/%d%d%d%d" % (l, i, j, k)
+                    c.hosts.append(h)
+
+                '''add 2 primary storages'''
+                for m in range(2):
+                    primary = primaryStorage()
+                    primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
+                    #primary.url = "nfs://localhost/path%s/size=%d" %
+                    #    (str(l) + str(i) + str(j) + str(m), size)
+                    primary.url = "nfs://localhost/path%s" % (str(l) + str(i)
+                                                              + str(j)
+                                                              + str(m))
+                    c.primaryStorages.append(primary)
+
+                p.clusters.append(c)
+
+            z.pods.append(p)
+
+        '''add two secondary'''
+        for i in range(5):
+            secondary = secondaryStorage()
+            secondary.url = "nfs://localhost/path"+str(l) + str(i)
+            z.secondaryStorages.append(secondary)
+
+        '''add default public network'''
+        ips = iprange()
+        ips.vlan = "26"
+        ips.startip = "172.16.26.2"
+        ips.endip = "172.16.26.100"
+        ips.gateway = "172.16.26.1"
+        ips.netmask = "255.255.255.0"
+        z.ipranges.append(ips)
+
+        zs.zones.append(z)
+
+    '''Add one mgt server'''
+    mgt = managementServer()
+    mgt.mgtSvrIp = "localhost"
+    zs.mgtSvr.append(mgt)
+
+    '''Add a database'''
+    db = dbServer()
+    db.dbSvr = "localhost"
+
+    zs.dbSvr = db
+
+    '''add global configuration'''
+    global_settings = {'expunge.delay': '60',
+                       'expunge.interval': '60',
+                       'expunge.workers': '3',
+                       }
+    for k, v in global_settings.iteritems():
+        cfg = configuration()
+        cfg.name = k
+        cfg.value = v
+        zs.globalConfig.append(cfg)
+
+    ''''add loggers'''
+    testClientLogger = logger()
+    testClientLogger.name = "TestClient"
+    testClientLogger.file = "/tmp/testclient.log"
+
+    testCaseLogger = logger()
+    testCaseLogger.name = "TestCase"
+    testCaseLogger.file = "/tmp/testcase.log"
+
+    zs.logger.append(testClientLogger)
+    zs.logger.append(testCaseLogger)
+
+    return zs
+
+'''sample code to generate setup configuration file'''
+
+
+def describe_setup_in_advancedsg_mode():
+    zs = cloudstackConfiguration()
+
+    for l in range(1):
+        z = zone()
+        z.dns1 = "8.8.8.8"
+        z.dns2 = "8.8.4.4"
+        z.internaldns1 = "192.168.110.254"
+        z.internaldns2 = "192.168.110.253"
+        z.name = "test"+str(l)
+        z.networktype = 'Advanced'
+        z.vlan = "100-2000"
+        z.securitygroupenabled = "true"
+
+        pn = physical_network()
+        pn.name = "test-network"
+        pn.traffictypes = [traffictype("Guest"), traffictype("Management")]
+
+        #If security groups are reqd
+        sgprovider = provider()
+        sgprovider.broadcastdomainrange = 'ZONE'
+        sgprovider.name = 'SecurityGroupProvider'
+
+        pn.providers.append(sgprovider)
+        z.physical_networks.append(pn)
+
+        '''create 10 pods'''
+        for i in range(2):
+            p = pod()
+            p.name = "test" + str(l) + str(i)
+            p.gateway = "192.168.%d.1" % i
+            p.netmask = "255.255.255.0"
+            p.startip = "192.168.%d.200" % i
+            p.endip = "192.168.%d.220" % i
+
+            '''add 10 clusters'''
+            for j in range(2):
+                c = cluster()
+                c.clustername = "test"+str(l)+str(i) + str(j)
+                c.clustertype = "CloudManaged"
+                c.hypervisor = "Simulator"
+
+                '''add 10 hosts'''
+                for k in range(2):
+                    h = host()
+                    h.username = "root"
+                    h.password = "password"
+                    memory = 8 * 1024 * 1024 * 1024
+                    localstorage = 1 * 1024 * 1024 * 1024 * 1024
+                    #h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&\
+                        #memory=%d&localstorage=%d" % (l, i, j, k, memory,
+                        #localstorage)
+                    h.url = "http://sim/%d%d%d%d" % (l, i, j, k)
+                    c.hosts.append(h)
+
+                '''add 2 primary storages'''
+                for m in range(2):
+                    primary = primaryStorage()
+                    primary.name = "primary"+str(l) + str(i) + str(j) + str(m)
+                    #primary.url = "nfs://localhost/path%s/size=%d" % \
+                        #(str(l) + str(i) + str(j) + str(m), size)
+                    primary.url = "nfs://localhost/path%s" % \
+                        (str(l) + str(i) + str(j) + str(m))
+                    c.primaryStorages.append(primary)
+
+                p.clusters.append(c)
+
+            z.pods.append(p)
+
+        '''add two secondary'''
+        for i in range(5):
+            secondary = secondaryStorage()
+            secondary.url = "nfs://localhost/path"+str(l) + str(i)
+            z.secondaryStorages.append(secondary)
+
+        '''add default guest network'''
+        ips = iprange()
+        ips.vlan = "26"
+        ips.startip = "172.16.26.2"
+        ips.endip = "172.16.26.100"
+        ips.gateway = "172.16.26.1"
+        ips.netmask = "255.255.255.0"
+        z.ipranges.append(ips)
+
+        zs.zones.append(z)
+
+    '''Add one mgt server'''
+    mgt = managementServer()
+    mgt.mgtSvrIp = "localhost"
+    zs.mgtSvr.append(mgt)
+
+    '''Add a database'''
+    db = dbServer()
+    db.dbSvr = "localhost"
+
+    zs.dbSvr = db
+
+    '''add global configuration'''
+    global_settings = {'expunge.delay': '60',
+                       'expunge.interval': '60',
+                       'expunge.workers': '3',
+                       }
+    for k, v in global_settings.iteritems():
+        cfg = configuration()
+        cfg.name = k
+        cfg.value = v
+        zs.globalConfig.append(cfg)
+
+    ''''add loggers'''
+    testClientLogger = logger()
+    testClientLogger.name = "TestClient"
+    testClientLogger.file = "/tmp/testclient.log"
+
+    testCaseLogger = logger()
+    testCaseLogger.name = "TestCase"
+    testCaseLogger.file = "/tmp/testcase.log"
+
+    zs.logger.append(testClientLogger)
+    zs.logger.append(testCaseLogger)
+
+    return zs
+
+
+def generate_setup_config(config, file=None):
+    describe = config
+    if file is None:
+        return json.dumps(jsonHelper.jsonDump.dump(describe))
+    else:
+        fp = open(file, 'w')
+        json.dump(jsonHelper.jsonDump.dump(describe), fp, indent=4)
+        fp.close()
+
+
+def get_setup_config(file):
+    if not os.path.exists(file):
+        raise IOError("deployer file %s not found. \
+please specify a valid deployer file" % file)
+    config = cloudstackConfiguration()
+    configLines = []
+    with open(file, 'r') as fp:
+        for line in fp:
+            ws = line.strip()
+            if not ws.startswith("#"):
+                configLines.append(ws)
+    config = json.loads("\n".join(configLines))
+    return jsonHelper.jsonLoader(config)
+
+if __name__ == "__main__":
+    parser = OptionParser()
+
+    parser.add_option("-i", "--input", action="store", default=None,
+                      dest="inputfile", help="input file")
+    parser.add_option("-a", "--advanced", action="store_true", default=False,
+                      dest="advanced", help="use advanced networking")
+    parser.add_option("-s", "--advancedsg", action="store_true", default=False,
+                      dest="advancedsg", help="use advanced networking \
+with security groups")
+    parser.add_option("-o", "--output", action="store",
+                      default="./datacenterCfg", dest="output",
+                      help="the path where the json deployer file generated, \
+by default is ./datacenterCfg")
+
+    (options, args) = parser.parse_args()
+
+    if options.inputfile:
+        config = get_setup_config(options.inputfile)
+    if options.advanced:
+        config = describe_setup_in_advanced_mode()
+    elif options.advancedsg:
+        config = describe_setup_in_advancedsg_mode()
+    else:
+        config = describe_setup_in_basic_mode()
+
+    generate_setup_config(config, options.output)


[32/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: initial commit for dsl implementation

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/73aabab6
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/73aabab6
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/73aabab6

Branch: refs/heads/marvin-refactor
Commit: 73aabab6f5cf83c8aa66145aa84bc5f05f58b034
Parents: c640a32
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Fri Sep 13 15:58:55 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:52 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/feature/__init__.py       | 16 ++++++++++++
 tools/marvin/marvin/feature/deployvm.feature  |  6 +++++
 tools/marvin/marvin/feature/steps/__init__.py | 16 ++++++++++++
 tools/marvin/marvin/feature/steps/deployvm.py | 30 ++++++++++++++++++++++
 4 files changed, 68 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/73aabab6/tools/marvin/marvin/feature/__init__.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/feature/__init__.py b/tools/marvin/marvin/feature/__init__.py
new file mode 100644
index 0000000..d216be4
--- /dev/null
+++ b/tools/marvin/marvin/feature/__init__.py
@@ -0,0 +1,16 @@
+# 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.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/73aabab6/tools/marvin/marvin/feature/deployvm.feature
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/feature/deployvm.feature b/tools/marvin/marvin/feature/deployvm.feature
new file mode 100644
index 0000000..eb787f0
--- /dev/null
+++ b/tools/marvin/marvin/feature/deployvm.feature
@@ -0,0 +1,6 @@
+Feature: Deploy a VirtualMachine
+
+Scenario: Deploy a VirtualMachine
+  Given: we have an advanced zone
+  when: I deploy a virtualmachine
+  then: virtualmachine is deployed

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/73aabab6/tools/marvin/marvin/feature/steps/__init__.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/feature/steps/__init__.py b/tools/marvin/marvin/feature/steps/__init__.py
new file mode 100644
index 0000000..d216be4
--- /dev/null
+++ b/tools/marvin/marvin/feature/steps/__init__.py
@@ -0,0 +1,16 @@
+# 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.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/73aabab6/tools/marvin/marvin/feature/steps/deployvm.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/feature/steps/deployvm.py b/tools/marvin/marvin/feature/steps/deployvm.py
new file mode 100644
index 0000000..9a30699
--- /dev/null
+++ b/tools/marvin/marvin/feature/steps/deployvm.py
@@ -0,0 +1,30 @@
+# 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 behave import *
+
+@given('we have an advanced zone')
+def step_impl(context):
+    pass
+
+@when('I deploy a virtualmachine')
+def step_impl(context):
+    pass
+
+@then('virtualmachine is deployed')
+def step_impl(context):
+    pass


[04/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: Some renames to organize data and entities

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/f57e109a
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/f57e109a
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/f57e109a

Branch: refs/heads/marvin-refactor
Commit: f57e109aab6e426671c19f0b171b82896a8e2e6a
Parents: 3621969
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Tue Sep 3 21:55:57 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:07 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/base/CloudStackEntity.py    | 25 -------
 tools/marvin/marvin/base/__init__.py            | 16 -----
 tools/marvin/marvin/codegenerator.py            |  2 +-
 tools/marvin/marvin/cs_entity_generator.py      | 45 +++++-------
 tools/marvin/marvin/data/__init__.py            | 16 -----
 tools/marvin/marvin/data/account.py             | 38 ----------
 tools/marvin/marvin/data/cluster.py             | 30 --------
 tools/marvin/marvin/data/diskoffering.py        | 34 ---------
 tools/marvin/marvin/data/firewallrule.py        | 30 --------
 tools/marvin/marvin/data/host.py                | 31 ---------
 tools/marvin/marvin/data/networkoffering.py     | 73 --------------------
 tools/marvin/marvin/data/serviceoffering.py     | 27 --------
 tools/marvin/marvin/data/template.py            | 25 -------
 tools/marvin/marvin/data/user.py                | 50 --------------
 tools/marvin/marvin/data/vm.py                  | 34 ---------
 tools/marvin/marvin/data/zone.py                | 33 ---------
 tools/marvin/marvin/entity/__init__.py          | 16 +++++
 tools/marvin/marvin/entity/cloudstackentity.py  | 25 +++++++
 tools/marvin/marvin/factory/data/__init__.py    | 16 +++++
 tools/marvin/marvin/factory/data/account.py     | 38 ++++++++++
 tools/marvin/marvin/factory/data/cluster.py     | 30 ++++++++
 .../marvin/marvin/factory/data/diskoffering.py  | 34 +++++++++
 .../marvin/marvin/factory/data/firewallrule.py  | 30 ++++++++
 tools/marvin/marvin/factory/data/host.py        | 31 +++++++++
 .../marvin/factory/data/networkoffering.py      | 73 ++++++++++++++++++++
 .../marvin/factory/data/serviceoffering.py      | 27 ++++++++
 tools/marvin/marvin/factory/data/template.py    | 25 +++++++
 tools/marvin/marvin/factory/data/user.py        | 50 ++++++++++++++
 tools/marvin/marvin/factory/data/vm.py          | 34 +++++++++
 tools/marvin/marvin/factory/data/zone.py        | 33 +++++++++
 tools/marvin/marvin/test/test_factories.py      | 42 ++++-------
 tools/marvin/marvin/utils.py                    |  2 +-
 tools/marvin/pom.xml                            |  2 +-
 tools/marvin/setup.py                           |  3 +-
 34 files changed, 498 insertions(+), 522 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/base/CloudStackEntity.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/base/CloudStackEntity.py b/tools/marvin/marvin/base/CloudStackEntity.py
deleted file mode 100644
index b7091de..0000000
--- a/tools/marvin/marvin/base/CloudStackEntity.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# 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.
-
-cloudstack_version = "4.2.0"
-
-class CloudStackEntity(object):
-
-    __version__ = cloudstack_version
-
-    def getVersion(self):
-        return self.__version__

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/base/__init__.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/base/__init__.py b/tools/marvin/marvin/base/__init__.py
deleted file mode 100644
index 13a8339..0000000
--- a/tools/marvin/marvin/base/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/codegenerator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/codegenerator.py b/tools/marvin/marvin/codegenerator.py
index 974b8cc..cb0cb5c 100644
--- a/tools/marvin/marvin/codegenerator.py
+++ b/tools/marvin/marvin/codegenerator.py
@@ -487,4 +487,4 @@ response=json' % options.endpoint
 
     if options.entity:
         entities = get_actionable_entities()
-        write_entity_classes(entities, "base")
+        write_entity_classes(entities, "entity")

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/cs_entity_generator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cs_entity_generator.py b/tools/marvin/marvin/cs_entity_generator.py
index b2cf3c5..c3cda0c 100644
--- a/tools/marvin/marvin/cs_entity_generator.py
+++ b/tools/marvin/marvin/cs_entity_generator.py
@@ -261,9 +261,8 @@ def write_entity_classes(entities, module=None):
     for entity, actions in entities.iteritems():
         body = []
         imports = []
-        imports.append('from CloudStackEntity import CloudStackEntity')
+        imports.append('from cloudstackentity import CloudStackEntity')
         body.append('class %s(CloudStackEntity):' % entity)
-        #TODO: Add docs for entity
         body.append('\n\n')
         body.append(tabspace + 'def __init__(self, items):')
         body.append(tabspace * 2 + 'self.__dict__.update(items)')
@@ -280,6 +279,7 @@ def write_entity_classes(entities, module=None):
                         action, ', '.join(list(set(no_id_args)))))
                 else:
                     body.append(tabspace + 'def %s(self, apiclient, **kwargs):' % (action))
+                #TODO: Add docs for entity
                 # doc to explain what possible args go into **kwargs
                 body.append(tabspace * 2 + '"""Placeholder for docstring')
                 body.append(tabspace * 2 + 'optional arguments (**kwargs): [%s]"""' % ', '.join(details['optionals']))
@@ -335,7 +335,7 @@ def write_entity_classes(entities, module=None):
             os.makedirs("%s" % module_path)
         with open("%s/__init__.py" % (module_path), "w") as writer:
             writer.write(LICENSE)
-        with open("%s/%s.py" % (module_path, entity), "w") as writer:
+        with open("%s/%s.py" % (module_path, entity.lower()), "w") as writer:
             writer.write(LICENSE)
             writer.write(code)
 
@@ -365,31 +365,20 @@ def write_entity_factory(entity, actions, module=None):
     if not os.path.exists(module_path):
         os.makedirs(module_path)
 
-    if os.path.exists("%s/%sFactory.py" % (module_path, entity)):
-        for arg in factory_defaults:
-            code += tabspace + '%s = None\n' % arg
-        with open("%s/%sFactory.py" % (module_path, entity), "r") as reader:
-            rcode = reader.read()
-            if rcode.find(code) > 0:
-                return
-        with open("%s/%sFactory.py" % (module_path, entity), "a") as writer:
-            writer.write(code)
-    else:
-        code += 'import factory\n'
-        code += 'from marvin.base import %s\n' % entity
-        code += 'from CloudStackBaseFactory import CloudStackBaseFactory'
-        code += '\n'
-        code += 'class %sFactory(CloudStackBaseFactory):' % entity
-        code += '\n\n'
-        code += tabspace + 'FACTORY_FOR = %s.%s\n\n' % (entity, entity)
-        for arg in factory_defaults:
-            code += tabspace + '%s = None\n' % arg
-        with open("%s/__init__.py" % (module_path), "w") as writer:
-            writer.write(LICENSE)
-        with open("%s/%sFactory.py" % (module_path, entity), "w") as writer:
-            writer.write(LICENSE)
-            writer.write(code)
+    code += 'from marvin.entity.%s import %s\n' % (entity.lower(), entity)
+    code += 'from cloudstackbasefactory import CloudStackBaseFactory'
+    code += '\n'
+    code += 'class %sFactory(CloudStackBaseFactory):' % entity
+    code += '\n\n'
+    code += tabspace + 'FACTORY_FOR = %s\n\n' % entity
+    for arg in factory_defaults:
+        code += tabspace + '%s = None\n' % arg
+    with open("%s/__init__.py" % (module_path), "w") as writer:
+        writer.write(LICENSE)
+    with open("%s/%s.py" % (module_path, entity.lower()), "w") as writer:
+        writer.write(LICENSE)
+        writer.write(code)
 
 if __name__ == '__main__':
     entities = get_actionable_entities()
-    write_entity_classes(entities, 'base')
+    write_entity_classes(entities, 'entity')

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/__init__.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/__init__.py b/tools/marvin/marvin/data/__init__.py
deleted file mode 100644
index d216be4..0000000
--- a/tools/marvin/marvin/data/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/account.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/account.py b/tools/marvin/marvin/data/account.py
deleted file mode 100644
index 1041cfe..0000000
--- a/tools/marvin/marvin/data/account.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# 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.
-
-import factory
-from marvin.factory.AccountFactory import AccountFactory
-from marvin.utils import random_gen
-
-class UserAccountFactory(AccountFactory):
-
-    accounttype = 0
-    firstname = factory.Sequence(lambda n: random_gen())
-    lastname = factory.Sequence(lambda n: random_gen())
-    email = factory.LazyAttribute(lambda e: '{0}.{1}@cloudstack.org'.format(e.firstname, e.lastname).lower())
-    username = factory.Sequence(lambda n: random_gen())
-    password = 'password'
-
-
-class AdminAccountFactory(UserAccountFactory):
-    accounttype = 1
-
-
-class DomainAdminFactory(UserAccountFactory):
-    accounttype = 2
-    domainid = None

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/cluster.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/cluster.py b/tools/marvin/marvin/data/cluster.py
deleted file mode 100644
index f4641cf..0000000
--- a/tools/marvin/marvin/data/cluster.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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.
-
-import factory
-from marvin.utils import random_gen
-from marvin.factory.ClusterFactory import ClusterFactory
-
-class XenClusterFactory(ClusterFactory):
-    clustername = factory.Sequence(lambda n: "xencluster" + random_gen())
-    clustertype = "XenServer"
-    hypervisor = "XenServer"
-
-class KvmClusterFactory(ClusterFactory):
-    clustername = factory.Sequence(lambda n: "kvmcluster" + random_gen())
-    clustertype = "KVM"
-    hypervisor = "KVM"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/diskoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/diskoffering.py b/tools/marvin/marvin/data/diskoffering.py
deleted file mode 100644
index 88ae7cb..0000000
--- a/tools/marvin/marvin/data/diskoffering.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# 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.
-
-import factory
-from marvin.factory.DiskOfferingFactory import DiskOfferingFactory
-from marvin.utils import random_gen
-
-class SharedDiskOfferingFactory(DiskOfferingFactory):
-
-    displaytext = "SharedDiskOffering"
-    name = factory.Sequence(lambda n : "SharedDiskOffering" + random_gen())
-    storagetype = "shared"
-    disksize = 10 #MB
-
-class LocalDiskOfferingFactory(DiskOfferingFactory):
-
-    displaytext = "LocalDiskOffering"
-    name = factory.Sequence(lambda n : "LocalDiskOffering" + random_gen())
-    storagetype = "local"
-    disksize = 10 #MB

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/firewallrule.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/firewallrule.py b/tools/marvin/marvin/data/firewallrule.py
deleted file mode 100644
index 1707347..0000000
--- a/tools/marvin/marvin/data/firewallrule.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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.factory.FirewallRuleFactory import FirewallRuleFactory
-
-class SshFirewallRuleFactory(FirewallRuleFactory):
-    protocol = 'tcp'
-    startport = 22
-    endport = 22
-    cidrlist = '0.0.0.0/0'
-
-class HttpFirewallRuleFactory(FirewallRuleFactory):
-    protocol = 'tcp'
-    startport = 80
-    endport = 80
-    cidrlist = '0.0.0.0/0'

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/host.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/host.py b/tools/marvin/marvin/data/host.py
deleted file mode 100644
index c8b4ab7..0000000
--- a/tools/marvin/marvin/data/host.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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.factory.HostFactory import HostFactory
-
-class XenserverHostFactory(HostFactory):
-
-    hypervisor = 'XenServer'
-    password = 'password'
-    username = 'root'
-
-
-class KvmHostFactory(HostFactory):
-
-    hypervisor = 'KVM'
-    password = 'password'
-    username = 'root'

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/networkoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/networkoffering.py b/tools/marvin/marvin/data/networkoffering.py
deleted file mode 100644
index 8d80631..0000000
--- a/tools/marvin/marvin/data/networkoffering.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# 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.
-
-import factory
-from marvin.factory.NetworkOfferingFactory import NetworkOfferingFactory
-from marvin.utils import random_gen
-
-
-class DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory(NetworkOfferingFactory):
-    #FIXME: Service Capability Lists with CapabilityTypes (ElasticIP, RvR etc) needs handling
-
-    displaytext = factory.Sequence(lambda n : "DefaultIsolatedNetworkOfferingWithSourceNatService" + random_gen())
-    name = factory.Sequence(lambda n : "DefaultIsolatedNetworkOfferingWithSourceNatService" + random_gen())
-    supportedservices = "Lb,Dns,PortForwarding,StaticNat,Dhcp,Firewall,Vpn,UserData,SourceNat"
-    traffictype = "GUEST"
-    availability = "Optional"
-    guestiptype = "Isolated"
-
-    specifyVlan = False
-    specifyIpRanges = False
-    isPersistent = False
-    conserveMode = True
-
-    serviceProviderList = []
-    for service in map(lambda l: l.strip(' '), supportedservices.split(',')):
-        serviceProviderList.append(
-            {
-                'service': service,
-                'provider': 'VirtualRouter'
-            }
-        )
-
-
-class DefaultSharedNetworkOfferingWithSGServiceFactory(NetworkOfferingFactory):
-
-    displaytext = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingWithSGService" + random_gen())
-    name = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingWithSGService" + random_gen())
-    availability = "Optional"
-    supportedservices = "SecurityGroup,Dns,Dhcp,UserData"
-    guestiptype = "Shared"
-    traffictype = "GUEST"
-
-    specifyVlan = True
-    specifyIpRanges = True
-    isPersistent = False
-    conserveMode = True
-
-    serviceProviderList = []
-    for service in map(lambda l: l.strip(' '), supportedservices.split(',')):
-        if service == 'SecurityGroup':
-            provider = 'SecurityGroupProvider'
-        else:
-            provider = 'VirtualRouter'
-        serviceProviderList.append(
-            {
-                'service': service,
-                'provider': provider
-            }
-        )

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/serviceoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/serviceoffering.py b/tools/marvin/marvin/data/serviceoffering.py
deleted file mode 100644
index a56d4e5..0000000
--- a/tools/marvin/marvin/data/serviceoffering.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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.
-
-import factory
-from marvin.factory.ServiceOfferingFactory import ServiceOfferingFactory
-from marvin.utils import random_gen
-
-class SmallServiceOfferingFactory(ServiceOfferingFactory):
-    cpunumber = 1
-    cpuspeed = 100 #Mhz
-    memory = 100 #MB
-    displaytext = "Small Service Offering"
-    name = factory.Sequence(lambda n: "SmallServiceOffering" + random_gen())

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/template.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/template.py b/tools/marvin/marvin/data/template.py
deleted file mode 100644
index 033835b..0000000
--- a/tools/marvin/marvin/data/template.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# 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.factory.TemplateFactory import TemplateFactory
-
-class DefaultBuiltInTemplateFactory(TemplateFactory):
-    ostype = 'CentOS 5.3 (64-bit)'
-    displaytext = 'CentOS 5.3 (64-bit)'
-    name = 'CentOS 5.3 (64-bit)'
-    format = 'VHD'
-    hypervisor = 'XenServer'

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/user.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/user.py b/tools/marvin/marvin/data/user.py
deleted file mode 100644
index 13c4db2..0000000
--- a/tools/marvin/marvin/data/user.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# 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.
-
-import factory
-from marvin.factory.UserFactory import UserFactory
-from marvin.data.account import UserAccountFactory
-from marvin.utils import random_gen
-
-class UserFactory(UserFactory):
-
-    firstname = factory.Sequence(lambda n: random_gen())
-    lastname = factory.Sequence(lambda n: random_gen())
-    email = factory.LazyAttribute(lambda e: '{0}.{1}@cloudstack.org'.format(e.firstname, e.lastname).lower())
-    username = factory.Sequence(lambda n: random_gen())
-    password = 'password'
-    account = factory.SubFactory(UserAccountFactory,
-        apiclient=factory.SelfAttribute('..apiclient'),
-        accounttype=0,
-        firstname=factory.SelfAttribute('..firstname'),
-        lastname=factory.SelfAttribute('..lastname'),
-        email=factory.SelfAttribute('..email'),
-        password=factory.SelfAttribute('..password'),
-        username=factory.SelfAttribute('..username'),
-    )
-
-class AdminUserFactory(UserFactory):
-
-    account = factory.SubFactory(UserAccountFactory,
-        apiclient=factory.SelfAttribute('..apiclient'),
-        accounttype=1,
-        firstname=factory.SelfAttribute('..firstname'),
-        lastname=factory.SelfAttribute('..lastname'),
-        email=factory.SelfAttribute('..email'),
-        password=factory.SelfAttribute('..password'),
-        username=factory.SelfAttribute('..username'),
-    )

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/vm.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/vm.py b/tools/marvin/marvin/data/vm.py
deleted file mode 100644
index 66f15a3..0000000
--- a/tools/marvin/marvin/data/vm.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# 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.
-
-import factory
-from marvin.factory.VirtualMachineFactory import VirtualMachineFactory
-from marvin.utils import random_gen
-
-
-class VirtualMachineIsolatedNetwork(VirtualMachineFactory):
-    """
-    Create a virtualmachine in an isolated network typically in an advanced zone
-
-    Uses a serviceoffering of tinyInstance
-    Uses a builtin template available
-    Deploys in the first zone available
-    """
-
-    serviceofferingid = None
-    templateid = None
-    zoneid = None

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/data/zone.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/data/zone.py b/tools/marvin/marvin/data/zone.py
deleted file mode 100644
index f4a278a..0000000
--- a/tools/marvin/marvin/data/zone.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# 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.
-
-import factory
-from marvin.factory.ZoneFactory import ZoneFactory
-from marvin.utils import random_gen
-
-class AdvancedZoneFactory(ZoneFactory):
-    name = factory.Sequence(lambda n: "advzone" + random_gen())
-    networktype = "Advanced"
-    dns1 = "8.8.8.8"
-    internaldns1 = "8.8.8.8"
-
-
-class BasicZoneFactory(ZoneFactory):
-    name = factory.Sequence(lambda n: "basiczone" + random_gen())
-    networktype = "Basic"
-    dns1 = "8.8.8.8"
-    internaldns1 = "8.8.8.8"
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/entity/__init__.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/entity/__init__.py b/tools/marvin/marvin/entity/__init__.py
new file mode 100644
index 0000000..13a8339
--- /dev/null
+++ b/tools/marvin/marvin/entity/__init__.py
@@ -0,0 +1,16 @@
+# 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.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/entity/cloudstackentity.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/entity/cloudstackentity.py b/tools/marvin/marvin/entity/cloudstackentity.py
new file mode 100644
index 0000000..b7091de
--- /dev/null
+++ b/tools/marvin/marvin/entity/cloudstackentity.py
@@ -0,0 +1,25 @@
+# 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.
+
+cloudstack_version = "4.2.0"
+
+class CloudStackEntity(object):
+
+    __version__ = cloudstack_version
+
+    def getVersion(self):
+        return self.__version__

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/factory/data/__init__.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/__init__.py b/tools/marvin/marvin/factory/data/__init__.py
new file mode 100644
index 0000000..d216be4
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/__init__.py
@@ -0,0 +1,16 @@
+# 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.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/factory/data/account.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/account.py b/tools/marvin/marvin/factory/data/account.py
new file mode 100644
index 0000000..1041cfe
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/account.py
@@ -0,0 +1,38 @@
+# 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.
+
+import factory
+from marvin.factory.AccountFactory import AccountFactory
+from marvin.utils import random_gen
+
+class UserAccountFactory(AccountFactory):
+
+    accounttype = 0
+    firstname = factory.Sequence(lambda n: random_gen())
+    lastname = factory.Sequence(lambda n: random_gen())
+    email = factory.LazyAttribute(lambda e: '{0}.{1}@cloudstack.org'.format(e.firstname, e.lastname).lower())
+    username = factory.Sequence(lambda n: random_gen())
+    password = 'password'
+
+
+class AdminAccountFactory(UserAccountFactory):
+    accounttype = 1
+
+
+class DomainAdminFactory(UserAccountFactory):
+    accounttype = 2
+    domainid = None

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/factory/data/cluster.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/cluster.py b/tools/marvin/marvin/factory/data/cluster.py
new file mode 100644
index 0000000..f4641cf
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/cluster.py
@@ -0,0 +1,30 @@
+# 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.
+
+import factory
+from marvin.utils import random_gen
+from marvin.factory.ClusterFactory import ClusterFactory
+
+class XenClusterFactory(ClusterFactory):
+    clustername = factory.Sequence(lambda n: "xencluster" + random_gen())
+    clustertype = "XenServer"
+    hypervisor = "XenServer"
+
+class KvmClusterFactory(ClusterFactory):
+    clustername = factory.Sequence(lambda n: "kvmcluster" + random_gen())
+    clustertype = "KVM"
+    hypervisor = "KVM"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/factory/data/diskoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/diskoffering.py b/tools/marvin/marvin/factory/data/diskoffering.py
new file mode 100644
index 0000000..88ae7cb
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/diskoffering.py
@@ -0,0 +1,34 @@
+# 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.
+
+import factory
+from marvin.factory.DiskOfferingFactory import DiskOfferingFactory
+from marvin.utils import random_gen
+
+class SharedDiskOfferingFactory(DiskOfferingFactory):
+
+    displaytext = "SharedDiskOffering"
+    name = factory.Sequence(lambda n : "SharedDiskOffering" + random_gen())
+    storagetype = "shared"
+    disksize = 10 #MB
+
+class LocalDiskOfferingFactory(DiskOfferingFactory):
+
+    displaytext = "LocalDiskOffering"
+    name = factory.Sequence(lambda n : "LocalDiskOffering" + random_gen())
+    storagetype = "local"
+    disksize = 10 #MB

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/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
new file mode 100644
index 0000000..1707347
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/firewallrule.py
@@ -0,0 +1,30 @@
+# 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.factory.FirewallRuleFactory import FirewallRuleFactory
+
+class SshFirewallRuleFactory(FirewallRuleFactory):
+    protocol = 'tcp'
+    startport = 22
+    endport = 22
+    cidrlist = '0.0.0.0/0'
+
+class HttpFirewallRuleFactory(FirewallRuleFactory):
+    protocol = 'tcp'
+    startport = 80
+    endport = 80
+    cidrlist = '0.0.0.0/0'

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/factory/data/host.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/host.py b/tools/marvin/marvin/factory/data/host.py
new file mode 100644
index 0000000..c8b4ab7
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/host.py
@@ -0,0 +1,31 @@
+# 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.factory.HostFactory import HostFactory
+
+class XenserverHostFactory(HostFactory):
+
+    hypervisor = 'XenServer'
+    password = 'password'
+    username = 'root'
+
+
+class KvmHostFactory(HostFactory):
+
+    hypervisor = 'KVM'
+    password = 'password'
+    username = 'root'

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/factory/data/networkoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/networkoffering.py b/tools/marvin/marvin/factory/data/networkoffering.py
new file mode 100644
index 0000000..8d80631
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/networkoffering.py
@@ -0,0 +1,73 @@
+# 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.
+
+import factory
+from marvin.factory.NetworkOfferingFactory import NetworkOfferingFactory
+from marvin.utils import random_gen
+
+
+class DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory(NetworkOfferingFactory):
+    #FIXME: Service Capability Lists with CapabilityTypes (ElasticIP, RvR etc) needs handling
+
+    displaytext = factory.Sequence(lambda n : "DefaultIsolatedNetworkOfferingWithSourceNatService" + random_gen())
+    name = factory.Sequence(lambda n : "DefaultIsolatedNetworkOfferingWithSourceNatService" + random_gen())
+    supportedservices = "Lb,Dns,PortForwarding,StaticNat,Dhcp,Firewall,Vpn,UserData,SourceNat"
+    traffictype = "GUEST"
+    availability = "Optional"
+    guestiptype = "Isolated"
+
+    specifyVlan = False
+    specifyIpRanges = False
+    isPersistent = False
+    conserveMode = True
+
+    serviceProviderList = []
+    for service in map(lambda l: l.strip(' '), supportedservices.split(',')):
+        serviceProviderList.append(
+            {
+                'service': service,
+                'provider': 'VirtualRouter'
+            }
+        )
+
+
+class DefaultSharedNetworkOfferingWithSGServiceFactory(NetworkOfferingFactory):
+
+    displaytext = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingWithSGService" + random_gen())
+    name = factory.Sequence(lambda n : "DefaultSharedNetworkOfferingWithSGService" + random_gen())
+    availability = "Optional"
+    supportedservices = "SecurityGroup,Dns,Dhcp,UserData"
+    guestiptype = "Shared"
+    traffictype = "GUEST"
+
+    specifyVlan = True
+    specifyIpRanges = True
+    isPersistent = False
+    conserveMode = True
+
+    serviceProviderList = []
+    for service in map(lambda l: l.strip(' '), supportedservices.split(',')):
+        if service == 'SecurityGroup':
+            provider = 'SecurityGroupProvider'
+        else:
+            provider = 'VirtualRouter'
+        serviceProviderList.append(
+            {
+                'service': service,
+                'provider': provider
+            }
+        )

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/factory/data/serviceoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/serviceoffering.py b/tools/marvin/marvin/factory/data/serviceoffering.py
new file mode 100644
index 0000000..a56d4e5
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/serviceoffering.py
@@ -0,0 +1,27 @@
+# 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.
+
+import factory
+from marvin.factory.ServiceOfferingFactory import ServiceOfferingFactory
+from marvin.utils import random_gen
+
+class SmallServiceOfferingFactory(ServiceOfferingFactory):
+    cpunumber = 1
+    cpuspeed = 100 #Mhz
+    memory = 100 #MB
+    displaytext = "Small Service Offering"
+    name = factory.Sequence(lambda n: "SmallServiceOffering" + random_gen())

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/factory/data/template.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/template.py b/tools/marvin/marvin/factory/data/template.py
new file mode 100644
index 0000000..033835b
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/template.py
@@ -0,0 +1,25 @@
+# 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.factory.TemplateFactory import TemplateFactory
+
+class DefaultBuiltInTemplateFactory(TemplateFactory):
+    ostype = 'CentOS 5.3 (64-bit)'
+    displaytext = 'CentOS 5.3 (64-bit)'
+    name = 'CentOS 5.3 (64-bit)'
+    format = 'VHD'
+    hypervisor = 'XenServer'

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/factory/data/user.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/user.py b/tools/marvin/marvin/factory/data/user.py
new file mode 100644
index 0000000..ee84644
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/user.py
@@ -0,0 +1,50 @@
+# 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.
+
+import factory
+from marvin.factory.UserFactory import UserFactory
+from marvin.factory.data.account import UserAccountFactory
+from marvin.utils import random_gen
+
+class UserFactory(UserFactory):
+
+    firstname = factory.Sequence(lambda n: random_gen())
+    lastname = factory.Sequence(lambda n: random_gen())
+    email = factory.LazyAttribute(lambda e: '{0}.{1}@cloudstack.org'.format(e.firstname, e.lastname).lower())
+    username = factory.Sequence(lambda n: random_gen())
+    password = 'password'
+    account = factory.SubFactory(UserAccountFactory,
+        apiclient=factory.SelfAttribute('..apiclient'),
+        accounttype=0,
+        firstname=factory.SelfAttribute('..firstname'),
+        lastname=factory.SelfAttribute('..lastname'),
+        email=factory.SelfAttribute('..email'),
+        password=factory.SelfAttribute('..password'),
+        username=factory.SelfAttribute('..username'),
+    )
+
+class AdminUserFactory(UserFactory):
+
+    account = factory.SubFactory(UserAccountFactory,
+        apiclient=factory.SelfAttribute('..apiclient'),
+        accounttype=1,
+        firstname=factory.SelfAttribute('..firstname'),
+        lastname=factory.SelfAttribute('..lastname'),
+        email=factory.SelfAttribute('..email'),
+        password=factory.SelfAttribute('..password'),
+        username=factory.SelfAttribute('..username'),
+    )

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/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
new file mode 100644
index 0000000..66f15a3
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/vm.py
@@ -0,0 +1,34 @@
+# 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.
+
+import factory
+from marvin.factory.VirtualMachineFactory import VirtualMachineFactory
+from marvin.utils import random_gen
+
+
+class VirtualMachineIsolatedNetwork(VirtualMachineFactory):
+    """
+    Create a virtualmachine in an isolated network typically in an advanced zone
+
+    Uses a serviceoffering of tinyInstance
+    Uses a builtin template available
+    Deploys in the first zone available
+    """
+
+    serviceofferingid = None
+    templateid = None
+    zoneid = None

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/factory/data/zone.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/zone.py b/tools/marvin/marvin/factory/data/zone.py
new file mode 100644
index 0000000..f4a278a
--- /dev/null
+++ b/tools/marvin/marvin/factory/data/zone.py
@@ -0,0 +1,33 @@
+# 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.
+
+import factory
+from marvin.factory.ZoneFactory import ZoneFactory
+from marvin.utils import random_gen
+
+class AdvancedZoneFactory(ZoneFactory):
+    name = factory.Sequence(lambda n: "advzone" + random_gen())
+    networktype = "Advanced"
+    dns1 = "8.8.8.8"
+    internaldns1 = "8.8.8.8"
+
+
+class BasicZoneFactory(ZoneFactory):
+    name = factory.Sequence(lambda n: "basiczone" + random_gen())
+    networktype = "Basic"
+    dns1 = "8.8.8.8"
+    internaldns1 = "8.8.8.8"
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/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 23a6580..5ce8c13 100644
--- a/tools/marvin/marvin/test/test_factories.py
+++ b/tools/marvin/marvin/test/test_factories.py
@@ -20,22 +20,22 @@ import logging
 
 from marvin.cloudstackTestClient import cloudstackTestClient
 
-from marvin.data.account import UserAccountFactory, AdminAccountFactory, DomainAdminFactory
-from marvin.data.serviceoffering import *
-from marvin.data.template import *
-from marvin.data.user import *
-from marvin.data.networkoffering import *
+from marvin.factory.data.account import UserAccountFactory, AdminAccountFactory, DomainAdminFactory
+from marvin.factory.data.serviceoffering import *
+from marvin.factory.data.template import *
+from marvin.factory.data.user import *
+from marvin.factory.data.networkoffering import *
 
 from marvin.factory.VirtualMachineFactory import *
 
-from marvin.base.ServiceOffering import ServiceOffering
-from marvin.base.Zone import Zone
-from marvin.base.Account import Account
-from marvin.base.Template import Template
-from marvin.base.User import User
-from marvin.base.Network import Network
+from marvin.entity.serviceoffering import ServiceOffering
+from marvin.entity.zone import Zone
+from marvin.entity.account import Account
+from marvin.entity.template import Template
+from marvin.entity.user import User
+from marvin.entity.network import Network
 
-from marvin.base.IpAddress import IpAddress
+from marvin.entity.ipaddress import IpAddress
 class BuildVsCreateStrategyTest(unittest.TestCase):
     def setUp(self):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
@@ -160,7 +160,7 @@ class IpAddressFactoryTest(unittest.TestCase):
         self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def tearDown(self):
-        pass
+        self.vm.destroy(apiclient=self.apiClient)
 
     def test_associateIpAddressToNetwork(self):
         accnt = UserAccountFactory.create(apiclient=self.apiClient)
@@ -171,7 +171,7 @@ class IpAddressFactoryTest(unittest.TestCase):
         template = Template.list(apiclient=self.apiClient, templatefilter="featured")
         self.assert_(len(template) > 0)
         zones = Zone.list(apiclient=self.apiClient)
-        vm = VirtualMachineFactory.create(
+        self.vm = VirtualMachineFactory.create(
             apiclient=self.apiClient,
             serviceofferingid = service[0].id,
             templateid = template[0].id,
@@ -182,18 +182,4 @@ 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)
-        vm.destroy(apiclient=self.apiClient)
-
-
-class VirtualMachineTest(unittest.TestCase):
-    """
-    Test virtualmachine lifecycle using factories
-    """
-    def setUp(self):
-        self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factory.cloudstack')).getApiClient()
-
-    def tearDown(self):
-        pass
 
-    def test_virtualmachinedeploy(self):
-        pass
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/marvin/utils.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/utils.py b/tools/marvin/marvin/utils.py
index f1b8e03..44a6e96 100644
--- a/tools/marvin/marvin/utils.py
+++ b/tools/marvin/marvin/utils.py
@@ -241,7 +241,7 @@ def is_snapshot_on_nfs(apiclient, dbconn, config, zoneid, snapshotid):
     @return: True if snapshot is found, False otherwise
     """
 
-    from base import ImageStore, Snapshot
+    from entity import ImageStore, Snapshot
     secondaryStores = ImageStore.list(apiclient, zoneid=zoneid)
 
     assert isinstance(secondaryStores, list), "Not a valid response for listImageStores"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/pom.xml
----------------------------------------------------------------------
diff --git a/tools/marvin/pom.xml b/tools/marvin/pom.xml
index 2b4f360..25909b3 100644
--- a/tools/marvin/pom.xml
+++ b/tools/marvin/pom.xml
@@ -142,7 +142,7 @@
                     <argument>install</argument>
                     <argument>--upgrade</argument>
                     <!-- TODO: Fix Marvin versioning here -->
-                    <argument>Marvin-0.1.0.tar.gz</argument>
+                    <argument>Marvin-0.2.0.tar.gz</argument>
                   </arguments>
                 </configuration>
               </execution>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/f57e109a/tools/marvin/setup.py
----------------------------------------------------------------------
diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py
index 5e9b125..b499671 100644
--- a/tools/marvin/setup.py
+++ b/tools/marvin/setup.py
@@ -42,7 +42,8 @@ setup(name="Marvin",
     maintainer_email="tsp@apache.org",
     long_description="Marvin is the Apache CloudStack python client written around the unittest framework",
     platforms=("Any",),
-    packages=["marvin", "marvin.cloudstackAPI", "marvin.base", "marvin.factory",
+    packages=["marvin", "marvin.cloudstackAPI", "marvin.entity", "marvin.factory", "marvin.factory.data",
+              "marvin.docs", "marvin.generate", "marvin.legacy", "marvin.sandbox",
               "marvin.sandbox.advanced", "marvin.sandbox.advancedsg", "marvin.sandbox.basic"],
     license="LICENSE.txt",
     install_requires=[


[14/50] [abbrv] marvin-refactor: move the deployment helpers to deployer module

Posted by ts...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ff8dfe1c/tools/marvin/marvin/deployer/deployDataCenter.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployer/deployDataCenter.py b/tools/marvin/marvin/deployer/deployDataCenter.py
new file mode 100644
index 0000000..2ce8757
--- /dev/null
+++ b/tools/marvin/marvin/deployer/deployDataCenter.py
@@ -0,0 +1,625 @@
+# 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.
+
+"""Deploy datacenters according to a json configuration file"""
+import cloudstackException
+import cloudstackTestClient
+import logging
+from cloudstackAPI import *
+from os import path
+from time import sleep
+from optparse import OptionParser
+from marvin.deployer import configGenerator
+
+
+class deployDataCenters(object):
+
+    def __init__(self, cfgFile):
+        if not path.exists(cfgFile) \
+           and not path.exists(path.abspath(cfgFile)):
+            raise IOError("deployer file %s not found. please \
+specify a valid deployer file" % cfgFile)
+        self.configFile = cfgFile
+
+    def addHosts(self, hosts, zoneId, podId, clusterId, hypervisor):
+        if hosts is None:
+            return
+        for host in hosts:
+            hostcmd = addHost.addHostCmd()
+            hostcmd.clusterid = clusterId
+            hostcmd.cpunumber = host.cpunumer
+            hostcmd.cpuspeed = host.cpuspeed
+            hostcmd.hostmac = host.hostmac
+            hostcmd.hosttags = host.hosttags
+            hostcmd.hypervisor = host.hypervisor
+            hostcmd.memory = host.memory
+            hostcmd.password = host.password
+            hostcmd.podid = podId
+            hostcmd.url = host.url
+            hostcmd.username = host.username
+            hostcmd.zoneid = zoneId
+            hostcmd.hypervisor = hypervisor
+            self.apiClient.addHost(hostcmd)
+
+    def addVmWareDataCenter(self, vmwareDc):
+        vdc = addVmwareDc.addVmwareDcCmd()
+        vdc.zoneid = vmwareDc.zoneid
+        vdc.name = vmwareDc.name
+        vdc.vcenter = vmwareDc.vcenter
+        vdc.username = vmwareDc.username
+        vdc.password = vmwareDc.password
+        self.apiClient.addVmwareDc(vdc)
+
+    def createClusters(self, clusters, zoneId, podId, vmwareDc=None):
+        if clusters is None:
+            return
+
+        if vmwareDc is not None:
+            vmwareDc.zoneid = zoneId
+            self.addVmWareDataCenter(vmwareDc)
+
+        for cluster in clusters:
+            clustercmd = addCluster.addClusterCmd()
+            clustercmd.clustername = cluster.clustername
+            clustercmd.clustertype = cluster.clustertype
+            clustercmd.hypervisor = cluster.hypervisor
+            clustercmd.password = cluster.password
+            clustercmd.podid = podId
+            clustercmd.url = cluster.url
+            clustercmd.username = cluster.username
+            clustercmd.zoneid = zoneId
+            clusterresponse = self.apiClient.addCluster(clustercmd)
+            clusterId = clusterresponse[0].id
+
+            if cluster.hypervisor.lower() != "vmware":
+                self.addHosts(cluster.hosts, zoneId, podId, clusterId,
+                              cluster.hypervisor)
+            self.wait_for_host(zoneId, clusterId)
+            self.createPrimaryStorages(cluster.primaryStorages, zoneId, podId,
+                                       clusterId)
+
+    def wait_for_host(self, zoneId, clusterId):
+        """
+        Wait for the hosts in the zoneid, clusterid to be up
+
+        2 retries with 30s delay
+        """
+        retry, timeout = 2, 30
+        cmd = listHosts.listHostsCmd()
+        cmd.clusterid, cmd.zoneid = clusterId, zoneId
+        hosts = self.apiClient.listHosts(cmd)
+        while retry != 0:
+            for host in hosts:
+                if host.state != 'Up':
+                    break
+            sleep(timeout)
+            retry = retry - 1
+
+    def createPrimaryStorages(self, primaryStorages, zoneId, podId, clusterId):
+        if primaryStorages is None:
+            return
+        for primary in primaryStorages:
+            primarycmd = createStoragePool.createStoragePoolCmd()
+            primarycmd.details = primary.details
+            primarycmd.name = primary.name
+            primarycmd.podid = podId
+            primarycmd.tags = primary.tags
+            primarycmd.url = primary.url
+            primarycmd.zoneid = zoneId
+            primarycmd.clusterid = clusterId
+            self.apiClient.createStoragePool(primarycmd)
+
+    def createpods(self, pods, zoneId, networkId=None):
+        if pods is None:
+            return
+        for pod in pods:
+            createpod = createPod.createPodCmd()
+            createpod.name = pod.name
+            createpod.gateway = pod.gateway
+            createpod.netmask = pod.netmask
+            createpod.startip = pod.startip
+            createpod.endip = pod.endip
+            createpod.zoneid = zoneId
+            createpodResponse = self.apiClient.createPod(createpod)
+            podId = createpodResponse.id
+
+            if pod.guestIpRanges is not None and networkId is not None:
+                self.createVlanIpRanges("Basic", pod.guestIpRanges, zoneId,
+                                        podId, networkId)
+
+            self.createClusters(pod.clusters, zoneId, podId,
+                                vmwareDc=pod.vmwaredc)
+
+    def createVlanIpRanges(self, mode, ipranges, zoneId, podId=None,
+                           networkId=None, forvirtualnetwork=None):
+        if ipranges is None:
+            return
+        for iprange in ipranges:
+            vlanipcmd = createVlanIpRange.createVlanIpRangeCmd()
+            vlanipcmd.account = iprange.account
+            vlanipcmd.domainid = iprange.domainid
+            vlanipcmd.endip = iprange.endip
+            vlanipcmd.gateway = iprange.gateway
+            vlanipcmd.netmask = iprange.netmask
+            vlanipcmd.networkid = networkId
+            vlanipcmd.podid = podId
+            vlanipcmd.startip = iprange.startip
+            vlanipcmd.zoneid = zoneId
+            vlanipcmd.vlan = iprange.vlan
+            if mode == "Basic":
+                if forvirtualnetwork:
+                    vlanipcmd.forvirtualnetwork = "true"
+                else:
+                    vlanipcmd.forvirtualnetwork = "false"
+            else:
+                vlanipcmd.forvirtualnetwork = "true"
+            self.apiClient.createVlanIpRange(vlanipcmd)
+
+    def createSecondaryStorages(self, secondaryStorages, zoneId):
+        if secondaryStorages is None:
+            return
+        for secondary in secondaryStorages:
+            secondarycmd = addImageStore.addImageStoreCmd()
+            secondarycmd.url = secondary.url
+            secondarycmd.provider = secondary.provider
+            secondarycmd.details = []
+
+            if secondarycmd.provider == 'S3' \
+                    or secondarycmd.provider == "Swift":
+                for key, value in vars(secondary.details).iteritems():
+                    secondarycmd.details.append({
+                                                'key': key,
+                                                'value': value
+                                                })
+            if secondarycmd.provider == "NFS":
+                secondarycmd.zoneid = zoneId
+            self.apiClient.addImageStore(secondarycmd)
+
+    def createCacheStorages(self, cacheStorages, zoneId):
+        if cacheStorages is None:
+            return
+        for cache in cacheStorages:
+            cachecmd = createSecondaryStagingStore.\
+                createSecondaryStagingStoreCmd()
+            cachecmd.url = cache.url
+            cachecmd.provider = cache.provider
+            cachecmd.zoneid = zoneId
+            cachecmd.details = []
+
+            if cache.details:
+                for key, value in vars(cache.details).iteritems():
+                    cachecmd.details.append({
+                                            'key': key,
+                                            'value': value
+                                            })
+            self.apiClient.createSecondaryStagingStore(cachecmd)
+
+    def createnetworks(self, networks, zoneId):
+        if networks is None:
+            return
+        for network in networks:
+            networkcmd = createNetwork.createNetworkCmd()
+            networkcmd.displaytext = network.displaytext
+            networkcmd.name = network.name
+            networkcmd.networkofferingid = network.networkofferingid
+            networkcmd.zoneid = zoneId
+
+            ipranges = network.ipranges
+            if ipranges:
+                iprange = ipranges.pop()
+                networkcmd.startip = iprange.startip
+                networkcmd.endip = iprange.endip
+                networkcmd.gateway = iprange.gateway
+                networkcmd.netmask = iprange.netmask
+
+            networkcmdresponse = self.apiClient.createNetwork(networkcmd)
+            networkId = networkcmdresponse.id
+            return networkId
+
+    def createPhysicalNetwork(self, net, zoneid):
+        phynet = createPhysicalNetwork.createPhysicalNetworkCmd()
+        phynet.zoneid = zoneid
+        phynet.name = net.name
+        phynet.isolationmethods = net.isolationmethods
+        phynetwrk = self.apiClient.createPhysicalNetwork(phynet)
+        self.addTrafficTypes(phynetwrk.id, net.traffictypes)
+        return phynetwrk
+
+    def updatePhysicalNetwork(self, networkid, state="Enabled", vlan=None):
+        upnet = updatePhysicalNetwork.updatePhysicalNetworkCmd()
+        upnet.id = networkid
+        upnet.state = state
+        if vlan:
+            upnet.vlan = vlan
+        return self.apiClient.updatePhysicalNetwork(upnet)
+
+    def enableProvider(self, provider_id):
+        upnetprov =\
+            updateNetworkServiceProvider.updateNetworkServiceProviderCmd()
+        upnetprov.id = provider_id
+        upnetprov.state = "Enabled"
+        self.apiClient.updateNetworkServiceProvider(upnetprov)
+
+    def configureProviders(self, phynetwrk, providers):
+        """
+        We will enable the virtualrouter elements for all zones. Other
+        providers like NetScalers, SRX, etc are explicitly added/configured
+        """
+
+        for provider in providers:
+            pnetprov = listNetworkServiceProviders.\
+                listNetworkServiceProvidersCmd()
+            pnetprov.physicalnetworkid = phynetwrk.id
+            pnetprov.state = "Disabled"
+            pnetprov.name = provider.name
+            pnetprovres = self.apiClient.listNetworkServiceProviders(pnetprov)
+
+            if pnetprovres and len(pnetprovres) > 0:
+                if provider.name == 'VirtualRouter'\
+                   or provider.name == 'VpcVirtualRouter':
+                    vrprov = listVirtualRouterElements.\
+                        listVirtualRouterElementsCmd()
+                    vrprov.nspid = pnetprovres[0].id
+                    vrprovresponse = self.apiClient.\
+                        listVirtualRouterElements(vrprov)
+                    vrprovid = vrprovresponse[0].id
+
+                    vrconfig = \
+                        configureVirtualRouterElement.\
+                        configureVirtualRouterElementCmd()
+                    vrconfig.enabled = "true"
+                    vrconfig.id = vrprovid
+                    self.apiClient.configureVirtualRouterElement(vrconfig)
+                    self.enableProvider(pnetprovres[0].id)
+                elif provider.name == 'InternalLbVm':
+                    internallbprov = listInternalLoadBalancerElements.\
+                        listInternalLoadBalancerElementsCmd()
+                    internallbprov.nspid = pnetprovres[0].id
+                    internallbresponse = self.apiClient.\
+                        listInternalLoadBalancerElements(internallbprov)
+                    internallbid = internallbresponse[0].id
+
+                    internallbconfig = \
+                        configureInternalLoadBalancerElement.\
+                        configureInternalLoadBalancerElementCmd()
+                    internallbconfig.enabled = "true"
+                    internallbconfig.id = internallbid
+                    self.apiClient.\
+                        configureInternalLoadBalancerElement(internallbconfig)
+                    self.enableProvider(pnetprovres[0].id)
+                elif provider.name == 'SecurityGroupProvider':
+                    self.enableProvider(pnetprovres[0].id)
+            elif provider.name in ['Netscaler', 'JuniperSRX', 'F5BigIp']:
+                netprov = addNetworkServiceProvider.\
+                    addNetworkServiceProviderCmd()
+                netprov.name = provider.name
+                netprov.physicalnetworkid = phynetwrk.id
+                result = self.apiClient.addNetworkServiceProvider(netprov)
+                for device in provider.devices:
+                    if provider.name == 'Netscaler':
+                        dev = addNetscalerLoadBalancer.\
+                            addNetscalerLoadBalancerCmd()
+                        dev.username = device.username
+                        dev.password = device.password
+                        dev.networkdevicetype = device.networkdevicetype
+                        dev.url = configGenerator.getDeviceUrl(device)
+                        dev.physicalnetworkid = phynetwrk.id
+                        self.apiClient.addNetscalerLoadBalancer(dev)
+                    elif provider.name == 'JuniperSRX':
+                        dev = addSrxFirewall.addSrxFirewallCmd()
+                        dev.username = device.username
+                        dev.password = device.password
+                        dev.networkdevicetype = device.networkdevicetype
+                        dev.url = configGenerator.getDeviceUrl(device)
+                        dev.physicalnetworkid = phynetwrk.id
+                        self.apiClient.addSrxFirewall(dev)
+                    elif provider.name == 'F5BigIp':
+                        dev = addF5LoadBalancer.addF5LoadBalancerCmd()
+                        dev.username = device.username
+                        dev.password = device.password
+                        dev.networkdevicetype = device.networkdevicetype
+                        dev.url = configGenerator.getDeviceUrl(device)
+                        dev.physicalnetworkid = phynetwrk.id
+                        self.apiClient.addF5LoadBalancer(dev)
+                    else:
+                        raise cloudstackException.\
+                            InvalidParameterException("Device %s doesn't match\
+ any know provider type" % device)
+                self.enableProvider(result.id)
+
+    def addTrafficTypes(self, physical_network_id, traffictypes):
+        [self.addTrafficType(physical_network_id, traffic_type)
+            for traffic_type in traffictypes]
+
+    def addTrafficType(self, physical_network_id, traffictype):
+        traffic_type = addTrafficType.addTrafficTypeCmd()
+        traffic_type.physicalnetworkid = physical_network_id
+        traffic_type.traffictype = traffictype.typ
+        traffic_type.kvmnetworklabel = traffictype.kvm\
+            if traffictype.kvm is not None else None
+        traffic_type.xennetworklabel = traffictype.xen\
+            if traffictype.xen is not None else None
+        traffic_type.vmwarenetworklabel = traffictype.vmware\
+            if traffictype.vmware is not None else None
+        traffic_type.simulatorlabel = traffictype.simulator\
+            if traffictype.simulator is not None else None
+        return self.apiClient.addTrafficType(traffic_type)
+
+    def enableZone(self, zoneid, allocation_state="Enabled"):
+        zoneCmd = updateZone.updateZoneCmd()
+        zoneCmd.id = zoneid
+        zoneCmd.allocationstate = allocation_state
+        return self.apiClient.updateZone(zoneCmd)
+
+    def updateZoneDetails(self, zoneid, details):
+        zoneCmd = updateZone.updateZoneCmd()
+        zoneCmd.id = zoneid
+        zoneCmd.details = details
+        return self.apiClient.updateZone(zoneCmd)
+
+    def createZones(self, zones):
+        for zone in zones:
+            createzone = createZone.createZoneCmd()
+            createzone.dns1 = zone.dns1
+            createzone.dns2 = zone.dns2
+            createzone.internaldns1 = zone.internaldns1
+            createzone.internaldns2 = zone.internaldns2
+            createzone.name = zone.name
+            createzone.securitygroupenabled = zone.securitygroupenabled
+            createzone.localstorageenabled = zone.localstorageenabled
+            createzone.networktype = zone.networktype
+            if zone.securitygroupenabled != "true":
+                createzone.guestcidraddress = zone.guestcidraddress
+
+            zoneresponse = self.apiClient.createZone(createzone)
+            zoneId = zoneresponse.id
+
+            for pnet in zone.physical_networks:
+                phynetwrk = self.createPhysicalNetwork(pnet, zoneId)
+                self.configureProviders(phynetwrk, pnet.providers)
+                self.updatePhysicalNetwork(phynetwrk.id, "Enabled",
+                                           vlan=pnet.vlan)
+
+            if zone.networktype == "Basic":
+                listnetworkoffering =\
+                    listNetworkOfferings.listNetworkOfferingsCmd()
+                listnetworkoffering.name =\
+                    "DefaultSharedNetscalerEIPandELBNetworkOffering" \
+                    if len(filter(lambda x:
+                                  x.typ == 'Public',
+                                  zone.physical_networks[0].
+                                  traffictypes)) > 0 \
+                    else "DefaultSharedNetworkOfferingWithSGService"
+                if zone.networkofferingname is not None:
+                    listnetworkoffering.name = zone.networkofferingname
+
+                listnetworkofferingresponse = \
+                    self.apiClient.listNetworkOfferings(listnetworkoffering)
+
+                guestntwrk = configGenerator.network()
+                guestntwrk.displaytext = "guestNetworkForBasicZone"
+                guestntwrk.name = "guestNetworkForBasicZone"
+                guestntwrk.zoneid = zoneId
+                guestntwrk.networkofferingid = \
+                    listnetworkofferingresponse[0].id
+
+                networkid = self.createnetworks([guestntwrk], zoneId)
+                self.createpods(zone.pods, zoneId, networkid)
+                if self.isEipElbZone(zone):
+                    self.createVlanIpRanges(zone.networktype, zone.ipranges,
+                                            zoneId, forvirtualnetwork=True)
+
+            isPureAdvancedZone = (zone.networktype == "Advanced"
+                                  and zone.securitygroupenabled != "true")
+            if isPureAdvancedZone:
+                self.createpods(zone.pods, zoneId)
+                self.createVlanIpRanges(zone.networktype, zone.ipranges,
+                                        zoneId)
+            elif (zone.networktype == "Advanced"
+                  and zone.securitygroupenabled == "true"):
+                listnetworkoffering =\
+                    listNetworkOfferings.listNetworkOfferingsCmd()
+                listnetworkoffering.name =\
+                    "DefaultSharedNetworkOfferingWithSGService"
+                if zone.networkofferingname is not None:
+                    listnetworkoffering.name = zone.networkofferingname
+
+                listnetworkofferingresponse = \
+                    self.apiClient.listNetworkOfferings(listnetworkoffering)
+
+                networkcmd = createNetwork.createNetworkCmd()
+                networkcmd.displaytext = "Shared SG enabled network"
+                networkcmd.name = "Shared SG enabled network"
+                networkcmd.networkofferingid =\
+                    listnetworkofferingresponse[0].id
+                networkcmd.zoneid = zoneId
+
+                ipranges = zone.ipranges
+                if ipranges:
+                    iprange = ipranges.pop()
+                    networkcmd.startip = iprange.startip
+                    networkcmd.endip = iprange.endip
+                    networkcmd.gateway = iprange.gateway
+                    networkcmd.netmask = iprange.netmask
+                    networkcmd.vlan = iprange.vlan
+
+                networkcmdresponse = self.apiClient.createNetwork(networkcmd)
+                networkId = networkcmdresponse.id
+                self.createpods(zone.pods, zoneId, networkId)
+
+            '''Note: Swift needs cache storage first'''
+            self.createCacheStorages(zone.cacheStorages, zoneId)
+            self.createSecondaryStorages(zone.secondaryStorages, zoneId)
+
+            enabled = getattr(zone, 'enabled', 'True')
+            if enabled == 'True' or enabled is None:
+                self.enableZone(zoneId, "Enabled")
+            details = getattr(zone, 'details')
+            if details is not None:
+                det = [d.__dict__ for d in details]
+                self.updateZoneDetails(zoneId, det)
+
+        return
+
+    def isEipElbZone(self, zone):
+        if (zone.networktype == "Basic"
+            and len(filter(lambda x: x.typ == 'Public',
+                           zone.physical_networks[0].traffictypes)) > 0):
+            return True
+        return False
+
+    def registerApiKey(self):
+        listuser = listUsers.listUsersCmd()
+        listuser.account = "admin"
+        listuserRes = self.testClient.getApiClient().listUsers(listuser)
+        userId = listuserRes[0].id
+        apiKey = listuserRes[0].apikey
+        securityKey = listuserRes[0].secretkey
+        if apiKey is None:
+            registerUser = registerUserKeys.registerUserKeysCmd()
+            registerUser.id = userId
+            registerUserRes = \
+                self.testClient.getApiClient().registerUserKeys(registerUser)
+
+            apiKey = registerUserRes.apikey
+            securityKey = registerUserRes.secretkey
+
+        self.config.mgtSvr[0].port = 8080
+        self.config.mgtSvr[0].apiKey = apiKey
+        self.config.mgtSvr[0].securityKey = securityKey
+        return apiKey, securityKey
+
+    def getCfg(self):
+        if self.config is not None:
+            return self.config
+        return None
+
+    def loadCfg(self):
+        try:
+            self.config = configGenerator.get_setup_config(self.configFile)
+        except:
+            raise cloudstackException.InvalidParameterException(
+                "Failed to load deployer %s" % self.configFile)
+
+        mgt = self.config.mgtSvr[0]
+
+        loggers = self.config.logger
+        testClientLogFile = None
+        self.testCaseLogFile = None
+        self.testResultLogFile = None
+        if loggers is not None and len(loggers) > 0:
+            for log in loggers:
+                if log.name == "TestClient":
+                    testClientLogFile = log.file
+                elif log.name == "TestCase":
+                    self.testCaseLogFile = log.file
+                elif log.name == "TestResult":
+                    self.testResultLogFile = log.file
+
+        testClientLogger = None
+        if testClientLogFile is not None:
+            testClientLogger = logging.getLogger("testclient.testengine.run")
+            fh = logging.FileHandler(testClientLogFile)
+            fh.setFormatter(logging.
+                            Formatter("%(asctime)s - %(levelname)s - %(name)s\
+ - %(message)s"))
+            testClientLogger.addHandler(fh)
+            testClientLogger.setLevel(logging.INFO)
+        self.testClientLogger = testClientLogger
+
+        self.testClient = \
+            cloudstackTestClient.\
+            cloudstackTestClient(mgt.mgtSvrIp, mgt.port, mgt.user, mgt.passwd,
+                                 mgt.apiKey, mgt.securityKey,
+                                 logging=self.testClientLogger)
+        if mgt.apiKey is None:
+            apiKey, securityKey = self.registerApiKey()
+            self.testClient = cloudstackTestClient.cloudstackTestClient(
+                mgt.mgtSvrIp, 8080,
+                mgt.user, mgt.passwd,
+                apiKey, securityKey,
+                logging=self.testClientLogger)
+
+        """deployer database"""
+        dbSvr = self.config.dbSvr
+        if dbSvr is not None:
+            self.testClient.dbConfigure(dbSvr.dbSvr, dbSvr.port, dbSvr.user,
+                                        dbSvr.passwd, dbSvr.db)
+
+        self.apiClient = self.testClient.getApiClient()
+        """set hypervisor"""
+        if mgt.hypervisor:
+            self.apiClient.hypervisor = mgt.hypervisor
+        else:
+            self.apiClient.hypervisor = "XenServer"  # Defaults to Xenserver
+
+    def updateConfiguration(self, globalCfg):
+        if globalCfg is None:
+            return None
+
+        for config in globalCfg:
+            updateCfg = updateConfiguration.updateConfigurationCmd()
+            updateCfg.name = config.name
+            updateCfg.value = config.value
+            self.apiClient.updateConfiguration(updateCfg)
+
+    def copyAttributesToCommand(self, source, command):
+
+        map(lambda attr: setattr(command, attr, getattr(source, attr, None)),
+            filter(lambda attr: not attr.startswith("__") and
+            attr not in ["required", "isAsync"], dir(command)))
+
+    def configureS3(self, s3):
+        if s3 is None:
+            return
+
+        command = addS3.addS3Cmd()
+        self.copyAttributesToCommand(s3, command)
+        self.apiClient.addS3(command)
+
+    def deploy(self):
+        self.loadCfg()
+        self.updateConfiguration(self.config.globalConfig)
+        self.createZones(self.config.zones)
+        self.configureS3(self.config.s3)
+
+if __name__ == "__main__":
+
+    parser = OptionParser()
+
+    parser.add_option("-i", "--input", action="store",
+                      default="./datacenterCfg", dest="input", help="the path \
+                      where the json deployer file generated, by default is \
+                      ./datacenterCfg")
+
+    (options, args) = parser.parse_args()
+
+    deploy = deployDataCenters(options.input)
+    deploy.deploy()
+
+    """
+    create = createStoragePool.createStoragePoolCmd()
+    create.clusterid = 1
+    create.podid = 2
+    create.name = "fdffdf"
+    create.url = "nfs://jfkdjf/fdkjfkd"
+    create.zoneid = 2
+
+    deploy = deployDataCenters("./datacenterCfg")
+    deploy.loadCfg()
+    deploy.apiClient.createStoragePool(create)
+    """


[20/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: remove redundant examples from sandbox

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/32a42f4f
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/32a42f4f
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/32a42f4f

Branch: refs/heads/marvin-refactor
Commit: 32a42f4f036b47aefc4c6fc3fef4d496d44b8c67
Parents: ffb7820
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Sat Sep 7 11:04:28 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:31 2013 +0530

----------------------------------------------------------------------
 .../marvin/sandbox/demo/live/testSshDeployVM.py |  128 --
 .../marvin/sandbox/demo/simulator/__init__.py   |   18 -
 .../sandbox/demo/simulator/simulator_setup.py   |  151 --
 .../demo/simulator/simulatordemo.properties     |   62 -
 .../sandbox/demo/simulator/testcase/__init__.py |   18 -
 .../demo/simulator/testcase/libs/__init__.py    |   18 -
 .../demo/simulator/testcase/libs/base.py        | 1436 ------------------
 .../demo/simulator/testcase/libs/common.py      |  460 ------
 .../demo/simulator/testcase/libs/utils.py       |  115 --
 .../simulator/testcase/test_vm_life_cycle.py    |  524 -------
 10 files changed, 2930 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/32a42f4f/tools/marvin/marvin/sandbox/demo/live/testSshDeployVM.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/demo/live/testSshDeployVM.py b/tools/marvin/marvin/sandbox/demo/live/testSshDeployVM.py
deleted file mode 100644
index 5438e40..0000000
--- a/tools/marvin/marvin/sandbox/demo/live/testSshDeployVM.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-
-
-import marvin
-from marvin.cloudstackTestCase import *
-from marvin.remoteSSHClient import remoteSSHClient 
-
-
-@UserName('demo', 'ROOT', '0')
-class TestSshDeployVm(cloudstackTestCase):
-    """
-    This test deploys a virtual machine into a user account 
-    using the small service offering and builtin template
-    """
-    def setUp(self):
-        self.apiClient = self.testClient.getApiClient()
-
-        self.zone = listZones.listZonesCmd()
-        self.zone.uuid = self.apiClient.listZones(self.zone)[0].id
-
-        self.service_offering = listServiceOfferings.listServiceOfferingsCmd()
-        self.service_offering.uuid = self.apiClient.listServiceOfferings(self.service_offering)[0].id
-
-        self.template = listTemplates.listTemplatesCmd()
-        self.template.templatefilter = 'featured'
-        self.template.name = 'CentOS'
-        self.template.uuid = self.apiClient.listTemplates(self.template)[0].id
-
-    def test_DeployVm(self):
-        """
-        Let's start by defining the attributes of our VM that we will be
-        deploying on CloudStack. We will be assuming a single zone is available
-        and is configured and all templates are Ready
-
-        The hardcoded values are used only for brevity. 
-        """
-        deployVmCmd = deployVirtualMachine.deployVirtualMachineCmd()
-        deployVmCmd.zoneid = self.zone.uuid
-        deployVmCmd.templateid = self.template.uuid #CentOS 5.6 builtin
-        deployVmCmd.serviceofferingid = self.service_offering.uuid
-
-        deployVmResponse = self.apiClient.deployVirtualMachine(deployVmCmd)
-        self.debug("VM %s was deployed in the job %s"%(deployVmResponse.id, deployVmResponse.jobid))
-
-        # At this point our VM is expected to be Running. Let's find out what
-        # listVirtualMachines tells us about VMs in this account
-
-        listVmCmd = listVirtualMachines.listVirtualMachinesCmd()
-        listVmCmd.id = deployVmResponse.id
-        listVmResponse = self.apiClient.listVirtualMachines(listVmCmd)
-
-        self.assertNotEqual(len(listVmResponse), 0, "Check if the list API \
-                            returns a non-empty response")
-
-        vm = listVmResponse[0]
-        self.assertEqual(vm.state, "Running", "Check if VM has reached Running state in CS")
-
-        hostname = vm.name
-        nattedip = self.setUpNAT(vm.id)
-
-        self.assertEqual(vm.id, deployVmResponse.id, "Check if the VM returned \
-                         is the same as the one we deployed")
-
-
-        self.assertEqual(vm.state, "Running", "Check if VM has reached \
-                         a state of running")
-
-        # SSH login and compare hostname        
-        self.debug("Attempting to SSH into %s over %s of %s"%(nattedip, "22", vm.name))
-        ssh_client = remoteSSHClient(nattedip, "22", "root", "password")
-        stdout = ssh_client.execute("hostname")
-
-        self.assertEqual(hostname, stdout[0], "cloudstack VM name and hostname \
-                         do not match")
-
-    def setUpNAT(self, virtualmachineid):
-        listSourceNat = listPublicIpAddresses.listPublicIpAddressesCmd()
-        listSourceNat.issourcenat = True
-
-        listsnatresponse = self.apiClient.listPublicIpAddresses(listSourceNat)
-        self.assertNotEqual(len(listsnatresponse), 0, "Found a source NAT for the account user")
-
-        snatid = listsnatresponse[0].id
-        snatip = listsnatresponse[0].ipaddress
-
-        try:
-            createFwRule = createFirewallRule.createFirewallRuleCmd()
-            createFwRule.cidrlist = "0.0.0.0/0"
-            createFwRule.startport = 22
-            createFwRule.endport = 22
-            createFwRule.ipaddressid = snatid
-            createFwRule.protocol = "tcp"
-            createfwresponse = self.apiClient.createFirewallRule(createFwRule)
-
-            createPfRule = createPortForwardingRule.createPortForwardingRuleCmd()
-            createPfRule.publicport = 22
-            createPfRule.privateport = 22
-            createPfRule.virtualmachineid = virtualmachineid
-            createPfRule.ipaddressid = snatid
-            createPfRule.protocol = "tcp"
-
-            createpfresponse = self.apiClient.createPortForwardingRule(createPfRule)
-        except e:
-            self.debug("Failed to create PF rule in the account due to %s"%e)
-            raise e
-        finally:
-            self.debug("Successfully programmed PF rule for :%s"%snatip)
-            return snatip        
-
-    def tearDown(self):
-        self.testClient.close()

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/32a42f4f/tools/marvin/marvin/sandbox/demo/simulator/__init__.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/demo/simulator/__init__.py b/tools/marvin/marvin/sandbox/demo/simulator/__init__.py
deleted file mode 100644
index 57823fc..0000000
--- a/tools/marvin/marvin/sandbox/demo/simulator/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/32a42f4f/tools/marvin/marvin/sandbox/demo/simulator/simulator_setup.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/demo/simulator/simulator_setup.py b/tools/marvin/marvin/sandbox/demo/simulator/simulator_setup.py
deleted file mode 100644
index 65294f2..0000000
--- a/tools/marvin/marvin/sandbox/demo/simulator/simulator_setup.py
+++ /dev/null
@@ -1,151 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-
-import marvin
-from ConfigParser import SafeConfigParser
-from optparse import OptionParser
-from marvin.configGenerator import *
-import random
-
-
-def getGlobalSettings(config):
-   for k, v in dict(config.items('globals')).iteritems():
-        cfg = configuration()
-        cfg.name = k
-        cfg.value = v
-        yield cfg
-
-
-def describeResources(config):
-    zs = cloudstackConfiguration()
-
-    z = zone()
-    z.dns1 = config.get('environment', 'dns')
-    z.internaldns1 = config.get('environment', 'dns')
-    z.name = 'Sandbox-%s'%(config.get('environment', 'hypervisor'))
-    z.networktype = 'Advanced'
-    z.guestcidraddress = '10.1.1.0/24'
-    z.securitygroupenabled = 'false'
-    
-    vpcprovider = provider()
-    vpcprovider.name = 'VpcVirtualRouter'
-    
-    pn = physical_network()
-    pn.name = "Sandbox-pnet"
-    pn.traffictypes = [traffictype("Guest"), traffictype("Management"), traffictype("Public")]
-    pn.isolationmethods = ["VLAN"]
-    pn.providers.append(vpcprovider)
-    pn.vlan = config.get('cloudstack', 'zone.vlan')
-    pn.isolationmethods = ['VLAN']
-    
-    z.physical_networks.append(pn)
-
-    p = pod()
-    p.name = 'POD0'
-    p.gateway = config.get('cloudstack', 'private.gateway')
-    p.startip =  config.get('cloudstack', 'private.pod.startip')
-    p.endip =  config.get('cloudstack', 'private.pod.endip')
-    p.netmask = '255.255.255.0'
-
-    v = iprange()
-    v.gateway = config.get('cloudstack', 'public.gateway')
-    v.startip = config.get('cloudstack', 'public.vlan.startip')
-    v.endip = config.get('cloudstack', 'public.vlan.endip') 
-    v.netmask = '255.255.255.0'
-    v.vlan = config.get('cloudstack', 'public.vlan')
-    z.ipranges.append(v)
-
-    c = cluster()
-    c.clustername = 'C0'
-    c.hypervisor = config.get('environment', 'hypervisor')
-    c.clustertype = 'CloudManaged'
-
-    h = host()
-    h.username = 'root'
-    h.password = 'password'
-    h.url = 'http://%s'%(config.get('cloudstack', 'host'))
-    c.hosts.append(h)
-    
-    h = host()
-    h.username = 'root'
-    h.password = 'password'
-    h.url = 'http://%s'%(config.get('cloudstack', 'host2'))
-    c.hosts.append(h)
-
-    ps = primaryStorage()
-    ps.name = 'PS0'
-    ps.url = config.get('cloudstack', 'pool')
-    c.primaryStorages.append(ps)
-
-    p.clusters.append(c)
-    z.pods.append(p)
-
-    secondary = secondaryStorage()
-    secondary.url = config.get('cloudstack', 'secondary')
-    z.secondaryStorages.append(secondary)
-
-    '''Add zone'''
-    zs.zones.append(z)
-
-    '''Add mgt server'''
-    mgt = managementServer()
-    mgt.mgtSvrIp = config.get('environment', 'mshost')
-    mgt.user = config.get('environment', 'mshost.user')
-    mgt.passwd = config.get('environment', 'mshost.passwd')
-    zs.mgtSvr.append(mgt)
-
-    '''Add a database'''
-    db = dbServer()
-    db.dbSvr = config.get('environment', 'mysql.host')
-    db.user = config.get('environment', 'mysql.cloud.user')
-    db.passwd = config.get('environment', 'mysql.cloud.passwd')
-    zs.dbSvr = db
-
-    '''Add some configuration'''
-    [zs.globalConfig.append(cfg) for cfg in getGlobalSettings(config)]
-
-    ''''add loggers'''
-    testClientLogger = logger()
-    testClientLogger.name = 'TestClient'
-    testClientLogger.file = '/var/log/testclient.log'
-
-    testCaseLogger = logger()
-    testCaseLogger.name = 'TestCase'
-    testCaseLogger.file = '/var/log/testcase.log'
-
-    zs.logger.append(testClientLogger)
-    zs.logger.append(testCaseLogger)
-    return zs
-
-
-if __name__ == '__main__':
-    parser = OptionParser()
-    parser.add_option('-i', '--input', action='store', default='setup.properties', \
-                      dest='input', help='file containing environment setup information')
-    parser.add_option('-o', '--output', action='store', default='./sandbox.cfg', \
-                      dest='output', help='path where environment json will be generated')
-
-
-    (opts, args) = parser.parse_args()
-
-    cfg_parser = SafeConfigParser()
-    cfg_parser.read(opts.input)
-
-    cfg = describeResources(cfg_parser)
-    generate_setup_config(cfg, opts.output)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/32a42f4f/tools/marvin/marvin/sandbox/demo/simulator/simulatordemo.properties
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/demo/simulator/simulatordemo.properties b/tools/marvin/marvin/sandbox/demo/simulator/simulatordemo.properties
deleted file mode 100644
index 9d9f14b..0000000
--- a/tools/marvin/marvin/sandbox/demo/simulator/simulatordemo.properties
+++ /dev/null
@@ -1,62 +0,0 @@
-# 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.
-
-
-[globals]
-expunge.delay=60
-expunge.interval=60
-storage.cleanup.interval=300
-account.cleanup.interval=600
-expunge.workers=3
-workers=10
-use.user.concentrated.pod.allocation=false
-vm.allocation.algorithm=random
-vm.op.wait.interval=5
-guest.domain.suffix=sandbox.simulator
-instance.name=QA
-direct.agent.load.size=1000
-default.page.size=10000
-check.pod.cidrs=true
-network.gc.interval=60
-network.gc.wait=60
-secstorage.allowed.internal.sites=10.147.28.0/24
-[environment]
-dns=10.147.28.6
-mshost=localhost
-mshost.user=root
-mshost.passwd=password
-mysql.host=localhost
-mysql.cloud.user=cloud
-mysql.cloud.passwd=cloud
-hypervisor=simulator
-[cloudstack]
-zone.vlan=100-200
-#pod configuration
-private.gateway=172.16.15.1
-private.pod.startip=172.16.15.2
-private.pod.endip=172.16.15.200
-#public vlan range
-public.gateway=192.168.2.1
-public.vlan=50
-public.vlan.startip=192.168.2.2
-public.vlan.endip=192.168.2.200
-#hosts
-host=sim/c0/h0
-host2=sim/c0/h1
-#pools
-pool=nfs://10.147.28.6:/export/home/sandbox/primary
-secondary=nfs://10.147.28.6:/export/home/sandbox/secondary

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/32a42f4f/tools/marvin/marvin/sandbox/demo/simulator/testcase/__init__.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/demo/simulator/testcase/__init__.py b/tools/marvin/marvin/sandbox/demo/simulator/testcase/__init__.py
deleted file mode 100644
index 57823fc..0000000
--- a/tools/marvin/marvin/sandbox/demo/simulator/testcase/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/32a42f4f/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/__init__.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/__init__.py b/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/__init__.py
deleted file mode 100644
index 57823fc..0000000
--- a/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/32a42f4f/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/base.py b/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/base.py
deleted file mode 100644
index 7c8546c..0000000
--- a/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/base.py
+++ /dev/null
@@ -1,1436 +0,0 @@
-# -*- encoding: utf-8 -*-
-# 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.
-
-""" Base class for all Cloudstack resources
-    -Virtual machine, Volume, Snapshot etc
-"""
-
-from utils import is_server_ssh_ready, random_gen
-from marvin.cloudstackAPI import *
-#Import System modules
-import time
-import hashlib
-import base64
-import types
-
-
-class Domain:
-    """ Domain Life Cycle """
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, name=None, networkdomain=None,
-               parentdomainid=None):
-        """Creates an domain"""
-
-        cmd = createDomain.createDomainCmd()
-
-        if name:
-            cmd.name = "-".join([name, random_gen()])
-        elif "name" in services:
-            cmd.name = "-".join([services["name"], random_gen()])
-
-        if networkdomain:
-            cmd.networkdomain = networkdomain
-        elif "networkdomain" in services:
-            cmd.networkdomain = services["networkdomain"]
-
-        if parentdomainid:
-            cmd.parentdomainid = parentdomainid
-        elif "parentdomainid" in services:
-            cmd.parentdomainid = services["parentdomainid"]
-
-        return Domain(apiclient.createDomain(cmd).__dict__)
-
-    def delete(self, apiclient, cleanup=None):
-        """Delete an domain"""
-        cmd = deleteDomain.deleteDomainCmd()
-        cmd.id = self.id
-        if cleanup:
-            cmd.cleanup = cleanup
-        apiclient.deleteDomain(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists domains"""
-        cmd = listDomains.listDomainsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listDomains(cmd))
-
-
-class Account:
-    """ Account Life Cycle """
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, admin=False, domainid=None):
-        """Creates an account"""
-        cmd = createAccount.createAccountCmd()
-
-        #0 - User, 1 - Root Admin, 2 - Domain Admin
-        cmd.accounttype = 2 if (admin and domainid) else int(admin)
-
-        cmd.email = services["email"]
-        cmd.firstname = services["firstname"]
-        cmd.lastname = services["lastname"]
-
-        # Password Encoding
-        mdf = hashlib.md5()
-        mdf.update(services["password"])
-        cmd.password = mdf.hexdigest()
-        cmd.username = "-".join([services["username"], random_gen()])
-
-        if domainid:
-            cmd.domainid = domainid
-        account = apiclient.createAccount(cmd)
-
-        return Account(account.__dict__)
-
-    def delete(self, apiclient):
-        """Delete an account"""
-        cmd = deleteAccount.deleteAccountCmd()
-        cmd.id = self.account.id
-        apiclient.deleteAccount(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists accounts and provides detailed account information for
-        listed accounts"""
-
-        cmd = listAccounts.listAccountsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listAccounts(cmd))
-
-
-class User:
-    """ User Life Cycle """
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, account, domainid):
-        cmd = createUser.createUserCmd()
-        """Creates an user"""
-
-        cmd.account = account
-        cmd.domainid = domainid
-        cmd.email = services["email"]
-        cmd.firstname = services["firstname"]
-        cmd.lastname = services["lastname"]
-
-        # Password Encoding
-        mdf = hashlib.md5()
-        mdf.update(services["password"])
-        cmd.password = mdf.hexdigest()
-        cmd.username = "-".join([services["username"], random_gen()])
-        user = apiclient.createUser(cmd)
-
-        return User(user.__dict__)
-
-    def delete(self, apiclient):
-        """Delete an account"""
-        cmd = deleteUser.deleteUserCmd()
-        cmd.id = self.id
-        apiclient.deleteUser(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists users and provides detailed account information for
-        listed users"""
-
-        cmd = listUsers.listUsersCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listUsers(cmd))
-
-
-class VirtualMachine:
-    """Manage virtual machine lifecycle"""
-
-    def __init__(self, items, services):
-        self.__dict__.update(items)
-        self.username = services["username"]
-        self.password = services["password"]
-        self.ssh_port = services["ssh_port"]
-        self.ssh_client = None
-        #extract out the ipaddress
-        self.ipaddress = self.nic[0].ipaddress
-
-    @classmethod
-    def create(cls, apiclient, services, templateid=None, accountid=None,
-                    domainid=None, networkids=None, serviceofferingid=None,
-                    securitygroupids=None, mode='basic'):
-        """Create the instance"""
-        
-        cmd = deployVirtualMachine.deployVirtualMachineCmd()
-        
-        if serviceofferingid:
-            cmd.serviceofferingid = serviceofferingid
-        elif "serviceoffering" in services:
-            cmd.serviceofferingid = services["serviceoffering"]
-
-        cmd.zoneid = services["zoneid"]
-        cmd.hypervisor = services["hypervisor"]
-
-        if accountid:
-            cmd.account = accountid
-        elif "account" in services:
-            cmd.account = services["account"]
-
-        if domainid:
-            cmd.domainid = domainid
-        elif "domainid" in services:
-            cmd.domainid = services["domainid"]
-
-        if networkids:
-            cmd.networkids = networkids
-        elif "networkids" in services:
-            cmd.networkids = services["networkids"]
-
-        if templateid:
-            cmd.templateid = templateid
-        elif "template" in services:
-            cmd.templateid = services["template"]
-
-        if "diskoffering" in services:
-            cmd.diskofferingid = services["diskoffering"]
-        
-        if securitygroupids:
-            cmd.securitygroupids = [str(sg_id) for sg_id in securitygroupids]
-        
-        if "userdata" in services:
-            cmd.userdata = base64.b64encode(services["userdata"])
-        
-        virtual_machine = apiclient.deployVirtualMachine(cmd)
-        
-        # VM should be in Running state after deploy
-        timeout = 10
-        while True:    
-            vm_status = VirtualMachine.list(
-                                            apiclient,
-                                            id=virtual_machine.id
-                                            )
-            if isinstance(vm_status, list):
-                if vm_status[0].state == 'Running':
-                    break
-                elif timeout == 0:
-                    raise Exception(
-                            "TimeOutException: Failed to start VM (ID: %s)" % 
-                                                        virtual_machine.id)
-            
-            time.sleep(10)
-            timeout = timeout -1
-
-        return VirtualMachine(virtual_machine.__dict__, services)
-
-    def start(self, apiclient):
-        """Start the instance"""
-        cmd = startVirtualMachine.startVirtualMachineCmd()
-        cmd.id = self.id
-        apiclient.startVirtualMachine(cmd)
-
-    def stop(self, apiclient):
-        """Stop the instance"""
-        cmd = stopVirtualMachine.stopVirtualMachineCmd()
-        cmd.id = self.id
-        apiclient.stopVirtualMachine(cmd)
-
-    def reboot(self, apiclient):
-        """Reboot the instance"""
-        cmd = rebootVirtualMachine.rebootVirtualMachineCmd()
-        cmd.id = self.id
-        apiclient.rebootVirtualMachine(cmd)
-
-
-    def delete(self, apiclient):
-        """Destroy an Instance"""
-        cmd = destroyVirtualMachine.destroyVirtualMachineCmd()
-        cmd.id = self.id
-        apiclient.destroyVirtualMachine(cmd)
-
-    def attach_volume(self, apiclient, volume):
-        """Attach volume to instance"""
-        cmd = attachVolume.attachVolumeCmd()
-        cmd.id = volume.id
-        cmd.virtualmachineid = self.id
-        return apiclient.attachVolume(cmd)
-
-    def detach_volume(self, apiclient, volume):
-        """Detach volume to instance"""
-        cmd = detachVolume.detachVolumeCmd()
-        cmd.id = volume.id
-        return apiclient.detachVolume(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all VMs matching criteria"""
-
-        cmd = listVirtualMachines.listVirtualMachinesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listVirtualMachines(cmd))
-
-
-class Volume:
-    """Manage Volume Lifecycle
-    """
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, zoneid=None, account=None, domainid=None,
-               diskofferingid=None):
-        """Create Volume"""
-        cmd = createVolume.createVolumeCmd()
-        cmd.name = services["diskname"]
-
-        if diskofferingid:
-            cmd.diskofferingid = diskofferingid
-        elif "diskofferingid" in services:
-            cmd.diskofferingid = services["diskofferingid"]
-
-        if zoneid:
-            cmd.zoneid = zoneid
-        elif "zoneid" in services:
-            cmd.zoneid = services["zoneid"]
-
-        if account:
-            cmd.account = account
-        elif "account" in services:
-            cmd.account = services["account"]
-
-        if domainid:
-            cmd.domainid = domainid
-        elif "domainid" in services:
-            cmd.domainid = services["domainid"]
-
-        return Volume(apiclient.createVolume(cmd).__dict__)
-
-    @classmethod
-    def create_custom_disk(cls, apiclient, services, account=None, domainid=None):
-        """Create Volume from Custom disk offering"""
-        cmd = createVolume.createVolumeCmd()
-        cmd.name = services["diskname"]
-        cmd.diskofferingid = services["customdiskofferingid"]
-        cmd.size = services["customdisksize"]
-        cmd.zoneid = services["zoneid"]
-        
-        if account:
-            cmd.account = account
-        else:
-            cmd.account = services["account"]
-        
-        if domainid:
-            cmd.domainid = domainid
-        else:
-            cmd.domainid = services["domainid"]
-            
-        return Volume(apiclient.createVolume(cmd).__dict__)
-
-    @classmethod
-    def create_from_snapshot(cls, apiclient, snapshot_id, services,
-                             account=None, domainid=None):
-        """Create Volume from snapshot"""
-        cmd = createVolume.createVolumeCmd()
-        cmd.name = "-".join([services["diskname"], random_gen()])
-        cmd.snapshotid = snapshot_id
-        cmd.zoneid = services["zoneid"]
-        cmd.size = services["size"]
-        if account:
-            cmd.account = account
-        else:
-            cmd.account = services["account"]
-        if domainid:
-            cmd.domainid = domainid
-        else:
-            cmd.domainid = services["domainid"]
-        return Volume(apiclient.createVolume(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Volume"""
-        cmd = deleteVolume.deleteVolumeCmd()
-        cmd.id = self.id
-        apiclient.deleteVolume(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all volumes matching criteria"""
-
-        cmd = listVolumes.listVolumesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listVolumes(cmd))
-
-
-class Snapshot:
-    """Manage Snapshot Lifecycle
-    """
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, volume_id, account=None, domainid=None):
-        """Create Snapshot"""
-        cmd = createSnapshot.createSnapshotCmd()
-        cmd.volumeid = volume_id
-        if account:
-            cmd.account = account
-        if domainid:
-            cmd.domainid = domainid
-        return Snapshot(apiclient.createSnapshot(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Snapshot"""
-        cmd = deleteSnapshot.deleteSnapshotCmd()
-        cmd.id = self.id
-        apiclient.deleteSnapshot(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all snapshots matching criteria"""
-
-        cmd = listSnapshots.listSnapshotsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listSnapshots(cmd))
-
-
-class Template:
-    """Manage template life cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, volumeid=None,
-               account=None, domainid=None):
-        """Create template from Volume"""
-        #Create template from Virtual machine and Volume ID
-        cmd = createTemplate.createTemplateCmd()
-        cmd.displaytext = services["displaytext"]
-        cmd.name = "-".join([services["name"], random_gen()])
-        cmd.ostypeid = services["ostypeid"]
-
-        cmd.isfeatured = services["isfeatured"] if "isfeatured" in services else False
-        cmd.ispublic = services["ispublic"] if "ispublic" in services else False
-        cmd.isextractable = services["isextractable"] if "isextractable" in services else False
-        cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False
-        
-        if volumeid:
-            cmd.volumeid = volumeid
-
-        if account:
-            cmd.account = account
-
-        if domainid:
-            cmd.domainid = domainid
-
-        return Template(apiclient.createTemplate(cmd).__dict__)
-
-    @classmethod
-    def register(cls, apiclient, services, zoneid=None, account=None, domainid=None):
-        """Create template from URL"""
-        
-        #Create template from Virtual machine and Volume ID
-        cmd = registerTemplate.registerTemplateCmd()
-        cmd.displaytext = services["displaytext"]
-        cmd.name = "-".join([services["name"], random_gen()])
-        cmd.format = services["format"]
-        cmd.hypervisor = services["hypervisor"]
-        cmd.ostypeid = services["ostypeid"]
-        cmd.url = services["url"]
-        
-        if zoneid:
-            cmd.zoneid = zoneid
-        else:
-            cmd.zoneid = services["zoneid"]
-
-        cmd.isfeatured = services["isfeatured"] if "isfeatured" in services else False
-        cmd.ispublic = services["ispublic"] if "ispublic" in services else False
-        cmd.isextractable = services["isextractable"] if "isextractable" in services else False
-
-        if account:
-            cmd.account = account
-
-        if domainid:
-            cmd.domainid = domainid
-        
-        # Register Template
-        template = apiclient.registerTemplate(cmd)
-    
-        if isinstance(template, list):
-            return Template(template[0].__dict__)
-
-    @classmethod
-    def create_from_snapshot(cls, apiclient, snapshot, services, random_name=True):
-        """Create Template from snapshot"""
-        #Create template from Virtual machine and Snapshot ID
-        cmd = createTemplate.createTemplateCmd()
-        cmd.displaytext = services["displaytext"]
-        cmd.name = "-".join([
-                             services["name"], 
-                             random_gen()
-                            ]) if random_name else services["name"]
-        cmd.ostypeid = services["ostypeid"]
-        cmd.snapshotid = snapshot.id
-        return Template(apiclient.createTemplate(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Template"""
-        
-        cmd = deleteTemplate.deleteTemplateCmd()
-        cmd.id = self.id
-        apiclient.deleteTemplate(cmd)
-
-    def download(self, apiclient, timeout=5, interval=60):
-        """Download Template"""
-        #Sleep to ensure template is in proper state before download
-        time.sleep(interval)
-        
-        while True:
-            template_response = Template.list(
-                                    apiclient,
-                                    id=self.id,
-                                    zoneid=self.zoneid,
-                                    templatefilter='self'
-                                    )
-            if isinstance(template_response, list):
-                
-                template = template_response[0]
-                # If template is ready,
-                # template.status = Download Complete
-                # Downloading - x% Downloaded
-                # Error - Any other string 
-                if template.status == 'Download Complete':
-                    break
-                
-                elif 'Downloaded' in template.status:
-                    time.sleep(interval)
-
-                elif 'Installing' not in template.status:
-                    raise Exception("ErrorInDownload")
-
-            elif timeout == 0:
-                break
-            
-            else:
-                time.sleep(interval)
-                timeout = timeout - 1
-        return
-                
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all templates matching criteria"""
-
-        cmd = listTemplates.listTemplatesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listTemplates(cmd))
-
-
-class Iso:
-    """Manage ISO life cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, account=None, domainid=None):
-        """Create an ISO"""
-        #Create ISO from URL
-        cmd = registerIso.registerIsoCmd()
-        cmd.displaytext = services["displaytext"]
-        cmd.name = services["name"]
-        cmd.ostypeid = services["ostypeid"]
-        cmd.url = services["url"]
-        cmd.zoneid = services["zoneid"]
-        
-        if "isextractable" in services:
-            cmd.isextractable = services["isextractable"]
-        if "isfeatured" in services:
-            cmd.isfeatured = services["isfeatured"]
-        if "ispublic" in services:
-            cmd.ispublic = services["ispublic"]
-
-        if account:
-            cmd.account = account
-        if domainid:
-            cmd.domainid = domainid
-        # Register ISO
-        iso = apiclient.registerIso(cmd)
-        
-        if iso:
-            return Iso(iso[0].__dict__)
-
-    def delete(self, apiclient):
-        """Delete an ISO"""
-        cmd = deleteIso.deleteIsoCmd()
-        cmd.id = self.id
-        apiclient.deleteIso(cmd)
-        return
-
-    def download(self, apiclient, timeout=5, interval=60):
-        """Download an ISO"""
-        #Ensuring ISO is successfully downloaded
-        while True:
-            time.sleep(interval)
-
-            cmd = listIsos.listIsosCmd()
-            cmd.id = self.id
-            iso_response = apiclient.listIsos(cmd)
-            
-            if isinstance(iso_response, list):     
-                response = iso_response[0]
-                # Again initialize timeout to avoid listISO failure
-                timeout = 5
-
-                # Check whether download is in progress(for Ex:10% Downloaded)
-                # or ISO is 'Successfully Installed'
-                if response.status == 'Successfully Installed':
-                    return
-
-                elif 'Downloaded' in response.status:
-                    time.sleep(interval)
-
-                elif 'Installing' not in response.status:
-                    raise Exception("ErrorInDownload")
-
-            elif timeout == 0:
-                raise Exception("TimeoutException")
-            else:
-                timeout = timeout - 1
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all available ISO files."""
-
-        cmd = listIsos.listIsosCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listIsos(cmd))
-
-
-class PublicIPAddress:
-    """Manage Public IP Addresses"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, accountid, zoneid=None, domainid=None,
-               services=None, networkid=None):
-        """Associate Public IP address"""
-        cmd = associateIpAddress.associateIpAddressCmd()
-        cmd.account = accountid
-        cmd.zoneid = zoneid or services["zoneid"]
-        cmd.domainid = domainid or services["domainid"]
-
-        if networkid:
-            cmd.networkid = networkid
-
-        return PublicIPAddress(apiclient.associateIpAddress(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Dissociate Public IP address"""
-        cmd = disassociateIpAddress.disassociateIpAddressCmd()
-        cmd.id = self.ipaddress.id
-        apiclient.disassociateIpAddress(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Public IPs matching criteria"""
-
-        cmd = listPublicIpAddresses.listPublicIpAddressesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listPublicIpAddresses(cmd))
-
-class NATRule:
-    """Manage port forwarding rule"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, virtual_machine, services, ipaddressid=None):
-        """Create Port forwarding rule"""
-        cmd = createPortForwardingRule.createPortForwardingRuleCmd()
-
-        if ipaddressid:
-            cmd.ipaddressid = ipaddressid
-        elif "ipaddressid" in services:
-            cmd.ipaddressid = services["ipaddressid"]
-
-        cmd.privateport = services["privateport"]
-        cmd.publicport = services["publicport"]
-        cmd.protocol = services["protocol"]
-        cmd.virtualmachineid = virtual_machine.id
-        
-        return NATRule(apiclient.createPortForwardingRule(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete port forwarding"""
-        cmd = deletePortForwardingRule.deletePortForwardingRuleCmd()
-        cmd.id = self.id
-        apiclient.deletePortForwardingRule(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all NAT rules matching criteria"""
-
-        cmd = listPortForwardingRules.listPortForwardingRulesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listPortForwardingRules(cmd))
-    
-
-class StaticNATRule:
-    """Manage Static NAT rule"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, ipaddressid=None):
-        """Creates static ip forwarding rule"""
-        
-        cmd = createIpForwardingRule.createIpForwardingRuleCmd()
-        cmd.protocol = services["protocol"]
-        cmd.startport = services["startport"]
-        
-        if "endport" in services:
-            cmd.endport = services["endport"]
-            
-        if "cidrlist" in services:
-            cmd.cidrlist = services["cidrlist"]
-        
-        if ipaddressid:
-            cmd.ipaddressid = ipaddressid
-        elif "ipaddressid" in services:
-            cmd.ipaddressid = services["ipaddressid"]
-            
-        return StaticNATRule(apiclient.createIpForwardingRule(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete IP forwarding rule"""
-        cmd = deleteIpForwardingRule.deleteIpForwardingRuleCmd()
-        cmd.id = self.id
-        apiclient.deleteIpForwardingRule(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all IP forwarding rules matching criteria"""
-
-        cmd = listIpForwardingRules.listIpForwardingRulesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listIpForwardingRules(cmd))
-    
-    @classmethod
-    def enable(cls, apiclient, ipaddressid, virtualmachineid):
-        """Enables Static NAT rule"""
-        
-        cmd = enableStaticNat.enableStaticNatCmd()
-        cmd.ipaddressid = ipaddressid
-        cmd.virtualmachineid = virtualmachineid
-        apiclient.enableStaticNat(cmd)
-        return
-        
-    @classmethod
-    def disable(cls, apiclient, ipaddressid, virtualmachineid):
-        """Disables Static NAT rule"""
-        
-        cmd = disableStaticNat.disableStaticNatCmd()
-        cmd.ipaddressid = ipaddressid
-        apiclient.disableStaticNat(cmd)
-        return
-    
-
-class FireWallRule:
-    """Manage Firewall rule"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, ipaddressid, protocol, cidrlist=None,
-               startport=None, endport=None):
-        """Create Firewall Rule"""
-        cmd = createFirewallRule.createFirewallRuleCmd()
-        cmd.ipaddressid = ipaddressid
-        cmd.protocol = protocol
-        if cidrlist:
-            cmd.cidrlist = cidrlist
-        if startport:
-            cmd.startport = startport
-        if endport:
-            cmd.endport = endport
-
-        return FireWallRule(apiclient.createFirewallRule(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Firewall rule"""
-        cmd = deleteFirewallRule.deleteFirewallRuleCmd()
-        cmd.id = self.id
-        apiclient.deleteFirewallRule(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Firewall Rules matching criteria"""
-
-        cmd = listFirewallRules.listFirewallRulesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listFirewallRules(cmd))
-
-
-class ServiceOffering:
-    """Manage service offerings cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, domainid=None):
-        """Create Service offering"""
-        cmd = createServiceOffering.createServiceOfferingCmd()
-        cmd.cpunumber = services["cpunumber"]
-        cmd.cpuspeed = services["cpuspeed"]
-        cmd.displaytext = services["displaytext"]
-        cmd.memory = services["memory"]
-        cmd.name = services["name"]
-
-        # Service Offering private to that domain
-        if domainid:
-            cmd.domainid = domainid
-
-        return ServiceOffering(apiclient.createServiceOffering(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Service offering"""
-        cmd = deleteServiceOffering.deleteServiceOfferingCmd()
-        cmd.id = self.id
-        apiclient.deleteServiceOffering(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all available service offerings."""
-
-        cmd = listServiceOfferings.listServiceOfferingsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listServiceOfferings(cmd))
-
-class DiskOffering:
-    """Manage disk offerings cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, custom=False):
-        """Create Disk offering"""
-        cmd = createDiskOffering.createDiskOfferingCmd()
-        cmd.displaytext = services["displaytext"]
-        cmd.name = services["name"]
-        if custom:
-            cmd.customized = True
-        else:
-            cmd.disksize = services["disksize"]
-        return DiskOffering(apiclient.createDiskOffering(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Disk offering"""
-        cmd = deleteDiskOffering.deleteDiskOfferingCmd()
-        cmd.id = self.id
-        apiclient.deleteDiskOffering(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all available disk offerings."""
-
-        cmd = listDiskOfferings.listDiskOfferingsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listDiskOfferings(cmd))
-
-
-class SnapshotPolicy:
-    """Manage snapshot policies"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, volumeid, services):
-        """Create Snapshot policy"""
-        cmd = createSnapshotPolicy.createSnapshotPolicyCmd()
-        cmd.intervaltype = services["intervaltype"]
-        cmd.maxsnaps = services["maxsnaps"]
-        cmd.schedule = services["schedule"]
-        cmd.timezone = services["timezone"]
-        cmd.volumeid = volumeid
-        return SnapshotPolicy(apiclient.createSnapshotPolicy(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Snapshot policy"""
-        cmd = deleteSnapshotPolicies.deleteSnapshotPoliciesCmd()
-        cmd.id = self.id
-        apiclient.deleteSnapshotPolicies(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists snapshot policies."""
-
-        cmd = listSnapshotPolicies.listSnapshotPoliciesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listSnapshotPolicies(cmd))
-
-
-class LoadBalancerRule:
-    """Manage Load Balancer rule"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, ipaddressid, accountid=None):
-        """Create Load balancing Rule"""
-
-        cmd = createLoadBalancerRule.createLoadBalancerRuleCmd()
-        cmd.publicipid = ipaddressid or services["ipaddressid"]
-        cmd.account = accountid or services["account"]
-        cmd.name = services["name"]
-        cmd.algorithm = services["alg"]
-        cmd.privateport = services["privateport"]
-        cmd.publicport = services["publicport"]
-        return LoadBalancerRule(apiclient.createLoadBalancerRule(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete load balancing rule"""
-        cmd = deleteLoadBalancerRule.deleteLoadBalancerRuleCmd()
-        cmd.id = self.id
-        apiclient.deleteLoadBalancerRule(cmd)
-        return
-
-    def assign(self, apiclient, vms):
-        """Assign virtual machines to load balancing rule"""
-        cmd = assignToLoadBalancerRule.assignToLoadBalancerRuleCmd()
-        cmd.id = self.id
-        cmd.virtualmachineids = [str(vm.id) for vm in vms]
-        apiclient.assignToLoadBalancerRule(cmd)
-        return
-
-    def remove(self, apiclient, vms):
-        """Remove virtual machines from load balancing rule"""
-        cmd = removeFromLoadBalancerRule.removeFromLoadBalancerRuleCmd()
-        cmd.id = self.id
-        cmd.virtualmachineids = [str(vm.id) for vm in vms]
-        apiclient.removeFromLoadBalancerRule(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Load balancing rules matching criteria"""
-
-        cmd = listLoadBalancerRules.listLoadBalancerRulesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listLoadBalancerRules(cmd))
-
-
-class Cluster:
-    """Manage Cluster life cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, zoneid=None, podid=None):
-        """Create Cluster"""
-        cmd = addCluster.addClusterCmd()
-        cmd.clustertype = services["clustertype"]
-        cmd.hypervisor = services["hypervisor"]
-        
-        if zoneid:
-            cmd.zoneid = zoneid
-        else:
-            cmd.zoneid = services["zoneid"]
-        
-        if podid:
-            cmd.podid = podid
-        else:
-            cmd.podid = services["podid"]
-
-        if "username" in services:
-            cmd.username = services["username"]
-        if "password" in services:
-            cmd.password = services["password"]
-        if "url" in services:
-            cmd.url = services["url"]
-        if "clustername" in services:
-            cmd.clustername = services["clustername"]
-
-        return Cluster(apiclient.addCluster(cmd)[0].__dict__)
-
-    def delete(self, apiclient):
-        """Delete Cluster"""
-        cmd = deleteCluster.deleteClusterCmd()
-        cmd.id = self.id
-        apiclient.deleteCluster(cmd)
-        return
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Clusters matching criteria"""
-
-        cmd = listClusters.listClustersCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listClusters(cmd))
-
-
-class Host:
-    """Manage Host life cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, cluster, services, zoneid=None, podid=None):
-        """Create Host in cluster"""
-        
-        cmd = addHost.addHostCmd()
-        cmd.hypervisor = services["hypervisor"]
-        cmd.url = services["url"]
-        cmd.clusterid = cluster.id
-        
-        if zoneid:
-            cmd.zoneid = zoneid
-        else:
-            cmd.zoneid = services["zoneid"]
-        
-        if podid:
-            cmd.podid = podid
-        else:
-            cmd.podid = services["podid"]
-
-        if "clustertype" in services:
-            cmd.clustertype = services["clustertype"]
-        if "username" in services:
-            cmd.username = services["username"]
-        if "password" in services:
-            cmd.password = services["password"]
-        
-        # Add host
-        host = apiclient.addHost(cmd)
-        
-        if isinstance(host, list):
-            return Host(host[0].__dict__)
-
-    def delete(self, apiclient):
-        """Delete Host"""
-        # Host must be in maintenance mode before deletion
-        cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
-        cmd.id = self.id
-        apiclient.prepareHostForMaintenance(cmd)
-        time.sleep(30)
-
-        cmd = deleteHost.deleteHostCmd()
-        cmd.id = self.id
-        apiclient.deleteHost(cmd)
-        return
-
-    def enableMaintenance(self, apiclient):
-        """enables maintenance mode Host"""
-
-        cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
-        cmd.id = self.id
-        return apiclient.prepareHostForMaintenance(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Hosts matching criteria"""
-
-        cmd = listHosts.listHostsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listHosts(cmd))
-
-
-class StoragePool:
-    """Manage Storage pools (Primary Storage)"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, clusterid=None, zoneid=None, podid=None):
-        """Create Storage pool (Primary Storage)"""
-
-        cmd = createStoragePool.createStoragePoolCmd()
-        cmd.name = services["name"]
-        
-        if podid:
-            cmd.podid = podid
-        else:
-            cmd.podid = services["podid"]
-            
-        cmd.url = services["url"]
-        if clusterid:
-            cmd.clusterid = clusterid
-        elif "clusterid" in services:
-            cmd.clusterid = services["clusterid"]
-        
-        if zoneid:
-            cmd.zoneid = zoneid
-        else:
-            cmd.zoneid = services["zoneid"]
-
-        return StoragePool(apiclient.createStoragePool(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Storage pool (Primary Storage)"""
-
-        # Storage pool must be in maintenance mode before deletion
-        cmd = enableStorageMaintenance.enableStorageMaintenanceCmd()
-        cmd.id = self.id
-        apiclient.enableStorageMaintenance(cmd)
-        time.sleep(30)
-        cmd = deleteStoragePool.deleteStoragePoolCmd()
-        cmd.id = self.id
-        apiclient.deleteStoragePool(cmd)
-        return
-
-    def enableMaintenance(self, apiclient):
-        """enables maintenance mode Storage pool"""
-
-        cmd = enableStorageMaintenance.enableStorageMaintenanceCmd()
-        cmd.id = self.id
-        return apiclient.enableStorageMaintenance(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all storage pools matching criteria"""
-
-        cmd = listStoragePools.listStoragePoolsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listStoragePools(cmd))
-
-
-class Network:
-    """Manage Network pools"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, accountid=None, domainid=None):
-        """Create Network for account"""
-        cmd = createNetwork.createNetworkCmd()
-        cmd.name = services["name"]
-        cmd.displaytext = services["displaytext"]
-        cmd.networkofferingid = services["networkoffering"]
-        cmd.zoneid = services["zoneid"]
-        if accountid:
-            cmd.account = accountid
-        if domainid:
-            cmd.domainid = domainid
-
-        return Network(apiclient.createNetwork(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Account"""
-
-        cmd = deleteNetwork.deleteNetworkCmd()
-        cmd.id = self.id
-        apiclient.deleteNetwork(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Networks matching criteria"""
-
-        cmd = listNetworks.listNetworksCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listNetworks(cmd))
-
-
-class Vpn:
-    """Manage VPN life cycle"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, publicipid, account=None, domainid=None):
-        """Create VPN for Public IP address"""
-        cmd = createRemoteAccessVpn.createRemoteAccessVpnCmd()
-        cmd.publicipid = publicipid
-        if account:
-            cmd.account = account
-        if domainid:
-            cmd.domainid = domainid
-
-        return Vpn(apiclient.createRemoteAccessVpn(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete remote VPN access"""
-
-        cmd = deleteRemoteAccessVpn.deleteRemoteAccessVpnCmd()
-        cmd.publicipid = self.publicipid
-        apiclient.deleteRemoteAccessVpn(cmd)
-
-
-class VpnUser:
-    """Manage VPN user"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, username, password, account=None, domainid=None):
-        """Create VPN user"""
-        cmd = addVpnUser.addVpnUserCmd()
-        cmd.username = username
-        cmd.password = password
-
-        if account:
-            cmd.account = account
-        if domainid:
-            cmd.domainid = domainid
-
-        return VpnUser(apiclient.addVpnUser(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Remove VPN user"""
-
-        cmd = removeVpnUser.removeVpnUserCmd()
-        cmd.username = self.username
-        cmd.account = self.account
-        cmd.domainid = self.domainid
-        apiclient.removeVpnUser(cmd)
-
-
-class Zone:
-    """Manage Zone"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, domainid=None):
-        """Create zone"""
-        cmd = createZone.createZoneCmd()
-        cmd.dns1 = services["dns1"]
-        cmd.internaldns1 = services["internaldns1"]
-        cmd.name = services["name"]
-        cmd.networktype = services["networktype"]
-
-        if "dns2" in services:
-            cmd.dns2 = services["dns2"]
-        if "internaldns2" in services:
-            cmd.internaldns2 = services["internaldns2"]
-        if domainid:
-            cmd.domainid = domainid
-
-        return Zone(apiclient.createZone(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Zone"""
-
-        cmd = deleteZone.deleteZoneCmd()
-        cmd.id = self.id
-        apiclient.deleteZone(cmd)
-
-    def update(self, apiclient, **kwargs):
-        """Update the zone"""
-        
-        cmd = updateZone.updateZoneCmd()
-        cmd.id = self.id
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return apiclient.updateZone(cmd)
-        
-        
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """List all Zones matching criteria"""
-
-        cmd = listZones.listZonesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listZones(cmd))
-
-
-class Pod:
-    """Manage Pod"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services):
-        """Create Pod"""
-        cmd = createPod.createPodCmd()
-        cmd.gateway = services["gateway"]
-        cmd.netmask = services["netmask"]
-        cmd.name = services["name"]
-        cmd.startip = services["startip"]
-        cmd.endip = services["endip"]
-        cmd.zoneid = services["zoneid"]
-
-        return Pod(apiclient.createPod(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Pod"""
-
-        cmd = deletePod.deletePodCmd()
-        cmd.id = self.id
-        apiclient.deletePod(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        "Returns a default pod for specified zone"
-
-        cmd = listPods.listPodsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return apiclient.listPods(cmd)
-
-
-class PublicIpRange:
-    """Manage VlanIpRange"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services):
-        """Create VlanIpRange"""
-        
-        cmd = createVlanIpRange.createVlanIpRangeCmd()
-        cmd.gateway = services["gateway"]
-        cmd.netmask = services["netmask"]
-        cmd.forvirtualnetwork = services["forvirtualnetwork"]
-        cmd.startip = services["startip"]
-        cmd.endip = services["endip"]
-        cmd.zoneid = services["zoneid"]
-        cmd.podid = services["podid"]
-        cmd.vlan = services["vlan"]
-
-        return PublicIpRange(apiclient.createVlanIpRange(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete VlanIpRange"""
-
-        cmd = deleteVlanIpRange.deleteVlanIpRangeCmd()
-        cmd.id = self.id
-        apiclient.deleteVlanIpRange(cmd)
-
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all VLAN IP ranges."""
-
-        cmd = listVlanIpRanges.listVlanIpRangesCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listVlanIpRanges(cmd))
-
-
-class SecondaryStorage:
-    """Manage Secondary storage"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services):
-        """Create Secondary Storage"""
-        cmd = addSecondaryStorage.addSecondaryStorageCmd()
-
-        cmd.url = services["url"]
-        if "zoneid" in services:
-            cmd.zoneid = services["zoneid"]
-        return SecondaryStorage(apiclient.addSecondaryStorage(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Secondary Storage"""
-
-        cmd = deleteHost.deleteHostCmd()
-        cmd.id = self.id
-        apiclient.deleteHost(cmd)
-        
-
-class SecurityGroup:
-    """Manage Security Groups"""
-
-    def __init__(self, items):
-        self.__dict__.update(items)
-
-    @classmethod
-    def create(cls, apiclient, services, account=None, domainid=None,
-               description=None):
-        """Create security group"""
-        cmd = createSecurityGroup.createSecurityGroupCmd()
-
-        cmd.name = services["name"]
-        if account:
-            cmd.account = account
-        if domainid:
-            cmd.domainid=domainid
-        if description:
-            cmd.description=description
-            
-        return SecurityGroup(apiclient.createSecurityGroup(cmd).__dict__)
-
-    def delete(self, apiclient):
-        """Delete Security Group"""
-
-        cmd = deleteSecurityGroup.deleteSecurityGroupCmd()
-        cmd.id = self.id
-        apiclient.deleteSecurityGroup(cmd)
-        
-    def authorize(self, apiclient, services,
-                  account=None, domainid=None):
-        """Authorize Ingress Rule"""
-        
-        cmd=authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd()
-        
-        if domainid:
-            cmd.domainid = domainid
-        if account:
-            cmd.account = account
-                
-        cmd.securitygroupid=self.id
-        cmd.protocol=services["protocol"]
-        
-        if services["protocol"] == 'ICMP':
-            cmd.icmptype = -1
-            cmd.icmpcode = -1
-        else:
-            cmd.startport = services["startport"]
-            cmd.endport = services["endport"]
-        
-        cmd.cidrlist = services["cidrlist"]
-        return (apiclient.authorizeSecurityGroupIngress(cmd).__dict__)
-    
-    def revoke(self, apiclient, id):
-        """Revoke ingress rule"""
-        
-        cmd=revokeSecurityGroupIngress.revokeSecurityGroupIngressCmd()
-        cmd.id=id
-        return apiclient.revokeSecurityGroupIngress(cmd)
-    
-    @classmethod
-    def list(cls, apiclient, **kwargs):
-        """Lists all security groups."""
-
-        cmd = listSecurityGroups.listSecurityGroupsCmd()
-        [setattr(cmd, k, v) for k, v in kwargs.items()]
-        return(apiclient.listSecurityGroups(cmd))

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/32a42f4f/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/common.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/common.py b/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/common.py
deleted file mode 100644
index fc18401..0000000
--- a/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/common.py
+++ /dev/null
@@ -1,460 +0,0 @@
-# -*- encoding: utf-8 -*-
-# 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.
-
-"""Common functions
-"""
-
-#Import Local Modules
-from marvin.cloudstackTestCase import *
-from marvin.cloudstackAPI import *
-import marvin.remoteSSHClient
-from utils import *
-from base import *
-
-#Import System modules
-import time
-
-def get_domain(apiclient, services=None):
-    "Returns a default domain"
-
-    cmd = listDomains.listDomainsCmd()
-    if services:
-        if "domainid" in services:
-            cmd.id = services["domainid"]
-    
-    domains = apiclient.listDomains(cmd)
-    
-    if isinstance(domains, list):
-        return domains[0]
-    else:
-        raise Exception("Failed to find specified domain.") 
-
-def get_zone(apiclient, services=None):
-    "Returns a default zone"
-
-    cmd = listZones.listZonesCmd()
-    if services:
-        if "zoneid" in services:
-            cmd.id = services["zoneid"]
-    
-    zones = apiclient.listZones(cmd)
-    
-    if isinstance(zones, list):
-        return zones[0]
-    else:
-        raise Exception("Failed to find specified zone.") 
-
-def get_pod(apiclient, zoneid, services=None):
-    "Returns a default pod for specified zone"
-
-    cmd = listPods.listPodsCmd()
-    cmd.zoneid = zoneid
-
-    if services:
-        if "podid" in services:
-            cmd.id = services["podid"]
-    
-    pods = apiclient.listPods(cmd)
-    
-    if isinstance(pods, list):
-        return pods[0]
-    else:
-        raise Exception("Exception: Failed to find specified pod.") 
-
-def get_template(apiclient, zoneid, ostypeid=12, services=None):
-    "Returns a template"
-
-    cmd = listTemplates.listTemplatesCmd()
-    cmd.templatefilter = 'featured'
-    cmd.zoneid = zoneid
-
-    if services:
-        if "template" in services:
-            cmd.id = services["template"]
-
-    list_templates = apiclient.listTemplates(cmd)
-
-    for template in list_templates:
-        if template.ostypeid == ostypeid:
-            return template
-        
-    raise Exception("Exception: Failed to find template with OSTypeID: %s" %
-                                                                    ostypeid) 
-    return
-
-def download_systemplates_sec_storage(server, services):
-    """Download System templates on sec storage"""
-
-    try:
-        # Login to management server
-        ssh = marvin.remoteSSHClient.remoteSSHClient(
-                                          server["ipaddress"],
-                                          server["port"],
-                                          server["username"],
-                                          server["password"]
-                                          )
-    except Exception as e:
-        raise Exception("SSH access failted for server with IP address: %s" %
-                                                            server["ipaddess"])
-    # Mount Secondary Storage on Management Server
-    cmds = [
-            "mkdir -p %s" % services["mnt_dir"],
-            "mount -t nfs %s:/%s %s" % (
-                                        services["sec_storage"],
-                                        services["path"],
-                                        services["mnt_dir"]
-                                        ),
-            "%s -m %s -u %s -h %s -F" % (
-                                         services["command"],
-                                         services["mnt_dir"],
-                                         services["download_url"],
-                                         services["hypervisor"]
-                                        )
-            ]
-    for c in cmds:
-        result = ssh.execute(c)
-
-    res = str(result)
-
-    # Unmount the Secondary storage
-    ssh.execute("umount %s" % (services["mnt_dir"]))
-
-    if res.count("Successfully installed system VM template") == 1:
-        return
-    else:
-        raise Exception("Failed to download System Templates on Sec Storage")
-    return
-
-def wait_for_ssvms(apiclient, zoneid, podid, interval=60):
-    """After setup wait for SSVMs to come Up"""
-
-    time.sleep(interval)
-    timeout = 40
-    while True:
-            list_ssvm_response = list_ssvms(
-                                        apiclient,
-                                        systemvmtype='secondarystoragevm',
-                                        zoneid=zoneid,
-                                        podid=podid
-                                        )
-            ssvm = list_ssvm_response[0]
-            if ssvm.state != 'Running':
-                # Sleep to ensure SSVMs are Up and Running
-                time.sleep(30)
-                timeout = timeout - 1
-            elif ssvm.state == 'Running':
-                break
-            elif timeout == 0:
-                raise Exception("SSVM failed to come up")
-                break
-
-    timeout = 40
-    while True:
-            list_ssvm_response = list_ssvms(
-                                        apiclient,
-                                        systemvmtype='consoleproxy',
-                                        zoneid=zoneid,
-                                        podid=podid
-                                        )
-            cpvm = list_ssvm_response[0]
-            if cpvm.state != 'Running':
-                # Sleep to ensure SSVMs are Up and Running
-                time.sleep(interval)
-                timeout = timeout - 1
-            elif cpvm.state == 'Running':
-                break
-            elif timeout == 0:
-                raise Exception("CPVM failed to come up")
-                break
-    return
-
-def download_builtin_templates(apiclient, zoneid, hypervisor, host, linklocalip, interval=60):
-    """After setup wait till builtin templates are downloaded"""
-    
-    # Change IPTABLES Rules
-    result = get_process_status(
-                                host["ipaddress"],
-                                host["port"],
-                                host["username"],
-                                host["password"],
-                                linklocalip,
-                                "iptables -P INPUT ACCEPT"
-                            )
-    time.sleep(interval)
-    # Find the BUILTIN Templates for given Zone, Hypervisor
-    list_template_response = list_templates(
-                                    apiclient,
-                                    hypervisor=hypervisor,
-                                    zoneid=zoneid,
-                                    templatefilter='self'
-                                    )
-    
-    if not isinstance(list_template_response, list):
-        raise Exception("Failed to download BUILTIN templates")
-    
-    # Ensure all BUILTIN templates are downloaded
-    templateid = None
-    for template in list_template_response:
-        if template.templatetype == "BUILTIN":
-                templateid = template.id
-
-    # Sleep to ensure that template is in downloading state after adding
-    # Sec storage
-    time.sleep(interval)
-    while True:
-        template_response = list_templates(
-                                    apiclient,
-                                    id=templateid,
-                                    zoneid=zoneid,
-                                    templatefilter='self'
-                                    )
-        template = template_response[0]
-        # If template is ready,
-        # template.status = Download Complete
-        # Downloading - x% Downloaded
-        # Error - Any other string 
-        if template.status == 'Download Complete':
-            break
-                
-        elif 'Downloaded' in template.status:
-            time.sleep(interval)
-
-        elif 'Installing' not in template.status:
-            raise Exception("ErrorInDownload")
-        
-    return
-
-def update_resource_limit(apiclient, resourcetype, account=None, domainid=None,
-                          max=None):
-    """Updates the resource limit to 'max' for given account"""
-
-    cmd = updateResourceLimit.updateResourceLimitCmd()
-    cmd.resourcetype = resourcetype
-    if account:
-        cmd.account = account
-    if domainid:
-        cmd.domainid = domainid
-    if max:
-        cmd.max = max
-    apiclient.updateResourceLimit(cmd)
-    return
-
-def list_routers(apiclient, **kwargs):
-    """List all Routers matching criteria"""
-
-    cmd = listRouters.listRoutersCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listRouters(cmd))
-
-def list_zones(apiclient, **kwargs):
-    """List all Zones matching criteria"""
-
-    cmd = listZones.listZonesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listZones(cmd))
-
-def list_networks(apiclient, **kwargs):
-    """List all Networks matching criteria"""
-
-    cmd = listNetworks.listNetworksCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listNetworks(cmd))
-
-def list_clusters(apiclient, **kwargs):
-    """List all Clusters matching criteria"""
-
-    cmd = listClusters.listClustersCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listClusters(cmd))
-
-def list_ssvms(apiclient, **kwargs):
-    """List all SSVMs matching criteria"""
-
-    cmd = listSystemVms.listSystemVmsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listSystemVms(cmd))
-
-def list_storage_pools(apiclient, **kwargs):
-    """List all storage pools matching criteria"""
-
-    cmd = listStoragePools.listStoragePoolsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listStoragePools(cmd))
-
-def list_virtual_machines(apiclient, **kwargs):
-    """List all VMs matching criteria"""
-
-    cmd = listVirtualMachines.listVirtualMachinesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listVirtualMachines(cmd))
-
-def list_hosts(apiclient, **kwargs):
-    """List all Hosts matching criteria"""
-
-    cmd = listHosts.listHostsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listHosts(cmd))
-
-def list_configurations(apiclient, **kwargs):
-    """List configuration with specified name"""
-
-    cmd = listConfigurations.listConfigurationsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listConfigurations(cmd))
-
-def list_publicIP(apiclient, **kwargs):
-    """List all Public IPs matching criteria"""
-
-    cmd = listPublicIpAddresses.listPublicIpAddressesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listPublicIpAddresses(cmd))
-
-def list_nat_rules(apiclient, **kwargs):
-    """List all NAT rules matching criteria"""
-
-    cmd = listPortForwardingRules.listPortForwardingRulesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listPortForwardingRules(cmd))
-
-def list_lb_rules(apiclient, **kwargs):
-    """List all Load balancing rules matching criteria"""
-
-    cmd = listLoadBalancerRules.listLoadBalancerRulesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listLoadBalancerRules(cmd))
-
-def list_lb_instances(apiclient, **kwargs):
-    """List all Load balancing instances matching criteria"""
-
-    cmd = listLoadBalancerRuleInstances.listLoadBalancerRuleInstancesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listLoadBalancerRuleInstances(cmd))
-
-def list_firewall_rules(apiclient, **kwargs):
-    """List all Firewall Rules matching criteria"""
-
-    cmd = listFirewallRules.listFirewallRulesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listFirewallRules(cmd))
-
-def list_volumes(apiclient, **kwargs):
-    """List all volumes matching criteria"""
-
-    cmd = listVolumes.listVolumesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listVolumes(cmd))
-
-def list_isos(apiclient, **kwargs):
-    """Lists all available ISO files."""
-
-    cmd = listIsos.listIsosCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listIsos(cmd))
-
-def list_snapshots(apiclient, **kwargs):
-    """List all snapshots matching criteria"""
-
-    cmd = listSnapshots.listSnapshotsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listSnapshots(cmd))
-
-def list_templates(apiclient, **kwargs):
-    """List all templates matching criteria"""
-
-    cmd = listTemplates.listTemplatesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listTemplates(cmd))
-
-def list_domains(apiclient, **kwargs):
-    """Lists domains"""
-
-    cmd = listDomains.listDomainsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listDomains(cmd))
-
-def list_accounts(apiclient, **kwargs):
-    """Lists accounts and provides detailed account information for
-    listed accounts"""
-
-    cmd = listAccounts.listAccountsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listAccounts(cmd))
-
-def list_users(apiclient, **kwargs):
-    """Lists users and provides detailed account information for
-    listed users"""
-
-    cmd = listUsers.listUsersCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listUsers(cmd))
-
-def list_snapshot_policy(apiclient, **kwargs):
-    """Lists snapshot policies."""
-
-    cmd = listSnapshotPolicies.listSnapshotPoliciesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listSnapshotPolicies(cmd))
-
-def list_events(apiclient, **kwargs):
-    """Lists events"""
-
-    cmd = listEvents.listEventsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listEvents(cmd))
-
-def list_disk_offering(apiclient, **kwargs):
-    """Lists all available disk offerings."""
-
-    cmd = listDiskOfferings.listDiskOfferingsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listDiskOfferings(cmd))
-
-def list_service_offering(apiclient, **kwargs):
-    """Lists all available service offerings."""
-
-    cmd = listServiceOfferings.listServiceOfferingsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listServiceOfferings(cmd))
-
-def list_vlan_ipranges(apiclient, **kwargs):
-    """Lists all VLAN IP ranges."""
-
-    cmd = listVlanIpRanges.listVlanIpRangesCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listVlanIpRanges(cmd))
-
-def list_usage_records(apiclient, **kwargs):
-    """Lists usage records for accounts"""
-
-    cmd = listUsageRecords.listUsageRecordsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listUsageRecords(cmd))
-
-def list_network_offerings(apiclient, **kwargs):
-    """Lists network offerings"""
-
-    cmd = listNetworkOfferings.listNetworkOfferingsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listNetworkOfferings(cmd))
-
-def list_resource_limits(apiclient, **kwargs):
-    """Lists resource limits"""
-
-    cmd = listResourceLimits.listResourceLimitsCmd()
-    [setattr(cmd, k, v) for k, v in kwargs.items()]
-    return(apiclient.listResourceLimits(cmd))

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/32a42f4f/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/utils.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/utils.py b/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/utils.py
deleted file mode 100644
index 8abed18..0000000
--- a/tools/marvin/marvin/sandbox/demo/simulator/testcase/libs/utils.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# -*- encoding: utf-8 -*-
-# 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.
-
-"""Utilities functions
-"""
-
-import time
-import marvin.remoteSSHClient
-from marvin.cloudstackAPI import *
-import marvin.cloudstackConnection
-from marvin.remoteSSHClient import remoteSSHClient
-#from marvin.cloudstackConnection import cloudConnection
-import marvin.configGenerator
-import logging
-import string
-import random
-
-def random_gen(size=6, chars=string.ascii_uppercase + string.digits):
-    """Generate Random Strings of variable length"""
-    return ''.join(random.choice(chars) for x in range(size))
-
-def cleanup_resources(api_client, resources):
-    """Delete resources"""
-    for obj in resources:
-        obj.delete(api_client)
-
-def is_server_ssh_ready(ipaddress, port, username, password, retries=50):
-    """Return ssh handle else wait till sshd is running"""
-    loop_cnt = retries
-    while True:
-        try:
-            ssh = marvin.remoteSSHClient.remoteSSHClient(
-                                            ipaddress,
-                                            port,
-                                            username,
-                                            password
-                                            )
-        except Exception as e:
-            if loop_cnt == 0:
-                raise e
-            loop_cnt = loop_cnt - 1
-            time.sleep(30)
-        else:
-            return ssh
-
-
-def format_volume_to_ext3(ssh_client, device="/dev/sda"):
-    """Format attached storage to ext3 fs"""
-    cmds = [
-            "echo -e 'n\np\n1\n\n\nw' | fdisk %s" % device,
-            "mkfs.ext3 %s1" % device,
-           ]
-    for c in cmds:
-        ssh_client.execute(c)
-
-def fetch_api_client(config_file='datacenterCfg'):
-    """Fetch the Cloudstack API Client"""
-    config = configGenerator.get_setup_config(config_file)
-    mgt = config.mgtSvr[0]
-    testClientLogger = logging.getLogger("testClient")
-    asyncTimeout = 3600
-    return cloudstackAPIClient.CloudStackAPIClient(
-            cloudstackConnection.cloudConnection(
-                                                mgt.mgtSvrIp,
-                                                mgt.port,
-                                                mgt.apiKey,
-                                                mgt.securityKey,
-                                                asyncTimeout,
-                                                testClientLogger
-                                                )
-                                            )
-
-def get_process_status(hostip, port, username, password, linklocalip, process):
-    """Double hop and returns a process status"""
-
-    #SSH to the machine
-    ssh = marvin.remoteSSHClient.remoteSSHClient(
-                                          hostip,
-                                          port,
-                                          username,
-                                          password
-                            )
-    ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
-    ssh_command = ssh_command + "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" \
-                        % (linklocalip, process)
-
-    # Double hop into router
-    timeout = 5
-    # Ensure the SSH login is successful
-    while True:
-        res = ssh.execute(ssh_command)
-        
-        if res[0] != "Host key verification failed.":
-            break
-        elif timeout == 0:
-            break
-        
-        time.sleep(5)
-        timeout = timeout - 1
-    return res


[03/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: use percached commands.xml for api generation

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/3621969b
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/3621969b
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/3621969b

Branch: refs/heads/marvin-refactor
Commit: 3621969b07399423da969dd7deccec11354e19f4
Parents: 215ac11
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Tue Sep 3 16:55:06 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:06 2013 +0530

----------------------------------------------------------------------
 tools/marvin/pom.xml | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3621969b/tools/marvin/pom.xml
----------------------------------------------------------------------
diff --git a/tools/marvin/pom.xml b/tools/marvin/pom.xml
index d4779a6..2b4f360 100644
--- a/tools/marvin/pom.xml
+++ b/tools/marvin/pom.xml
@@ -57,8 +57,7 @@
               <arguments>
                 <argument>codegenerator.py</argument>
                 <argument>-s</argument>
-                <argument>${basedir}/../apidoc/target/commands.xml</argument>
-                <echo>Generating ${project.artifactId} API classes}</echo>
+                <argument>${basedir}/commands.xml</argument>
               </arguments>
             </configuration>
           </execution>
@@ -112,7 +111,6 @@
                     <argument>-e</argument>
                     <argument>${endpoint}</argument>
                     <argument>-y</argument>
-                    <echo>Generating ${project.artifactId} API classes}</echo>
                   </arguments>
                 </configuration>
               </execution>
@@ -143,6 +141,7 @@
                   <arguments>
                     <argument>install</argument>
                     <argument>--upgrade</argument>
+                    <!-- TODO: Fix Marvin versioning here -->
                     <argument>Marvin-0.1.0.tar.gz</argument>
                   </arguments>
                 </configuration>


[27/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: include apiclient as part of factory

The apiclient is required for creation of any factory and should be the
in the FACTORY_ARGS list. This is useful for post_generation hooks to
call other methods on the resulting object. For eg: A network creation
triggers a networkoffering creation and so the enabling of the
networkoffering.

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/b61f6ce6
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/b61f6ce6
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/b61f6ce6

Branch: refs/heads/marvin-refactor
Commit: b61f6ce61a0c1e1da67c44ca3752a1f432721efd
Parents: 94b203e
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Wed Sep 11 20:00:05 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:27:45 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/factory/data/network.py         | 1 -
 tools/marvin/marvin/factory/data/networkoffering.py | 6 +++---
 tools/marvin/marvin/generate/entity.py              | 5 +++--
 tools/marvin/marvin/generate/factory.py             | 4 +++-
 tools/marvin/marvin/test/test_factories.py          | 6 +++---
 tools/marvin/pom.xml                                | 1 +
 6 files changed, 13 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b61f6ce6/tools/marvin/marvin/factory/data/network.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/network.py b/tools/marvin/marvin/factory/data/network.py
index 962d24f..ad6101c 100644
--- a/tools/marvin/marvin/factory/data/network.py
+++ b/tools/marvin/marvin/factory/data/network.py
@@ -30,7 +30,6 @@ class GuestIsolatedNetworkFactory(NetworkFactory):
         DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory,
         apiclient=factory.SelfAttribute('..apiclient'),
         name=factory.Sequence(lambda n: 'GuestIsolatedNetworkOffering-%s' % random_gen()),
-        enable__apiclient=factory.SelfAttribute('..apiclient')
     )
     networkofferingid = factory.LazyAttribute(lambda no: no.networkoffering.id if no.networkoffering else no.networkoffering)
     zoneid = None

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b61f6ce6/tools/marvin/marvin/factory/data/networkoffering.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/factory/data/networkoffering.py b/tools/marvin/marvin/factory/data/networkoffering.py
index 96f77cf..41cda56 100644
--- a/tools/marvin/marvin/factory/data/networkoffering.py
+++ b/tools/marvin/marvin/factory/data/networkoffering.py
@@ -48,7 +48,7 @@ class DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory(NetworkOfferingF
     def enable(self, create, extracted, **kwargs):
         if not create:
             return
-        self.update(apiclient=kwargs['apiclient'], id=self.id, state='Enabled')
+        self.update(apiclient=self.apiclient, id=self.id, state='Enabled')
 
 
 class DefaultSharedNetworkOfferingWithSGServiceFactory(NetworkOfferingFactory):
@@ -83,7 +83,7 @@ class DefaultSharedNetworkOfferingWithSGServiceFactory(NetworkOfferingFactory):
     def enable(self, create, extracted, **kwargs):
         if not create:
             return
-        self.update(apiclient=kwargs['apiclient'], id=self.id, state='Enabled')
+        self.update(apiclient=self.apiclient, id=self.id, state='Enabled')
 
 
 
@@ -115,4 +115,4 @@ class DefaultSharedNetworkOfferingFactory(NetworkOfferingFactory):
     def enable(self, create, extracted, **kwargs):
         if not create:
             return
-        self.update(apiclient=kwargs['apiclient'], id=self.id, state='Enabled')
+        self.update(apiclient=self.apiclient, id=self.id, state='Enabled')

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b61f6ce6/tools/marvin/marvin/generate/entity.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/entity.py b/tools/marvin/marvin/generate/entity.py
index 76316ef..dc96a14 100644
--- a/tools/marvin/marvin/generate/entity.py
+++ b/tools/marvin/marvin/generate/entity.py
@@ -96,11 +96,12 @@ 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=None, factory=None, **kwargs):' % action
+                    m.signature = 'def %s(cls, apiclient, factory=None, **kwargs):' % action
 
+                m.body.append(self.tabspace + 'self.__update__(kwargs)')
                 m.body.append(self.tabspace + 'if not apiclient:')
-                m.body.append(self.tabspace * 2 + 'self.__update__(kwargs)')
                 m.body.append(self.tabspace*2 + 'return')
+                m.body.append(self.tabspace + 'self.apiclient = apiclient')
 
                 m.body.append(self.tabspace + 'cmd = %(module)s.%(command)s()' % {"module": details["apimodule"],
                                                                                "command": details["apicmd"]})

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b61f6ce6/tools/marvin/marvin/generate/factory.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/factory.py b/tools/marvin/marvin/generate/factory.py
index d31f916..7c717f0 100644
--- a/tools/marvin/marvin/generate/factory.py
+++ b/tools/marvin/marvin/generate/factory.py
@@ -52,7 +52,9 @@ class Factory(object):
         code += '\n\n'
         code += 'class %sFactory(Factory):' % entity
         code += '\n\n'
-        code += tabspace + 'FACTORY_FOR = %s\n\n' % entity
+        code += tabspace + 'FACTORY_FOR = %s\n' % entity
+        code += tabspace + 'FACTORY_ARG_PARAMETERS = (\'apiclient\',)\n\n'
+        code += tabspace + 'apiclient = None\n'
         for arg in factory_defaults:
             code += tabspace + '%s = None\n' % arg
         self.name = entity

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b61f6ce6/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 2dd5069..81e78a7 100644
--- a/tools/marvin/marvin/test/test_factories.py
+++ b/tools/marvin/marvin/test/test_factories.py
@@ -107,9 +107,9 @@ class NetworkOfferingFactoryTest(unittest.TestCase):
         self.assert_(snatOffering is not None, msg = "no network offering was created")
         self.assert_(snatOffering.name is not None, msg="error in network offering creation")
 
+    @attr(tags='offering')
     def test_defaultSGOfferingEnable(self):
-        sgOffering = DefaultSharedNetworkOfferingWithSGServiceFactory(apiclient=self.apiClient)
-        sgOffering.update(self.apiClient, state='Enabled', name=sgOffering.name, id=sgOffering.id)
+        DefaultSharedNetworkOfferingWithSGServiceFactory(apiclient=self.apiClient)
 
     def tearDown(self):
         pass
@@ -201,7 +201,7 @@ class NetworkFactoryTest(unittest.TestCase):
             logging=logging.getLogger('factory.cloudstack')).getApiClient()
 
     def tearDown(self):
-        self.accnt.delete()
+        self.accnt.delete(apiclient=self.apiClient)
 
     @attr(tags='network')
     def test_isolatedGuestNetwork(self):

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b61f6ce6/tools/marvin/pom.xml
----------------------------------------------------------------------
diff --git a/tools/marvin/pom.xml b/tools/marvin/pom.xml
index 9876122..053a1a1 100644
--- a/tools/marvin/pom.xml
+++ b/tools/marvin/pom.xml
@@ -62,6 +62,7 @@
                 <argument>codegenerator.py</argument>
                 <argument>-s</argument>
                 <argument>${basedir}/commands.xml</argument>
+                <argument>-y</argument>
               </arguments>
             </configuration>
           </execution>


[40/50] [abbrv] git commit: updated refs/heads/marvin-refactor to bbaf354

Posted by ts...@apache.org.
marvin_refactor: additional verbs modify and disocciate

modify -> modifyPool
dissociate -> dissociateLun

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/e3d93593
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/e3d93593
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/e3d93593

Branch: refs/heads/marvin-refactor
Commit: e3d93593ef48160771c9b1d8102e7ef82639cb07
Parents: 746399a
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Mon Sep 30 10:46:36 2013 +0530
Committer: Prasanna Santhanam <ts...@apache.org>
Committed: Wed Oct 2 20:28:04 2013 +0530

----------------------------------------------------------------------
 tools/marvin/marvin/generate/verbs.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e3d93593/tools/marvin/marvin/generate/verbs.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/generate/verbs.py b/tools/marvin/marvin/generate/verbs.py
index 2051f2d..68d9d83 100644
--- a/tools/marvin/marvin/generate/verbs.py
+++ b/tools/marvin/marvin/generate/verbs.py
@@ -17,10 +17,10 @@
 
 grammar = ['create', 'list', 'delete', 'update', 'ldap', 'login', 'logout',
            'enable', 'activate', 'disable', 'add', 'remove',
-           'attach', 'detach', 'associate', 'generate', 'assign',
+           'attach', 'detach', 'associate', 'dissociate', 'generate', 'assign',
            'authorize', 'change', 'register', 'configure',
            'start', 'restart', 'reboot', 'stop', 'reconnect',
-           'cancel', 'destroy', 'revoke', 'mark', 'reset',
+           'cancel', 'destroy', 'revoke', 'mark', 'modify', 'reset',
            'copy', 'extract', 'migrate', 'restore', 'suspend',
            'get', 'query', 'prepare', 'deploy', 'upload', 'lock',
            'disassociate', 'scale', 'dedicate', 'archive', 'find',