# 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.
""" P1 tests for Account
"""
#Import Local Modules
from marvin.cloudstackTestCase import *
from marvin.cloudstackAPI import *
from marvin.integration.lib.utils import *
from marvin.integration.lib.base import *
from marvin.integration.lib.common import *
from marvin import remoteSSHClient
from nose.plugins.attrib import attr
from marvin.cloudstackException import cloudstackAPIException

class Services:
    """Test Account Services
    """

    def __init__(self):
        self.services = {
                        "domain": {
                                   "name": "Domain",
                                   },
                        "account": {
                                    "email": "test@test.com",
                                    "firstname": "Test",
                                    "lastname": "User",
                                    "username": "test",
                                    # Random characters are appended for unique
                                    # username
                                    "password": "fr3sca",
                         },
                         "user": {
                                    "email": "user@test.com",
                                    "firstname": "User",
                                    "lastname": "User",
                                    "username": "User",
                                    # Random characters are appended for unique
                                    # username
                                    "password": "fr3sca",
                         },
                         "service_offering": {
                                    "name": "Tiny Instance",
                                    "displaytext": "Tiny Instance",
                                    "cpunumber": 1,
                                    "cpuspeed": 100,
                                    # in MHz
                                    "memory": 128,
                                    # In MBs
                        },
                         "virtual_machine": {
                                    "displayname": "Test VM",
                                    "username": "root",
                                    "password": "password",
                                    "ssh_port": 22,
                                    "hypervisor": 'XenServer',
                                    # Hypervisor type should be same as
                                    # hypervisor type of cluster
                                    "privateport": 22,
                                    "publicport": 22,
                                    "protocol": 'TCP',
                         },
                         "template": {
                                "displaytext": "Public Template",
                                "name": "Public template",
                                "url": "http://download.cloud.com/releases/2.0.0/UbuntuServer-10-04-64bit.vhd.bz2",
                                "hypervisor": 'XenServer',
                                "format": 'VHD',
                                "isfeatured": True,
                                "ispublic": True,
                                "isextractable": True,
                                "ostype": 'CentOS 5.3 (64-bit)',
                        },
                        "natrule": {
                                    "publicport": 22,
                                    "privateport": 22,
                                    "protocol": 'TCP',
                        },
                        "ostype": 'CentOS 5.3 (64-bit)',
                        # Cent OS 5.3 (64 bit)
                        "sleep": 60,
                        "timeout": 10,
                    }


