From b3112fd45a1aaca3bd3feb1cb075cf972f1ccbd1 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Thu, 25 Apr 2013 16:58:24 +0530 Subject: [PATCH] marvin_refactor: Chain subFactory calls SubFactories now can call in a nested fashion to populate attributes in dependant entities. --- tools/marvin/marvin/base/Account.py | 4 +- tools/marvin/marvin/factory/AccountFactory.py | 13 +- .../marvin/factory/CloudStackBaseFactory.py | 2 +- tools/marvin/marvin/factory/UserFactory.py | 14 +- .../marvin/factory/test/testFactories.py | 2 +- .../marvin/factory/test/test_factories.py | 187 ++++++++++++++++++ 6 files changed, 209 insertions(+), 13 deletions(-) create mode 100644 tools/marvin/marvin/factory/test/test_factories.py diff --git a/tools/marvin/marvin/base/Account.py b/tools/marvin/marvin/base/Account.py index aaf72ed1576..32744c93cf5 100644 --- a/tools/marvin/marvin/base/Account.py +++ b/tools/marvin/marvin/base/Account.py @@ -14,6 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. + from marvin.base import CloudStackEntity from marvin.cloudstackAPI import enableAccount from marvin.cloudstackAPI import lockAccount @@ -24,8 +25,8 @@ from marvin.cloudstackAPI import disableAccount from marvin.cloudstackAPI import deleteAccount from marvin.cloudstackAPI import markDefaultZoneForAccount -class Account(CloudStackEntity.CloudStackEntity): +class Account(CloudStackEntity.CloudStackEntity): def __init__(self, items): self.__dict__.update(items) @@ -91,6 +92,7 @@ class Account(CloudStackEntity.CloudStackEntity): account = apiclient.deleteAccount(cmd) return account + def mark(self, apiclient, zoneid, **kwargs): cmd = markDefaultZoneForAccount.markDefaultZoneForAccountCmd() cmd.id = self.id diff --git a/tools/marvin/marvin/factory/AccountFactory.py b/tools/marvin/marvin/factory/AccountFactory.py index 3c076833788..db38732553e 100644 --- a/tools/marvin/marvin/factory/AccountFactory.py +++ b/tools/marvin/marvin/factory/AccountFactory.py @@ -20,11 +20,18 @@ from marvin.factory.CloudStackBaseFactory import CloudStackBaseFactory from marvin.base import Account from marvin.utils import random_gen -@factory.use_strategy(new_strategy=factory.BUILD_STRATEGY) class AccountFactory(CloudStackBaseFactory): FACTORY_FOR = Account.Account + accounttype = None + firstname = None + lastname = None + email = None + username = None + password = None + +class UserAccountFactory(AccountFactory): accounttype = 0 firstname = factory.Sequence(lambda n: random_gen()) lastname = factory.Sequence(lambda n: random_gen()) @@ -33,10 +40,10 @@ class AccountFactory(CloudStackBaseFactory): password = 'password' -class AdminAccountFactory(AccountFactory): +class AdminAccountFactory(UserAccountFactory): accounttype = 1 -class DomainAdminFactory(AccountFactory): +class DomainAdminFactory(UserAccountFactory): accounttype = 2 domainid = None diff --git a/tools/marvin/marvin/factory/CloudStackBaseFactory.py b/tools/marvin/marvin/factory/CloudStackBaseFactory.py index 499dbc2ae36..c4a7c77ae02 100644 --- a/tools/marvin/marvin/factory/CloudStackBaseFactory.py +++ b/tools/marvin/marvin/factory/CloudStackBaseFactory.py @@ -32,7 +32,7 @@ class CloudStackBaseFactory(factory.Factory): @classmethod def _create(cls, target_class, *args, **kwargs): - if cls.apiclient: + if hasattr(cls, 'apiclient'): members = inspect.getmembers(target_class, predicate=inspect.ismethod) creators = filter(lambda x: x[0] in CREATORS, members) diff --git a/tools/marvin/marvin/factory/UserFactory.py b/tools/marvin/marvin/factory/UserFactory.py index f70089dce6b..4981ca4ff0d 100644 --- a/tools/marvin/marvin/factory/UserFactory.py +++ b/tools/marvin/marvin/factory/UserFactory.py @@ -23,12 +23,12 @@ class UserFactory(CloudStackBaseFactory): FACTORY_FOR = User.User - account = factory.SubFactory(AccountFactory, apiclient=factory.SelfAttribute('..apiclient')).factory() - email = account.email - firstname = account.firstname - lastname = account.lastname - password = account.password - username = account.username + account = factory.SubFactory(AccountFactory, apiclient=factory.SelfAttribute('..apiclient')) + email = factory.SelfAttribute('account.email') + firstname = factory.SelfAttribute('account.firstname') + lastname = factory.SelfAttribute('account.lastname') + password = factory.SelfAttribute('account.password') + username = factory.SelfAttribute('account.name') class AdminUserFactory(UserFactory): - account = factory.SubFactory(AccountFactory, accounttype=1).factory() + account = factory.SubFactory(AccountFactory, accounttype=1) diff --git a/tools/marvin/marvin/factory/test/testFactories.py b/tools/marvin/marvin/factory/test/testFactories.py index d4e947ec743..c798bb4ccb0 100644 --- a/tools/marvin/marvin/factory/test/testFactories.py +++ b/tools/marvin/marvin/factory/test/testFactories.py @@ -147,7 +147,7 @@ class UserFactorySubFactoryTest(unittest.TestCase): def test_userSubFactory(self): uf = UserFactory.create(apiclient=self.apiClient) - user = User.list(apiclient=self.apiClient, username=uf.username) + user = User.list(apiclient=self.apiClient, username=uf.account.username) self.assert_(uf.username == user[0].username, msg="Usernames don't match") diff --git a/tools/marvin/marvin/factory/test/test_factories.py b/tools/marvin/marvin/factory/test/test_factories.py new file mode 100644 index 00000000000..56903ff8181 --- /dev/null +++ b/tools/marvin/marvin/factory/test/test_factories.py @@ -0,0 +1,187 @@ +# 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 unittest +import logging + +from marvin.cloudstackTestClient import cloudstackTestClient + +from marvin.factory.AccountFactory import * +from marvin.factory.ServiceOfferingFactory import * +from marvin.factory.NetworkOfferingFactory import * +from marvin.factory.TemplateFactory import * +from marvin.factory.VirtualMachineFactory import * +from marvin.factory.UserFactory 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.IpAddress import IpAddress +from marvin.base.Network import Network + +class BuildVsCreateStrategyTest(unittest.TestCase): + def setUp(self): + self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factories.cloudstack')).getApiClient() + + def tearDown(self): + pass + + def test_buildUserAccountFactory(self): + af = UserAccountFactory() + self.assert_(af.account is not None, msg="Acount factory didn't initialize") + + def test_createAccountFactory(self): + af = AccountFactory.create(apiclient=self.apiClient) + self.assert_(isinstance(af, Account)) + self.assert_(af.account.id is not None, msg="Account creation failed") + self.assert_(af.account.domain is not None, msg="Account belongs to no domain") + + +class AccountFactoryTest(unittest.TestCase): + def setUp(self): + self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factories.cloudstack')).getApiClient() + + def test_adminAccountFactory(self): + accnt = AdminAccountFactory.create(apiclient=self.apiClient) + self.assert_(accnt is not None, msg="no account created by factory") + self.assert_(accnt.account.name is not None) + + def test_userAccountFactoryCustomArgs(self): + accnt = UserAccountFactory.create(apiclient=self.apiClient, firstname='test', lastname='test') + a = accnt.list(apiclient=self.apiClient, account=accnt.account.username, domainid=accnt.account.domainid) + self.assert_(accnt is not None, msg="no account created by factory") + self.assert_(accnt.account.name is not None) + + @unittest.skip("Account doesn't deserialize correctly") + def test_disableAccountPostFactoryGeneration(self): + domadmin = DomainAdminFactory.create(apiclient=self.apiClient) + self.assert_(domadmin is not None, msg="no account was created") + domadmin.disable(self.apiClient, lock=True) + + def tearDown(self): + pass + + +class ServiceOfferingFactoryTest(unittest.TestCase): + def setUp(self): + self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factories.cloudstack')).getApiClient() + + def test_serviceOfferingFactory(self): + soffering = ServiceOfferingFactory.create(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") + + + def tearDown(self): + pass + + +class NetworkOfferingFactoryTest(unittest.TestCase): + def setUp(self): + self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factories.cloudstack')).getApiClient() + + def test_defaultSourceNatOfferingFactory(self): + snatOffering = DefaultIsolatedNetworkOfferingWithSourceNatServiceFactory.create(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.update(self.apiClient, state='Enabled') + + def tearDown(self): + pass + + +class VirtualMachineFactoryTest(unittest.TestCase): + def setUp(self): + self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factories.cloudstack')).getApiClient() + + def tearDown(self): + pass + + def test_virtualMachineDeploy(self): + accnt = AccountFactory.create(apiclient=self.apiClient) + service = SmallServiceOfferingFactory.create(apiclient=self.apiClient) + tf = DefaultBuiltInTemplateFactory.build() #FIXME: Using build() strategy is confusing + 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, + serviceofferingid = service.id, + templateid = template[0].id, + zoneid = zones[0].id, + account = accnt.account.name, + domainid = accnt.account.domainid) + vm.destroy(apiclient=self.apiClient) + + + +class UserFactorySubFactoryTest(unittest.TestCase): + def setUp(self): + self.apiClient = cloudstackTestClient(mgtSvr='localhost', logging=logging.getLogger('factories.cloudstack')).getApiClient() + + def tearDown(self): + pass + + def test_userSubFactory(self): + uf = UserFactory.create(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('factories.cloudstack')).getApiClient() + + def tearDown(self): + pass + + def test_associateIpAddress(self): + all_ips = IpAddress.list(apiclient=self.apiClient) + self.assert_(len(all_ips) > 0, msg="No free public IPs") + firstip = all_ips[0] + firstip.associate(apiclient=self.apiClient, zoneid=firstip.zoneid) + + def test_vpcAssociateIpAddress(self): + #FIXME: To be written + self.assert_(1 == 1) + + def test_associateIpAddressToNetwork(self): + accnt = AccountFactory.create(apiclient=self.apiClient) + self.assert_(accnt is not None) + self.assert_(isinstance(accnt, Account)) + 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) + vm = VirtualMachineFactory.create( + apiclient=self.apiClient, + serviceofferingid = service[0].id, + templateid = template[0].id, + zoneid = zones[0].id, + account=accnt.account.name, + domainid=accnt.account.domainid) + all_ips = IpAddress.list(apiclient=self.apiClient) + firstip = all_ips[0] + networks = Network.list(apiclient=self.apiClient, account = accnt.account.name, domainid = accnt.account.domainid) + firstip.associate(apiclient=self.apiClient, networkid = networks[0].id) + vm.destroy(apiclient=self.apiClient) \ No newline at end of file