You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by da...@apache.org on 2014/07/28 23:13:54 UTC

[26/50] [abbrv] CLOUDSTACK-1466: Automation - Priamary Storage Limits

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/12b6cf1b/test/integration/component/test_ps_resize_volume.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_ps_resize_volume.py b/test/integration/component/test_ps_resize_volume.py
new file mode 100644
index 0000000..737f910
--- /dev/null
+++ b/test/integration/component/test_ps_resize_volume.py
@@ -0,0 +1,339 @@
+# 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 testing resize volume functionality with primary storage limit constraints on
+    account/domain
+
+    Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domain+or+accounts
+
+    Issue Link: https://issues.apache.org/jira/browse/CLOUDSTACK-1466
+
+    Feature Specifications: https://cwiki.apache.org/confluence/display/CLOUDSTACK/Limit+Resources+to+domains+and+accounts
+"""
+# Import Local Modules
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase, unittest
+from marvin.lib.base import (Account,
+                             ServiceOffering,
+                             VirtualMachine,
+                             Resources,
+                             Domain,
+                             DiskOffering,
+                             Volume)
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               matchResourceCount,
+                               isDomainResourceCountEqualToExpectedCount)
+from marvin.lib.utils import (cleanup_resources,
+                              get_hypervisor_type)
+from marvin.codes import (PASS,
+                          FAIL,
+                          FAILED,
+                          RESOURCE_PRIMARY_STORAGE,
+                          RESOURCE_SECONDARY_STORAGE,
+                          XEN_SERVER)
+
+class TestResizeVolume(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        cloudstackTestClient = super(TestResizeVolume,
+                               cls).getClsTestClient()
+        cls.api_client = cloudstackTestClient.getApiClient()
+        # Fill services from the external config file
+        cls.services = cloudstackTestClient.getParsedTestDataConfig()
+        # Get Zone, Domain and templates
+        cls.domain = get_domain(cls.api_client)
+        cls.zone = get_zone(cls.api_client, cloudstackTestClient.getZoneForTests())
+        cls.services["mode"] = cls.zone.networktype
+        cls.resourcetypemapping = {RESOURCE_PRIMARY_STORAGE: 10,
+                                   RESOURCE_SECONDARY_STORAGE: 11}
+
+        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.services["volume"]["zoneid"] = cls.zone.id
+
+        cls._cleanup = []
+        try:
+            cls.hypervisor = str(get_hypervisor_type(cls.api_client)).lower()
+
+            # Creating service offering with normal config
+            cls.service_offering = ServiceOffering.create(cls.api_client,
+                                            cls.services["service_offering"])
+            cls._cleanup.append(cls.service_offering)
+
+            cls.services["disk_offering"]["disksize"] = 5
+            cls.disk_offering_5_GB = DiskOffering.create(
+                                    cls.api_client,
+                                    cls.services["disk_offering"]
+                                    )
+            cls._cleanup.append(cls.disk_offering_5_GB)
+
+            cls.services["disk_offering"]["disksize"] = 20
+            cls.disk_offering_20_GB = DiskOffering.create(
+                                    cls.api_client,
+                                    cls.services["disk_offering"]
+                                    )
+            cls._cleanup.append(cls.disk_offering_20_GB)
+        except Exception as e:
+            cls.tearDownClass()
+            raise unittest.SkipTest("Failure while creating disk offering: %s" % e)
+        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)
+            pass
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    def updateResourceLimits(self, accountLimit=None, domainLimit=None):
+        """Update primary storage limits of the parent domain and its
+        child domains"""
+
+        try:
+            if domainLimit:
+                #Update resource limit for domain
+                Resources.updateLimit(self.apiclient, resourcetype=10,
+                              max=domainLimit,
+                              domainid=self.parent_domain.id)
+            if accountLimit:
+                #Update resource limit for domain
+                Resources.updateLimit(self.apiclient, resourcetype=10,
+                              max=accountLimit, account=self.parentd_admin.name,
+                              domainid=self.parent_domain.id)
+        except Exception as e:
+            return [FAIL, e]
+        return [PASS, None]
+
+    def setupAccounts(self):
+        try:
+            self.parent_domain = Domain.create(self.apiclient,
+                                        services=self.services["domain"],
+                                        parentdomainid=self.domain.id)
+            self.parentd_admin = Account.create(self.apiclient, self.services["account"],
+                                            admin=True, domainid=self.parent_domain.id)
+
+            # Cleanup the resources created at end of test
+            self.cleanup.append(self.parentd_admin)
+            self.cleanup.append(self.parent_domain)
+        except Exception as e:
+            return [FAIL, e]
+        return [PASS, None]
+
+    @attr(tags=["advanced", "selfservice"])
+    def test_01_increase_volume_size_within_account_limit(self):
+	"""Test increasing volume size within the account limit and verify primary storage usage
+
+        # Validate the following
+        # 1. Create a domain and its admin account
+        # 2. Set account primary storage limit well beyond (20 GB volume + template size of VM)
+        # 3. Deploy a VM without any disk offering (only root disk)
+        # 4. Create a volume of 5 GB in the account and attach it to the VM
+        # 5. Increase (resize) the volume to 20 GB
+        # 6. Resize opearation should be successful and primary storage counnt for
+        #    account should be updated successfully"""
+
+        # Setting up account and domain hierarchy
+        result = self.setupAccounts()
+        self.assertEqual(result[0], PASS, result[1])
+
+        apiclient = self.testClient.getUserApiClient(
+                        UserName=self.parentd_admin.name,
+                        DomainName=self.parentd_admin.domain)
+        self.assertNotEqual(apiclient, FAILED, "Failed to get api client\
+                            of account: %s" % self.parentd_admin.name)
+
+        templateSize = (self.template.size / (1024**3))
+        accountLimit = (templateSize + self.disk_offering_20_GB.disksize)
+        response = self.updateResourceLimits(accountLimit=accountLimit)
+        self.assertEqual(response[0], PASS, response[1])
+        try:
+            virtualMachine = VirtualMachine.create(
+                    apiclient, self.services["virtual_machine"],
+                    accountid=self.parentd_admin.name, domainid=self.parent_domain.id,
+                    serviceofferingid=self.service_offering.id
+                    )
+
+            volume = Volume.create(
+                    apiclient,self.services["volume"],zoneid=self.zone.id,
+                    account=self.parentd_admin.name,domainid=self.parent_domain.id,
+                    diskofferingid=self.disk_offering_5_GB.id)
+
+            virtualMachine.attach_volume(apiclient, volume=volume)
+
+            expectedCount = (templateSize + self.disk_offering_5_GB.disksize)
+            response = matchResourceCount(
+                        self.apiclient, expectedCount,
+                        RESOURCE_PRIMARY_STORAGE,
+                        accountid=self.parentd_admin.id)
+            if response[0] == FAIL:
+                raise Exception(response[1])
+
+            if self.hypervisor == str(XEN_SERVER).lower():
+                virtualMachine.stop(self.apiclient)
+            volume.resize(apiclient, diskofferingid=self.disk_offering_20_GB.id)
+
+            expectedCount = (templateSize + self.disk_offering_20_GB.disksize)
+            response = matchResourceCount(
+                        self.apiclient, expectedCount,
+                        RESOURCE_PRIMARY_STORAGE,
+                        accountid=self.parentd_admin.id)
+            if response[0] == FAIL:
+                raise Exception(response[1])
+        except Exception as e:
+            self.fail("Failed with exception: %s" % e)
+        return
+
+    @attr(tags=["advanced", "selfservice"])
+    def test_02_increase_volume_size_above_account_limit(self):
+	"""Test increasing volume size above the account limit
+
+        # Validate the following
+        # 1. Create a domain and its admin account
+        # 2. Set account primary storage limit more than (5 GB volume + template size of VM)
+        #    and less than (20 GB volume+ template size of VM)
+        # 3. Deploy a VM without any disk offering (only root disk)
+        # 4. Create a volume of 5 GB in the account and attach it to the VM
+        # 5. Try to (resize) the volume to 20 GB
+        # 6. Resize opearation should fail"""
+
+        # Setting up account and domain hierarchy
+        result = self.setupAccounts()
+        self.assertEqual(result[0], PASS, result[1])
+
+        templateSize = (self.template.size / (1024**3))
+        accountLimit = ((templateSize + self.disk_offering_20_GB.disksize) - 1)
+        response = self.updateResourceLimits(accountLimit=accountLimit)
+        self.assertEqual(response[0], PASS, response[1])
+
+        apiclient = self.testClient.getUserApiClient(
+                        UserName=self.parentd_admin.name,
+                        DomainName=self.parentd_admin.domain)
+        self.assertNotEqual(apiclient, FAILED, "Failed to get api client\
+                            of account: %s" % self.parentd_admin.name)
+
+        try:
+            virtualMachine = VirtualMachine.create(
+                    apiclient, self.services["virtual_machine"],
+                    accountid=self.parentd_admin.name, domainid=self.parent_domain.id,
+                    serviceofferingid=self.service_offering.id
+                    )
+
+            volume = Volume.create(
+                    apiclient,self.services["volume"],zoneid=self.zone.id,
+                    account=self.parentd_admin.name,domainid=self.parent_domain.id,
+                    diskofferingid=self.disk_offering_5_GB.id)
+
+            virtualMachine.attach_volume(apiclient, volume=volume)
+
+            expectedCount = (templateSize + self.disk_offering_5_GB.disksize)
+            response = matchResourceCount(
+                        self.apiclient, expectedCount,
+                        RESOURCE_PRIMARY_STORAGE,
+                        accountid=self.parentd_admin.id)
+            if response[0] == FAIL:
+                raise Exception(response[1])
+        except Exception as e:
+            self.fail("Failed with exception: %s" % e)
+
+        if self.hypervisor == str(XEN_SERVER).lower():
+            virtualMachine.stop(self.apiclient)
+        with self.assertRaises(Exception):
+            volume.resize(apiclient, diskofferingid=self.disk_offering_20_GB.id)
+        return
+
+    @attr(tags=["advanced", "selfservice"])
+    def test_03_increase_volume_size_above_domain_limit(self):
+	"""Test increasing volume size above the domain limit
+
+        # Validate the following
+        # 1. Create a domain and its admin account
+        # 2. Set domain primary storage limit more than (5 GB volume + template size of VM)
+        #    and less than (20 GB volume+ template size of VM)
+        # 3. Deploy a VM without any disk offering (only root disk)
+        # 4. Create a volume of 5 GB in the account and attach it to the VM
+        # 5. Try to (resize) the volume to 20 GB
+        # 6. Resize opearation should fail"""
+
+        # Setting up account and domain hierarchy
+        result = self.setupAccounts()
+        self.assertEqual(result[0], PASS, result[1])
+
+        templateSize = (self.template.size / (1024**3))
+        domainLimit = ((templateSize + self.disk_offering_20_GB.disksize) - 1)
+        response = self.updateResourceLimits(domainLimit=domainLimit)
+        self.assertEqual(response[0], PASS, response[1])
+
+        apiclient = self.testClient.getUserApiClient(
+                        UserName=self.parentd_admin.name,
+                        DomainName=self.parentd_admin.domain)
+        self.assertNotEqual(apiclient, FAILED, "Failed to get api client\
+                            of account: %s" % self.parentd_admin.name)
+
+        try:
+            virtualMachine = VirtualMachine.create(
+                    apiclient, self.services["virtual_machine"],
+                    accountid=self.parentd_admin.name, domainid=self.parent_domain.id,
+                    serviceofferingid=self.service_offering.id
+                    )
+
+            volume = Volume.create(
+                    apiclient,self.services["volume"],zoneid=self.zone.id,
+                    account=self.parentd_admin.name,domainid=self.parent_domain.id,
+                    diskofferingid=self.disk_offering_5_GB.id)
+
+            virtualMachine.attach_volume(apiclient, volume=volume)
+
+            expectedCount = (templateSize + self.disk_offering_5_GB.disksize)
+            result = isDomainResourceCountEqualToExpectedCount(
+                        self.apiclient, self.parent_domain.id,
+                        expectedCount, RESOURCE_PRIMARY_STORAGE)
+            self.assertFalse(result[0], result[1])
+            self.assertTrue(result[2], "Resource count does not match")
+        except Exception as e:
+            self.fail("Failed with exception: %s" % e)
+
+        if self.hypervisor == str(XEN_SERVER).lower():
+            virtualMachine.stop(self.apiclient)
+        with self.assertRaises(Exception):
+            volume.resize(apiclient, diskofferingid=self.disk_offering_20_GB.id)
+        return

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/12b6cf1b/tools/marvin/marvin/codes.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/codes.py b/tools/marvin/marvin/codes.py
index c72a6bd..e6e5602 100644
--- a/tools/marvin/marvin/codes.py
+++ b/tools/marvin/marvin/codes.py
@@ -30,12 +30,28 @@
 @DateAdded: 20th October 2013
 """
 
+'''
+VM STATES - START
+'''
 RUNNING = "Running"
 STOPPED = "Stopped"
 STOPPING = "Stopping"
 STARTING = "Starting"
 DESTROYED = "Destroyed"
 EXPUNGING = "Expunging"
+'''
+VM STATES - END
+'''
+
+'''
+Snapshot States - START
+'''
+BACKED_UP = "backedup"
+BACKING_UP = "backingup"
+'''
+Snapshot States - END
+'''
+
 RECURRING = "RECURRING"
 ENABLED = "Enabled"
 NETWORK_OFFERING = "network_offering"
@@ -82,3 +98,11 @@ USER = 0
 XEN_SERVER = "XenServer"
 ADMIN_ACCOUNT = 'ADMIN_ACCOUNT'
 USER_ACCOUNT = 'USER_ACCOUNT'
+RESOURCE_CPU = 8
+RESOURCE_MEMORY = 9
+RESOURCE_PRIMARY_STORAGE = 10
+RESOURCE_SECONDARY_STORAGE = 11
+KVM = "kvm"
+VMWARE = "vmware"
+ROOT_DOMAIN_ADMIN="root domain admin"
+CHILD_DOMAIN_ADMIN="child domain admin"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/12b6cf1b/tools/marvin/marvin/lib/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index 9b011f2..d45b7cc 100644
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -20,11 +20,10 @@
 """
 
 import marvin