class TestAccounts(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        cls.api_client = super(
                               TestAccounts,
                               cls
                               ).getClsTestClient().getApiClient()
        cls.services = Services().services
        # Get Zone, Domain and templates
        cls.zone = get_zone(cls.api_client, cls.services)
        cls.services['mode'] = cls.zone.networktype
        cls.template = get_template(
                            cls.api_client,
                            cls.zone.id,
                            cls.services["ostype"]
                            )
        cls.services["virtual_machine"]["zoneid"] = cls.zone.id
        cls.services["virtual_machine"]["template"] = cls.template.id

        cls.service_offering = ServiceOffering.create(
                                            cls.api_client,
                                            cls.services["service_offering"]
                                            )
        cls._cleanup = [cls.service_offering]
        return

    @classmethod
    def tearDownClass(cls):
        try:
            #Cleanup resources used
            cleanup_resources(cls.api_client, cls._cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()
        self.cleanup = []
        return

    def tearDown(self):
        try:
            #Clean up, terminate the created accounts, domains etc
            cleanup_resources(self.apiclient, self.cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"])
    def test_01_create_account(self):
        """Test Create Account and user for that account
        """

        # Validate the following
        # 1. Create an Account. Verify the account is created.
        # 2. Create User associated with that account. Verify the created user

        # Create an account
        account = Account.create(
                            self.apiclient,
                            self.services["account"]
                            )
        self.debug("Created account: %s" % account.name)
        self.cleanup.append(account)
        list_accounts_response = list_accounts(
                                               self.apiclient,
                                               id=account.id
                                               )
        self.assertEqual(
                         isinstance(list_accounts_response, list),
                         True,
                         "Check list accounts for valid data"
                         )
        self.assertNotEqual(
                            len(list_accounts_response),
                            0,
                            "Check List Account response"
                            )

        account_response = list_accounts_response[0]
        self.assertEqual(
                            account.accounttype,
                            account_response.accounttype,
                            "Check Account Type of Created account"
                            )
        self.assertEqual(
                            account.name,
                            account_response.name,
                            "Check Account Name of Created account"
                            )
        # Create an User associated with account
        user = User.create(
                            self.apiclient,
                            self.services["user"],
                            account=account.name,
                            domainid=account.domainid
                            )
        self.debug("Created user: %s" % user.id)
        list_users_response = list_users(
                                         self.apiclient,
                                         id=user.id
                                      )
        self.assertEqual(
                         isinstance(list_users_response, list),
                         True,
                         "Check list users for valid data"
                         )

        self.assertNotEqual(
                            len(list_users_response),
                            0,
                            "Check List User response"
                            )

        user_response = list_users_response[0]
        self.assertEqual(
                            user.username,
                            user_response.username,
                            "Check username of Created user"
                            )
        self.assertEqual(
                            user.state,
                            user_response.state,
                            "Check state of created user"
                            )
        return


class TestRemoveUserFromAccount(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        cls.api_client = super(
                               TestRemoveUserFromAccount,
                               cls
                               ).getClsTestClient().getApiClient()
        cls.services = Services().services
        # Get Zone, Domain and templates
        cls.zone = get_zone(cls.api_client, cls.services)
        cls.services['mode'] = cls.zone.networktype
        cls.template = get_template(
                            cls.api_client,
                            cls.zone.id,
                            cls.services["ostype"]
                            )
        cls.services["virtual_machine"]["zoneid"] = cls.zone.id
        cls.services["virtual_machine"]["template"] = cls.template.id

        cls.service_offering = ServiceOffering.create(
                                            cls.api_client,
                                            cls.services["service_offering"]
                                            )
        # Create an account
        cls.account = Account.create(
                            cls.api_client,
                            cls.services["account"]
                            )

        cls._cleanup = [
                        cls.service_offering,
                        ]
        return

    @classmethod
    def tearDownClass(cls):
        try:
            #Cleanup resources used
            cleanup_resources(cls.api_client, cls._cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()
        self.cleanup = []
        return

    def tearDown(self):
        try:
            #Clean up, terminate the created instance, users etc
            cleanup_resources(self.apiclient, self.cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"])
    def test_01_user_remove_VM_running(self):
        """Test Remove one user from the account
        """

        # Validate the following
        # 1. Create an account with 2 users.
        # 2. Start 2 VMs; one for each user of the account
        # 3. Remove one user from the account. Verify that account still exists.
        # 4. Verify that VM started by the removed user are still running

        # Create an User associated with account and VMs
        user_1 = User.create(
                            self.apiclient,
                            self.services["user"],
                            account=self.account.name,
                            domainid=self.account.domainid
                            )
        self.debug("Created user: %s" % user_1.id)

        user_2 = User.create(
                            self.apiclient,
                            self.services["user"],
                            account=self.account.name,
                            domainid=self.account.domainid
                            )
        self.debug("Created user: %s" % user_2.id)
        self.cleanup.append(user_2)

        vm_1 = VirtualMachine.create(
                                  self.apiclient,
                                  self.services["virtual_machine"],
                                  accountid=self.account.name,
                                  domainid=self.account.domainid,
                                  serviceofferingid=self.service_offering.id
                                  )
        self.debug("Deployed VM in account: %s, ID: %s" % (
                                                           self.account.name,
                                                           vm_1.id
                                                           ))
        self.cleanup.append(vm_1)

        vm_2 = VirtualMachine.create(
                                  self.apiclient,
                                  self.services["virtual_machine"],
                                  accountid=self.account.name,
                                  domainid=self.account.domainid,
                                  serviceofferingid=self.service_offering.id
                                  )
        self.debug("Deployed VM in account: %s, ID: %s" % (
                                                           self.account.name,
                                                           vm_2.id
                                                           ))
        self.cleanup.append(vm_2)

        # Remove one of the user
        self.debug("Deleting user: %s" % user_1.id)
        user_1.delete(self.apiclient)

        # Account should exist after deleting user
        accounts_response = list_accounts(
                                          self.apiclient,
                                          id=self.account.id
                                        )
        self.assertEqual(
                         isinstance(accounts_response, list),
                         True,
                         "Check for valid list accounts response"
                         )

        self.assertNotEqual(
                            len(accounts_response),
                            0,
                            "Check List Account response"
                            )
        vm_response = list_virtual_machines(
                                    self.apiclient,
                                    account=self.account.name,
                                    domainid=self.account.domainid
                                    )
        self.assertEqual(
                         isinstance(vm_response, list),
                         True,
                         "Check for valid list VM response"
                         )

        self.assertNotEqual(
                            len(vm_response),
                            0,
                            "Check List VM response"
                            )

        # VMs associated with that account should be running
        for vm in vm_response:
            self.assertEqual(
                            vm.state,
                            'Running',
                            "Check state of VMs associated with account"
                            )
        return


class TestNonRootAdminsPrivileges(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        cls.api_client = super(
                               TestNonRootAdminsPrivileges,
                               cls
                               ).getClsTestClient().getApiClient()
        cls.services = Services().services
        # Get Zone settings
        cls.zone = get_zone(cls.api_client, cls.services)
        cls.services['mode'] = cls.zone.networktype
        # Create an account, domain etc
        cls.domain = Domain.create(
                                   cls.api_client,
                                   cls.services["domain"],
                                   )
        cls.account = Account.create(
                            cls.api_client,
                            cls.services["account"],
                            admin=True,
                            domainid=cls.domain.id
                            )
        cls._cleanup = [
                        cls.account,
                        cls.domain
                        ]
        return

    @classmethod
    def tearDownClass(cls):
        try:
            #Cleanup resources used
            cleanup_resources(cls.api_client, cls._cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()
        self.cleanup = []
        return

    def tearDown(self):
        try:
            #Clean up, terminate the created accounts
            cleanup_resources(self.apiclient, self.cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"])
    def test_01_non_root_admin_Privileges(self):
        """Test to verify Non Root admin previleges"""

        # Validate the following
        # 1. Create few accounts/users in ROOT domain
        # 2. Verify listAccounts API gives only accounts associated with new
        #    domain.

        # Create accounts for ROOT domain
        account_1 = Account.create(
                            self.apiclient,
                            self.services["account"]
                            )
        self.debug("Created account: %s" % account_1.name)
        self.cleanup.append(account_1)
        account_2 = Account.create(
                            self.apiclient,
                            self.services["account"]
                            )
        self.debug("Created account: %s" % account_2.name)
        self.cleanup.append(account_2)

        accounts_response = list_accounts(
                                          self.apiclient,
                                          domainid=self.domain.id
                                          )

        self.assertEqual(
                         isinstance(accounts_response, list),
                         True,
                         "Check list accounts response for valid data"
                        )

        self.assertEqual(
                            len(accounts_response),
                            1,
                            "Check List accounts response"
                            )
        # Verify only account associated with domain is listed
        for account in accounts_response:
            self.assertEqual(
                            account.domainid,
                            self.domain.id,
                            "Check domain ID of account"
                            )
        return


class TestServiceOfferingSiblings(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        cls.api_client = super(
                               TestServiceOfferingSiblings,
                               cls
                               ).getClsTestClient().getApiClient()
        cls.services = Services().services

        # Create Domains, accounts etc
        cls.domain_1 = Domain.create(
                                   cls.api_client,
                                   cls.services["domain"]
                                   )
        cls.domain_2 = Domain.create(
                                   cls.api_client,
                                   cls.services["domain"]
                                   )
        cls.service_offering = ServiceOffering.create(
                                            cls.api_client,
                                            cls.services["service_offering"],
                                            domainid=cls.domain_1.id
                                            )
        # Create account for doamin_1
        cls.account_1 = Account.create(
                            cls.api_client,
                            cls.services["account"],
                            admin=True,
                            domainid=cls.domain_1.id
                            )

        # Create an account for domain_2
        cls.account_2 = Account.create(
                            cls.api_client,
                            cls.services["account"],
                            admin=True,
                            domainid=cls.domain_2.id
                            )

        cls._cleanup = [
                        cls.account_1,
                        cls.account_2,
                        cls.service_offering,
                        cls.domain_1,
                        cls.domain_2,
                        ]
        return

    @classmethod
    def tearDownClass(cls):
        try:
            #Cleanup resources used
            cleanup_resources(cls.api_client, cls._cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()
        self.cleanup = []
        return

    def tearDown(self):
        try:
            #Clean up, terminate the created domains, accounts
            cleanup_resources(self.apiclient, self.cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"])
    def test_01_service_offering_siblings(self):
        """Test to verify service offerings at same level in hierarchy"""

        # Validate the following
        # 1. Verify service offering is visible for domain_1
        # 2. Verify service offering is not visible for domain_2

        service_offerings = list_service_offering(
                                                  self.apiclient,
                                                  domainid=self.domain_1.id
                                                  )
        self.assertEqual(
                         isinstance(service_offerings, list),
                         True,
                         "Check if valid list service offerings response"
                        )

        self.assertNotEqual(
                            len(service_offerings),
                            0,
                            "Check List Service Offerings response"
                            )

        for service_offering in service_offerings:
            self.debug("Validating service offering: %s" % service_offering.id)
            self.assertEqual(
               service_offering.id,
               self.service_offering.id,
               "Check Service offering ID for domain" + str(self.domain_1.name)
            )
        # Verify private service offering is not visible to other domain
        service_offerings = list_service_offering(
                                                  self.apiclient,
                                                  domainid=self.domain_2.id
                                                  )
        self.assertEqual(
                    service_offerings,
                    None,
                    "Check List Service Offerings response for other domain"
                    )
        return


class TestServiceOfferingHierarchy(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        cls.api_client = super(
                               TestServiceOfferingHierarchy,
                               cls
                               ).getClsTestClient().getApiClient()
        cls.services = Services().services

        # Create domain, service offerings etc
        cls.domain_1 = Domain.create(
                                   cls.api_client,
                                   cls.services["domain"]
                                   )
        cls.domain_2 = Domain.create(
                                   cls.api_client,
                                   cls.services["domain"],
                                   parentdomainid=cls.domain_1.id
                                   )
        cls.service_offering = ServiceOffering.create(
                                            cls.api_client,
                                            cls.services["service_offering"],
                                            domainid=cls.domain_1.id
                                            )
        # Create account for doamin_1
        cls.account_1 = Account.create(
                            cls.api_client,
                            cls.services["account"],
                            admin=True,
                            domainid=cls.domain_1.id
                            )

        # Create an account for domain_2
        cls.account_2 = Account.create(
                            cls.api_client,
                            cls.services["account"],
                            admin=True,
                            domainid=cls.domain_2.id
                            )

        cls._cleanup = [
                       cls.account_2,
                       cls.domain_2,
                       cls.service_offering,
                       cls.account_1,
                       cls.domain_1,
                       ]

        return

    @classmethod
    def tearDownClass(cls):
        try:
            #Cleanup resources used
            cleanup_resources(cls.api_client, cls._cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()
        self.cleanup = []
        return

    def tearDown(self):
        try:
            #Clean up, terminate the created instance, volumes and snapshots
            cleanup_resources(self.apiclient, self.cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"])
    def test_01_service_offering_hierarchy(self):
        """Test to verify service offerings at same level in hierarchy"""

        # Validate the following
        # 1. Verify service offering is visible for domain_1
        # 2. Verify service offering is also visible for domain_2

        service_offerings = list_service_offering(
                                                  self.apiclient,
                                                  domainid=self.domain_1.id
                                                  )
        self.assertEqual(
                            isinstance(service_offerings, list),
                            True,
                            "Check List Service Offerings for a valid response"
                        )
        self.assertNotEqual(
                            len(service_offerings),
                            0,
                            "Check List Service Offerings response"
                            )

        for service_offering in service_offerings:
            self.assertEqual(
               service_offering.id,
               self.service_offering.id,
               "Check Service offering ID for domain" + str(self.domain_1.name)
            )

        # Verify private service offering is not visible to other domain
        service_offerings = list_service_offering(
                                                  self.apiclient,
                                                  domainid=self.domain_2.id
                                                  )
        self.assertEqual(
                            service_offerings,
                            None,
                            "Check List Service Offerings for a valid response"
                        )
        return


class TestTemplateHierarchy(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        cls.api_client = super(
                               TestTemplateHierarchy,
                               cls).getClsTestClient().getApiClient()
        cls.services = Services().services
        # Get Zone settings
        cls.zone = get_zone(cls.api_client, cls.services)
        cls.services['mode'] = cls.zone.networktype
        cls.services["template"]["zoneid"] = cls.zone.id

        # Create domains, accounts and template
        cls.domain_1 = Domain.create(
                                   cls.api_client,
                                   cls.services["domain"]
                                   )
        cls.domain_2 = Domain.create(
                                   cls.api_client,
                                   cls.services["domain"],
                                   parentdomainid=cls.domain_1.id
                                   )

        # Create account for doamin_1
        cls.account_1 = Account.create(
                            cls.api_client,
                            cls.services["account"],
                            admin=True,
                            domainid=cls.domain_1.id
                            )

        # Create an account for domain_2
        cls.account_2 = Account.create(
                            cls.api_client,
                            cls.services["account"],
                            admin=True,
                            domainid=cls.domain_2.id
                            )

        cls.template = Template.register(
                                            cls.api_client,
                                            cls.services["template"],
                                            account=cls.account_1.name,
                                            domainid=cls.domain_1.id
                                        )

        # Wait for template to download
        cls.template.download(cls.api_client)

        # Wait for template status to be changed across
        time.sleep(60)

        cls._cleanup = [
                        cls.account_2,
                        cls.domain_2,
                        cls.template,
                        cls.account_1,
                        cls.domain_1,
                        ]
        return

    @classmethod
    def tearDownClass(cls):
        try:
            #Cleanup resources used
            cleanup_resources(cls.api_client, cls._cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()
        self.cleanup = []
        return

    def tearDown(self):
        try:
            #Clean up, terminate the created instance, volumes and snapshots
            cleanup_resources(self.apiclient, self.cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"])
    def test_01_template_hierarchy(self):
        """Test to verify template at same level in hierarchy"""

        # Validate the following
        # 1. Verify template is visible for domain_1
        # 2. Verify template is also visible for domain_2

        # Sleep to ensure that template state is reflected across

        templates = list_templates(
                                    self.apiclient,
                                    templatefilter='self',
                                    account=self.account_1.name,
                                    domainid=self.domain_1.id
                                )
        self.assertEqual(
                            isinstance(templates, list),
                            True,
                            "Template response %s is not a list" % templates
                        )
        self.assertNotEqual(
                            len(templates),
                            0,
                            "No templates found"
                            )

        for template in templates:
            self.assertEqual(
               template.id,
               self.template.id,
               "Check Template ID for domain" + str(self.domain_1.name)
            )

        # Verify private service offering is not visible to other domain
        templates = list_templates(
                                    self.apiclient,
                                    id=self.template.id,
                                    templatefilter='all',
                                    account=self.account_2.name,
                                    domainid=self.domain_2.id
                                )
        self.assertEqual(
                            isinstance(templates, list),
                            True,
                            "Template response %s is not a list" % templates
                        )
        self.assertNotEqual(
                            len(templates),
                            0,
                            "No templates found"
                            )

        for template in templates:
            self.assertEqual(
               template.id,
               self.template.id,
               "Check Template ID for domain" + str(self.domain_2.name)
            )
        return


class TestAddVmToSubDomain(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        cls.api_client = super(
                               TestAddVmToSubDomain,
                               cls
                               ).getClsTestClient().getApiClient()
        cls.services = Services().services

        # Setup working Environment- Create domain, zone, pod cluster etc.
        cls.domain = get_domain(
                                   cls.api_client,
                                   cls.services
                                   )
        cls.zone = get_zone(
                               cls.api_client,
                               cls.services,
                               )
        cls.services['mode'] = cls.zone.networktype
        cls.sub_domain = Domain.create(
                                   cls.api_client,
                                   cls.services["domain"],
                                   parentdomainid=cls.domain.id
                                   )

        # Create account for doamin_1
        cls.account_1 = Account.create(
                            cls.api_client,
                            cls.services["account"],
                            admin=True,
                            domainid=cls.domain.id
                            )

        # Create an account for domain_2
        cls.account_2 = Account.create(
                            cls.api_client,
                            cls.services["account"],
                            admin=True,
                            domainid=cls.sub_domain.id
                            )

        cls.service_offering = ServiceOffering.create(
                                    cls.api_client,
                                    cls.services["service_offering"],
                                    domainid=cls.domain.id
                                    )
        cls.template = get_template(
                            cls.api_client,
                            cls.zone.id,
                            cls.services["ostype"]
                            )
        cls.services["virtual_machine"]["zoneid"] = cls.zone.id
        cls.vm_1 = VirtualMachine.create(
                                    cls.api_client,
                                    cls.services["virtual_machine"],
                                    templateid=cls.template.id,
                                    accountid=cls.account_1.name,
                                    domainid=cls.account_1.domainid,
                                    serviceofferingid=cls.service_offering.id
                                    )

        cls.vm_2 = VirtualMachine.create(
                                    cls.api_client,
                                    cls.services["virtual_machine"],
                                    templateid=cls.template.id,
                                    accountid=cls.account_2.name,
                                    domainid=cls.account_2.domainid,
                                    serviceofferingid=cls.service_offering.id
                                    )
        cls._cleanup = [
                        cls.account_2,
                        cls.account_1,
                        cls.sub_domain,
                        cls.service_offering
                        ]
        return

    @classmethod
    def tearDownClass(cls):
        try:
            #Clean up, terminate the created resources
            cleanup_resources(cls.api_client, cls._cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()
        self.cleanup = []
        return

    def tearDown(self):
        try:
            #Clean up, terminate the created resources
            cleanup_resources(self.apiclient, self.cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"])
    def test_01_add_vm_to_subdomain(self):
        """ Test Sub domain allowed to launch VM  when a Domain level zone is created"""

        # Validate the following
        # 1. Verify VM created by Account_1 is in Running state
        # 2. Verify VM created by Account_2 is in Running state

        vm_response = list_virtual_machines(
                                    self.apiclient,
                                    id=self.vm_1.id
                                )
        self.assertEqual(
                            isinstance(vm_response, list),
                            True,
                            "Check List VM for a valid response"
                        )
        self.assertNotEqual(
                            len(vm_response),
                            0,
                            "Check List Template response"
                            )

        for vm in vm_response:
            self.debug("VM ID: %s and state: %s" % (vm.id, vm.state))
            self.assertEqual(
                             vm.state,
                             'Running',
                             "Check State of Virtual machine"
                             )

        vm_response = list_virtual_machines(
                                    self.apiclient,
                                    id=self.vm_2.id
                                )
        self.assertNotEqual(
                            len(vm_response),
                            0,
                            "Check List Template response"
                            )

        for vm in vm_response:
            self.debug("VM ID: %s and state: %s" % (vm.id, vm.state))
            self.assertEqual(
                             vm.state,
                             'Running',
                             "Check State of Virtual machine"
                             )
        return


class TestUserDetails(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        cls.api_client = super(
                               TestUserDetails,
                               cls
                               ).getClsTestClient().getApiClient()
        cls.services = Services().services
        # Get Zone, Domain etc
        cls.domain = get_domain(cls.api_client, cls.services)
        cls.zone = get_zone(cls.api_client, cls.services)
        cls.services['mode'] = cls.zone.networktype
        cls._cleanup = []
        return

    @classmethod
    def tearDownClass(cls):
        try:
            #Cleanup resources used
            cleanup_resources(cls.api_client, cls._cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()
        self.cleanup = []
        return

    def tearDown(self):
        try:
            #Clean up, terminate the created network offerings
            cleanup_resources(self.apiclient, self.cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    @attr(tags=[
                "role",
                "accounts",
                "simulator",
                "advanced",
                "advancedns",
                "basic",
                "eip",
                "sg"
                ])
    def test_updateUserDetails(self):
        """Test user update API
        """

        # Steps for test scenario
        # 1. create a user account
        # 2. update the user details (firstname, lastname, user) with
        #    updateUser API
        # 3. listUsers in the account
        # 4. delete the account
        # Validate the following
        # 1. listAccounts should show account created successfully
        # 2. updateUser API should return valid response
        # 3. user should be updated with new details

        self.debug("Creating an user account..")
        self.account = Account.create(
                                     self.apiclient,
                                     self.services["account"],
                                     domainid=self.domain.id
                                     )
        self.cleanup.append(self.account)

        # Fetching the user details of account
        self.debug(
                   "Fetching user details for account: %s" %
                                            self.account.name)
        users = User.list(
                          self.apiclient,
                          account=self.account.name,
                          domainid=self.account.domainid
                          )
        self.assertEqual(
                         isinstance(users, list),
                         True,
                         "List users should return a valid list for account"
                         )
        user_1 = users[0]
        self.debug("Updating the details of user: %s" % user_1.name)
        firstname = random_gen()
        lastname = random_gen()

        self.debug("New firstname: %s, lastname: %s" % (firstname, lastname))
        User.update(
                    self.apiclient,
                    user_1.id,
                    firstname=firstname,
                    lastname=lastname
                    )

        # Fetching the user details of account
        self.debug(
                   "Fetching user details for user: %s" % user_1.name)
        users = User.list(
                          self.apiclient,
                          id=user_1.id,
                          listall=True
                          )

        self.assertEqual(
                         isinstance(users, list),
                         True,
                         "List users should return a valid list for account"
                         )
        user_1 = users[0]
        self.assertEqual(
                         user_1.firstname,
                         firstname,
                         "User's first name should be updated with new one"
                         )
        self.assertEqual(
                         user_1.lastname,
                         lastname,
                         "User's last name should be updated with new one"
                         )
        return

    @attr(tags=[
                "role",
                "accounts",
                "simulator",
                "advanced",
                "advancedns",
                "basic",
                "eip",
                "sg"
                ])
    def test_updateAdminDetails(self):
        """Test update admin details
        """

        # Steps for test scenario
        # 1. create a admin account
        # 2. update the user details (firstname, lastname, user) with
        #    updateUser API
        # 3. listUsers in the account
        # 4. delete the account
        # Validate the following
        # 1. listAccounts should show account created successfully
        # 2. updateUser API should return valid response
        # 3. user should be updated with new details

        self.debug("Creating a ROOT admin account")
        self.account = Account.create(
                                     self.apiclient,
                                     self.services["account"],
                                     admin=True,
                                     )
        self.cleanup.append(self.account)

        # Fetching the user details of account
        self.debug(
                   "Fetching user details for account: %s" %
                                            self.account.name)
        users = User.list(
                          self.apiclient,
                          account=self.account.name,
                          domainid=self.account.domainid
                          )
        self.assertEqual(
                         isinstance(users, list),
                         True,
                         "List users should return a valid list for account"
                         )
        user_1 = users[0]
        self.debug("Updating the details of user: %s" % user_1.name)
        firstname = random_gen()
        lastname = random_gen()

        self.debug("New firstname: %s, lastname: %s" % (firstname, lastname))
        User.update(
                    self.apiclient,
                    user_1.id,
                    firstname=firstname,
                    lastname=lastname
                    )

        # Fetching the user details of account
        self.debug(
                   "Fetching user details for user: %s" % user_1.name)
        users = User.list(
                          self.apiclient,
                          id=user_1.id,
                          listall=True
                          )

        self.assertEqual(
                         isinstance(users, list),
                         True,
                         "List users should return a valid list for account"
                         )
        user_1 = users[0]
        self.assertEqual(
                         user_1.firstname,
                         firstname,
                         "User's first name should be updated with new one"
                         )
        self.assertEqual(
                         user_1.lastname,
                         lastname,
                         "User's last name should be updated with new one"
                         )
        return

    @attr(tags=[
                "role",
                "accounts",
                "simulator",
                "advanced",
                "advancedns",
                "basic",
                "eip",
                "sg"
                ])
    def test_updateDomainAdminDetails(self):
        """Test update domain admin details
        """

        # Steps for test scenario
        # 2. update the user details (firstname, lastname, user) with
        #    updateUser API
        # 3. listUsers in the account
        # 4. delete the account
        # Validate the following
        # 1. listAccounts should show account created successfully
        # 2. updateUser API should return valid response
        # 3. user should be updated with new details

        self.debug("Creating a domain admin account")
        self.account = Account.create(
                                     self.apiclient,
                                     self.services["account"],
                                     admin=True,
                                     domainid=self.domain.id
                                     )
        self.cleanup.append(self.account)

        # Fetching the user details of account
        self.debug(
                   "Fetching user details for account: %s" %
                                            self.account.name)
        users = User.list(
                          self.apiclient,
                          account=self.account.name,
                          domainid=self.account.domainid
                          )
        self.assertEqual(
                         isinstance(users, list),
                         True,
                         "List users should return a valid list for account"
                         )
        user_1 = users[0]
        self.debug("Updating the details of user: %s" % user_1.name)
        firstname = random_gen()
        lastname = random_gen()

        self.debug("New firstname: %s, lastname: %s" % (firstname, lastname))
        User.update(
                    self.apiclient,
                    user_1.id,
                    firstname=firstname,
                    lastname=lastname
                    )

        # Fetching the user details of account
        self.debug(
                   "Fetching user details for user: %s" % user_1.name)
        users = User.list(
                          self.apiclient,
                          id=user_1.id,
                          listall=True
                          )

        self.assertEqual(
                         isinstance(users, list),
                         True,
                         "List users should return a valid list for account"
                         )
        user_1 = users[0]
        self.assertEqual(
                         user_1.firstname,
                         firstname,
                         "User's first name should be updated with new one"
                         )
        self.assertEqual(
                         user_1.lastname,
                         lastname,
                         "User's last name should be updated with new one"
                         )
        return

class TestUserLogin(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        cls.api_client = super(
                               TestUserLogin,
                               cls
                               ).getClsTestClient().getApiClient()
        cls.services = Services().services
        # Get Zone, Domain etc
        cls.domain = get_domain(cls.api_client, cls.services)
        cls.zone = get_zone(cls.api_client, cls.services)
        cls.services['mode'] = cls.zone.networktype
        cls._cleanup = []
        return

    @classmethod
    def tearDownClass(cls):
        try:
            #Cleanup resources used
            cleanup_resources(cls.api_client, cls._cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()
        self.cleanup = []
        return

    def tearDown(self):
        try:
            #Clean up, terminate the created network offerings
            cleanup_resources(self.apiclient, self.cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    @attr(tags=["login", "accounts", "simulator", "advanced",
                        "advancedns", "basic", "eip", "sg"])
    def test_LoginApiUuidResponse(self):
        """Test if Login API does not return UUID's
        """

        # Steps for test scenario
        # 1. create a user account
        # 2. login to the user account with given credentials (loginCmd)
        # 3. delete the user account
        # Validate the following
        # 1. listAccounts should return account created
        # 2. loginResponse should have UUID only is response. Assert by
        #    checking database id is not same as response id
        #    Login also succeeds with non NULL sessionId in response

        self.debug("Creating an user account..")
        self.account = Account.create(
                                     self.apiclient,
                                     self.services["account"],
                                     domainid=self.domain.id
                                     )
        self.cleanup.append(self.account)

        self.debug("Logging into the cloudstack with login API")
        respose = User.login(
                             self.apiclient,
                             username=self.account.name,
                             password=self.services["account"]["password"]
                             )

        self.debug("Login API response: %s" % respose)

        self.assertNotEqual(
                            respose.sessionkey,
                            None,
                            "Login to the CloudStack should be successful" +
                            "response shall have non Null key"
                            )
        return

    @attr(tags=["login", "accounts", "simulator", "advanced",
                        "advancedns", "basic", "eip", "sg"])
    def test_LoginApiDomain(self):
        """Test login API with domain
        """

        # Steps for test scenario
        # 1. create a domain
        # 2. create user in the domain
        # 3. login to the user account above using UUID domain/user
        # 4. delete the user account
        # Validate the following
        # 1. listDomains returns created domain
        # 2. listAccounts returns created user
        # 3. loginResponse should have UUID only in responses
        #    Login also succeeds with non NULL sessionId in response

        self.debug("Creating a domain for login with API domain test")
        domain = Domain.create(
                                self.apiclient,
                                self.services["domain"],
                                parentdomainid=self.domain.id
                                )
        self.debug("Domain: %s is created succesfully." % domain.name)
        self.debug(
            "Checking if the created domain is listed in list domains API")
        domains = Domain.list(self.apiclient, id=domain.id, listall=True)

        self.assertEqual(
                         isinstance(domains, list),
                         True,
                         "List domains shall return a valid response"
                         )
        self.debug("Creating an user account in domain: %s" % domain.name)
        self.account = Account.create(
                                     self.apiclient,
                                     self.services["account"],
                                     domainid=domain.id
                                     )
        self.cleanup.append(self.account)

        accounts = Account.list(
                                self.apiclient,
                                name=self.account.name,
                                domainid=self.account.domainid,
                                listall=True
                                )

        self.assertEqual(
                         isinstance(accounts, list),
                         True,
                         "List accounts should return a valid response"
                         )

        self.debug("Logging into the cloudstack with login API")
        respose = User.login(
                             self.apiclient,
                             username=self.account.name,
                             password=self.services["account"]["password"],
                             domainid=domain.id)
        self.debug("Login API response: %s" % respose)

        self.assertNotEqual(
                            respose.sessionkey,
                            None,
                            "Login to the CloudStack should be successful" +
                            "response shall have non Null key"
                            )
        return


class TestDomainForceRemove(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        cls.api_client = super(
                               TestDomainForceRemove,
                               cls
                               ).getClsTestClient().getApiClient()
        cls.services = Services().services

        # Setup working Environment- Create domain, zone, pod cluster etc.
        cls.domain = get_domain(
                                   cls.api_client,
                                   cls.services
                                   )
        cls.zone = get_zone(
                               cls.api_client,
                               cls.services,
                               )
        cls.services['mode'] = cls.zone.networktype

        cls.template = get_template(
                            cls.api_client,
                            cls.zone.id,
                            cls.services["ostype"]
                            )

        cls.services["virtual_machine"]["zoneid"] = cls.zone.id
        cls._cleanup = []
        return

    @classmethod
    def tearDownClass(cls):
        try:
            #Clean up, terminate the created resources
            cleanup_resources(cls.api_client, cls._cleanup)
        except Exception as e:

            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()
        self.cleanup = []
        return

    def tearDown(self):
        try:
            #Clean up, terminate the created resources
            cleanup_resources(self.apiclient, self.cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    @attr(tags=["domains", "advanced", "advancedns", "simulator"])
    def test_forceDeleteDomain(self):
        """ Test delete domain with force option"""

        # Steps for validations
        # 1. create a domain DOM
        # 2. create 2 users under this domain
        # 3. deploy 1 VM into each of these user accounts
        # 4. create PF / FW rules for port 22 on these VMs for their
        #    respective accounts
        # 5. delete the domain with force=true option
        # Validate the following
        # 1. listDomains should list the created domain
        # 2. listAccounts should list the created accounts
        # 3. listvirtualmachines should show the Running VMs
        # 4. PF and FW rules should be shown in listFirewallRules
        # 5. domain should delete successfully and above three list calls
        #    should show all the resources now deleted. listRouters should
        #    not return any routers in the deleted accounts/domains

        self.debug("Creating a domain for login with API domain test")
        domain = Domain.create(
                                self.apiclient,
                                self.services["domain"],
                                parentdomainid=self.domain.id
                                )
        self.debug("Domain is created succesfully.")
        self.debug(
            "Checking if the created domain is listed in list domains API")
        domains = Domain.list(self.apiclient, id=domain.id, listall=True)

        self.assertEqual(
                         isinstance(domains, list),
                         True,
                         "List domains shall return a valid response"
                         )
        self.debug("Creating 2 user accounts in domain: %s" % domain.name)
        self.account_1 = Account.create(
                                     self.apiclient,
                                     self.services["account"],
                                     domainid=domain.id
                                     )

        self.account_2 = Account.create(
                                     self.apiclient,
                                     self.services["account"],
                                     domainid=domain.id
                                     )

        self.debug("Creating a tiny service offering for VM deployment")
        self.service_offering = ServiceOffering.create(
                                    self.apiclient,
                                    self.services["service_offering"],
                                    domainid=self.domain.id
                                    )

        self.debug("Deploying virtual machine in account 1: %s" %
                                                self.account_1.name)
        vm_1 = VirtualMachine.create(
                                    self.apiclient,
                                    self.services["virtual_machine"],
                                    templateid=self.template.id,
                                    accountid=self.account_1.name,
                                    domainid=self.account_1.domainid,
                                    serviceofferingid=self.service_offering.id
                                    )

        self.debug("Deploying virtual machine in account 2: %s" %
                                                self.account_2.name)
        vm_2 = VirtualMachine.create(
                                    self.apiclient,
                                    self.services["virtual_machine"],
                                    templateid=self.template.id,
                                    accountid=self.account_2.name,
                                    domainid=self.account_2.domainid,
                                    serviceofferingid=self.service_offering.id
                                    )

        networks = Network.list(
                                self.apiclient,
                                account=self.account_1.name,
                                domainid=self.account_1.domainid,
                                listall=True
                                )
        self.assertEqual(
                         isinstance(networks, list),
                         True,
                         "List networks should return a valid response"
                         )
        network_1 = networks[0]
        self.debug("Default network in account 1: %s is %s" % (
                                                self.account_1.name,
                                                network_1.name))
        src_nat_list = PublicIPAddress.list(
                                    self.apiclient,
                                    associatednetworkid=network_1.id,
                                    account=self.account_1.name,
                                    domainid=self.account_1.domainid,
                                    listall=True,
                                    issourcenat=True,
                                    )
        self.assertEqual(
                         isinstance(src_nat_list, list),
                         True,
                         "List Public IP should return a valid source NAT"
                         )
        self.assertNotEqual(
                    len(src_nat_list),
                    0,
                    "Length of response from listPublicIp should not be 0"
                    )

        src_nat = src_nat_list[0]

        self.debug(
            "Trying to create a port forwarding rule in source NAT: %s" %
                                                            src_nat.ipaddress)
        #Create NAT rule
        nat_rule = NATRule.create(
                                  self.apiclient,
                                  vm_1,
                                  self.services["natrule"],
                                  ipaddressid=src_nat.id
                           )
        self.debug("Created PF rule on source NAT: %s" % src_nat.ipaddress)

        nat_rules = NATRule.list(self.apiclient, id=nat_rule.id)

        self.assertEqual(
                         isinstance(nat_rules, list),
                         True,
                         "List NAT should return a valid port forwarding rules"
                         )

        self.assertNotEqual(
                    len(nat_rules),
                    0,
                    "Length of response from listLbRules should not be 0"
                    )

        self.debug("Deleting domain with force option")
        try:
            domain.delete(self.apiclient, cleanup=True)
        except Exception as e:
            self.debug("Waiting for account.cleanup.interval" +
                " to cleanup any remaining resouces")
            # Sleep 3*account.gc to ensure that all resources are deleted
            wait_for_cleanup(self.apiclient, ["account.cleanup.interval"]*3)
            with self.assertRaises(cloudstackAPIException):
                Domain.list(
                        self.apiclient,
                        id=domain.id,
                        listall=True
                        )

        self.debug("Checking if the resources in domain are deleted")
        with self.assertRaises(cloudstackAPIException):
            Account.list(
                        self.apiclient,
                        name=self.account_1.name,
                        domainid=self.account_1.domainid,
                        listall=True
                        )
        return

    @attr(tags=["domains", "advanced", "advancedns", "simulator"])
    def test_DeleteDomain(self):
        """ Test delete domain without force option"""

        # Steps for validations
        # 1. create a domain DOM
        # 2. create 2 users under this domain
        # 3. deploy 1 VM into each of these user accounts
        # 4. create PF / FW rules for port 22 on these VMs for their
        #    respective accounts
        # 5. delete the domain with force=false option
        # Validate the following
        # 1. listDomains should list the created domain
        # 2. listAccounts should list the created accounts
        # 3. listvirtualmachines should show the Running VMs
        # 4. PF and FW rules should be shown in listFirewallRules
        # 5. domain deletion should fail saying there are resources under use

        self.debug("Creating a domain for login with API domain test")
        domain = Domain.create(
                                self.apiclient,
                                self.services["domain"],
                                parentdomainid=self.domain.id
                                )
        self.debug("Domain: %s is created successfully." % domain.name)
        self.debug(
            "Checking if the created domain is listed in list domains API")
        domains = Domain.list(self.apiclient, id=domain.id, listall=True)

        self.assertEqual(
                         isinstance(domains, list),
                         True,
                         "List domains shall return a valid response"
                         )
        self.debug("Creating 2 user accounts in domain: %s" % domain.name)
        self.account_1 = Account.create(
                                     self.apiclient,
                                     self.services["account"],
                                     domainid=domain.id
                                     )
        self.cleanup.append(self.account_1)

        self.account_2 = Account.create(
                                     self.apiclient,
                                     self.services["account"],
                                     domainid=domain.id
                                     )
        self.cleanup.append(self.account_2)

        self.debug("Creating a tiny service offering for VM deployment")
        self.service_offering = ServiceOffering.create(
                                    self.apiclient,
                                    self.services["service_offering"],
                                    domainid=self.domain.id
                                    )
        self.cleanup.append(self.service_offering)

        self.debug("Deploying virtual machine in account 1: %s" %
                                                self.account_1.name)
        vm_1 = VirtualMachine.create(
                                    self.apiclient,
                                    self.services["virtual_machine"],
                                    templateid=self.template.id,
                                    accountid=self.account_1.name,
                                    domainid=self.account_1.domainid,
                                    serviceofferingid=self.service_offering.id
                                    )

        self.debug("Deploying virtual machine in account 2: %s" %
                                                self.account_2.name)
        vm_2 = VirtualMachine.create(
                                    self.apiclient,
                                    self.services["virtual_machine"],
                                    templateid=self.template.id,
                                    accountid=self.account_2.name,
                                    domainid=self.account_2.domainid,
                                    serviceofferingid=self.service_offering.id
                                    )

        networks = Network.list(
                                self.apiclient,
                                account=self.account_1.name,
                                domainid=self.account_1.domainid,
                                listall=True
                                )
        self.assertEqual(
                         isinstance(networks, list),
                         True,
                         "List networks should return a valid response"
                         )
        network_1 = networks[0]
        self.debug("Default network in account 1: %s is %s" % (
                                                self.account_1.name,
                                                network_1.name))
        src_nat_list = PublicIPAddress.list(
                                    self.apiclient,
                                    associatednetworkid=network_1.id,
                                    account=self.account_1.name,
                                    domainid=self.account_1.domainid,
                                    listall=True,
                                    issourcenat=True,
                                    )
        self.assertEqual(
                         isinstance(src_nat_list, list),
                         True,
                         "List Public IP should return a valid source NAT"
                         )
        self.assertNotEqual(
                    len(src_nat_list),
                    0,
                    "Length of response from listPublicIp should not be 0"
                    )

        src_nat = src_nat_list[0]

        self.debug(
            "Trying to create a port forwarding rule in source NAT: %s" %
                                                            src_nat.ipaddress)
        #Create NAT rule
        nat_rule = NATRule.create(
                                  self.apiclient,
                                  vm_1,
                                  self.services["natrule"],
                                  ipaddressid=src_nat.id
                           )
        self.debug("Created PF rule on source NAT: %s" % src_nat.ipaddress)

        nat_rules = NATRule.list(self.apiclient, id=nat_rule.id)

        self.assertEqual(
                         isinstance(nat_rules, list),
                         True,
                         "List NAT should return a valid port forwarding rules"
                         )

        self.assertNotEqual(
                    len(nat_rules),
                    0,
                    "Length of response from listLbRules should not be 0"
                    )

        self.debug("Deleting domain without force option")
        with self.assertRaises(Exception):
            domain.delete(self.apiclient, cleanup=False)
        return