-from utils import is_server_ssh_ready, random_gen
 from marvin.cloudstackAPI import *
 from marvin.codes import (FAILED, FAIL, PASS, RUNNING, STOPPED,
                           STARTING, DESTROYED, EXPUNGING,
-                          STOPPING)
+                          STOPPING, BACKED_UP, BACKING_UP)
 from marvin.cloudstackException import GetDetailExceptionInfo
 from marvin.lib.utils import validateList, is_server_ssh_ready, random_gen
 # Import System modules
@@ -957,6 +956,12 @@ class Snapshot:
     """Manage Snapshot Lifecycle
     """
 
+    '''Class level variables'''
+    # Variables denoting possible Snapshot states - start
+    BACKED_UP = BACKED_UP
+    BACKING_UP = BACKING_UP
+    # Variables denoting possible Snapshot states - end
+
     def __init__(self, items):
         self.__dict__.update(items)
 
@@ -990,6 +995,33 @@ class Snapshot:
             cmd.listall=True
         return(apiclient.listSnapshots(cmd))
 
+    def validateState(self, apiclient, snapshotstate, timeout=600):
+        """Check if snapshot is in required state
+           returnValue: List[Result, Reason]
+                 @Result: PASS if snapshot is in required state,
+                          else FAIL
+                 @Reason: Reason for failure in case Result is FAIL
+        """
+        isSnapshotInRequiredState = False
+        try:
+            while timeout >= 0:
+                snapshots = Snapshot.list(apiclient, id=self.id)
+                assert validateList(snapshots)[0] == PASS, "snapshots list\
+                        validation failed"
+                if str(snapshots[0].state).lower() == snapshotstate:
+                    isSnapshotInRequiredState = True
+                    break
+                timeout -= 60
+                time.sleep(60)
+            #end while
+            if isSnapshotInRequiredState:
+                return[PASS, None]
+            else:
+                raise Exception("Snapshot not in required state")
+        except Exception as e:
+            return [FAIL, e]
+
+
 
 class Template:
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/12b6cf1b/tools/marvin/marvin/lib/common.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/lib/common.py b/tools/marvin/marvin/lib/common.py
index 7753385..42ffc51 100644
--- a/tools/marvin/marvin/lib/common.py
+++ b/tools/marvin/marvin/lib/common.py
@@ -60,12 +60,29 @@ from marvin.cloudstackAPI import (listConfigurations,
 
 
 from marvin.sshClient import SshClient
-from marvin.codes import (PASS, ISOLATED_NETWORK, VPC_NETWORK,
-                          BASIC_ZONE, FAIL, NAT_RULE, STATIC_NAT_RULE, FAILED)
+from marvin.codes import (PASS, FAILED, ISOLATED_NETWORK, VPC_NETWORK,
+                          BASIC_ZONE, FAIL, NAT_RULE, STATIC_NAT_RULE,
+                          RESOURCE_PRIMARY_STORAGE, RESOURCE_SECONDARY_STORAGE,
+                          RESOURCE_CPU, RESOURCE_MEMORY)
+from marvin.lib.utils import (validateList, xsplit, get_process_status)
+from marvin.lib.base import (PhysicalNetwork,
+                             PublicIPAddress,
+                             NetworkOffering,
+                             NATRule,
+                             StaticNATRule,
+                             Volume,
+                             Account,
+                             Project,
+                             Snapshot,
+                             NetScaler,
+                             VirtualMachine,
+                             FireWallRule,
+                             Template,
+                             Network,
+                             Host,
+                             Resources,
+                             Configurations)
 import random
-from marvin.lib.utils import *
-from marvin.lib.base import *
-from marvin.codes import PASS
 
 
 # Import System modules
@@ -1222,3 +1239,111 @@ def getPortableIpRangeServices(config):
         services = FAILED
 
     return services
+
+
+def uploadVolume(apiclient, zoneid, account, services):
+    try:
+        # Upload the volume
+        volume = Volume.upload(apiclient, services["volume"],
+                                   zoneid=zoneid, account=account.name,
+                                   domainid=account.domainid, url=services["url"])
+
+        volume.wait_for_upload(apiclient)
+
+        # Check List Volume response for newly created volume
+        volumes = Volume.list(apiclient, id=volume.id,
+                                  zoneid=zoneid, listall=True)
+        validationresult = validateList(volumes)
+        assert validationresult[0] == PASS,\
+                            "volumes list validation failed: %s" % validationresult[2]
+        assert str(volumes[0].state).lower() == "uploaded",\
+                    "Volume state should be 'uploaded' but it is %s" % volumes[0].state
+    except Exception as e:
+        return [FAIL, e]
+    return [PASS, volume]
+
+def matchResourceCount(apiclient, expectedCount, resourceType,
+                              accountid=None, projectid=None):
+    """Match the resource count of account/project with the expected
+    resource count"""
+    try:
+        resourceholderlist = None
+        if accountid:
+            resourceholderlist = Account.list(apiclient, id=accountid)
+        elif projectid:
+            resourceholderlist = Project.list(apiclient, id=projectid, listall=True)
+        validationresult = validateList(resourceholderlist)
+        assert validationresult[0] == PASS,\
+               "accounts list validation failed"
+        if resourceType == RESOURCE_PRIMARY_STORAGE:
+            resourceCount = resourceholderlist[0].primarystoragetotal
+        elif resourceType == RESOURCE_SECONDARY_STORAGE:
+            resourceCount = resourceholderlist[0].secondarystoragetotal
+        elif resourceType == RESOURCE_CPU:
+            resourceCount = resourceholderlist[0].cputotal
+        elif resourceType == RESOURCE_MEMORY:
+            resourceCount = resourceholderlist[0].memorytotal
+        assert str(resourceCount) == str(expectedCount),\
+                "Resource count %s should match with the expected resource count %s" %\
+                (resourceCount, expectedCount)
+    except Exception as e:
+        return [FAIL, e]
+    return [PASS, None]
+
+def createSnapshotFromVirtualMachineVolume(apiclient, account, vmid):
+    """Create snapshot from volume"""
+
+    try:
+        volumes = Volume.list(apiclient, account=account.name,
+                              domainid=account.domainid, virtualmachineid=vmid)
+        validationresult = validateList(volumes)
+        assert validateList(volumes)[0] == PASS,\
+                            "List volumes should return a valid response"
+        snapshot = Snapshot.create(apiclient, volume_id=volumes[0].id,
+                                   account=account.name, domainid=account.domainid)
+        snapshots = Snapshot.list(apiclient, id=snapshot.id,
+                                      listall=True)
+        validationresult = validateList(snapshots)
+        assert validationresult[0] == PASS,\
+               "List snapshot should return a valid list"
+    except Exception as e:
+       return[FAIL, e]
+    return [PASS, snapshot]
+
+def isVmExpunged(apiclient, vmid, projectid=None, timeout=600):
+    """Verify if VM is expunged or not"""
+    vmExpunged= False
+    while timeout>=0:
+        try:
+            vms = VirtualMachine.list(apiclient, id=vmid, projectid=projectid)
+            if vms is None:
+                vmExpunged = True
+                break
+            timeout -= 60
+            time.sleep(60)
+        except Exception:
+           vmExpunged = True
+            break
+     #end while
+    return vmExpunged
+
+def isDomainResourceCountEqualToExpectedCount(apiclient, domainid, expectedcount,
+                                              resourcetype):
+    """Get the resource count of specific domain and match
+    it with the expected count
+    Return list [isExceptionOccured, reasonForException, isResourceCountEqual]"""
+    isResourceCountEqual = False
+    isExceptionOccured = False
+    reasonForException = None
+    try:
+        response = Resources.updateCount(apiclient, domainid=domainid,
+                                         resourcetype=resourcetype)
+    except Exception as e:
+        reasonForException = "Failed while updating resource count: %s" % e
+        isExceptionOccured = True
+        return [isExceptionOccured, reasonForException, isResourceCountEqual]
+
+    resourcecount = (response[0].resourcecount / (1024**3))
+    if resourcecount == expectedcount:
+        isResourceCountEqual = True
+    return [isExceptionOccured, reasonForException, isResourceCountEqual]