| # 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. |
| """ Test cases for Usage Test Path |
| """ |
| from nose.plugins.attrib import attr |
| from marvin.cloudstackTestCase import cloudstackTestCase |
| from marvin.lib.utils import (cleanup_resources, |
| validateList, |
| verifyRouterState, |
| get_process_status) |
| from marvin.lib.base import (Account, |
| ServiceOffering, |
| VirtualMachine, |
| Template, |
| Iso, |
| DiskOffering, |
| Volume, |
| Snapshot, |
| PublicIPAddress, |
| LoadBalancerRule, |
| EgressFireWallRule, |
| Router, |
| VmSnapshot, |
| Usage, |
| Configurations, |
| FireWallRule, |
| NATRule, |
| StaticNATRule, |
| Network, |
| Vpn, |
| VpnUser, |
| VpcOffering, |
| VPC, |
| NetworkACL) |
| from marvin.lib.common import (get_domain, |
| get_zone, |
| get_template, |
| createEnabledNetworkOffering, |
| get_builtin_template_info, |
| findSuitableHostForMigration, |
| list_hosts, |
| list_volumes, |
| list_routers) |
| from marvin.codes import (PASS, FAIL, ERROR_NO_HOST_FOR_MIGRATION) |
| from marvin.sshClient import SshClient |
| import time |
| |
| |
| def CreateEnabledNetworkOffering(apiclient, networkServices): |
| """Create network offering of given services and enable it""" |
| |
| result = createEnabledNetworkOffering(apiclient, networkServices) |
| assert result[0] == PASS,\ |
| "Network offering creation/enabling failed due to %s" % result[2] |
| return result[1] |
| |
| |
| class TestUsage(cloudstackTestCase): |
| |
| @classmethod |
| def setUpClass(cls): |
| testClient = super(TestUsage, cls).getClsTestClient() |
| cls.hypervisor = testClient.getHypervisorInfo() |
| cls.apiclient = testClient.getApiClient() |
| cls.testdata = testClient.getParsedTestDataConfig() |
| cls._cleanup = [] |
| # Get Zone, Domain and templates |
| cls.domain = get_domain(cls.apiclient) |
| cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) |
| |
| cls.mgtSvrDetails = cls.config.__dict__["mgtSvr"][0].__dict__ |
| |
| isUsageJobRunning = cls.IsUsageJobRunning() |
| cls.usageJobNotRunning = False |
| if not isUsageJobRunning: |
| cls.usageJobNotRunning = True |
| return |
| |
| if cls.testdata["configurableData"][ |
| "setUsageConfigurationThroughTestCase"]: |
| cls.setUsageConfiguration() |
| cls.RestartServers() |
| else: |
| currentMgtSvrTime = cls.getCurrentMgtSvrTime() |
| dateTimeSplit = currentMgtSvrTime.split("/") |
| cls.curDate = dateTimeSplit[0] |
| |
| cls.hypervisor = testClient.getHypervisorInfo() |
| |
| cls.template = get_template( |
| cls.apiclient, |
| cls.zone.id, |
| cls.testdata["ostype"]) |
| |
| try: |
| # If local storage is enabled, alter the offerings to use |
| # localstorage |
| if cls.zone.localstorageenable: |
| cls.testdata["service_offering"]["storagetype"] = 'local' |
| |
| # Create 2 service offerings with different values for |
| # for cpunumber, cpuspeed, and memory |
| |
| cls.testdata["service_offering"]["cpunumber"] = "1" |
| cls.testdata["service_offering"]["cpuspeed"] = "128" |
| cls.testdata["service_offering"]["memory"] = "256" |
| |
| cls.service_offering = ServiceOffering.create( |
| cls.apiclient, |
| cls.testdata["service_offering"] |
| ) |
| cls._cleanup.append(cls.service_offering) |
| |
| cls.testdata["service_offering"]["cpunumber"] = "2" |
| cls.testdata["service_offering"]["cpuspeed"] = "256" |
| cls.testdata["service_offering"]["memory"] = "512" |
| |
| cls.service_offering_2 = ServiceOffering.create( |
| cls.apiclient, |
| cls.testdata["service_offering"] |
| ) |
| cls._cleanup.append(cls.service_offering_2) |
| |
| # Create isolated network offering |
| cls.isolated_network_offering = CreateEnabledNetworkOffering( |
| cls.apiclient, |
| cls.testdata["isolated_network_offering"] |
| ) |
| cls._cleanup.append(cls.isolated_network_offering) |
| |
| cls.isolated_network_offering_2 = CreateEnabledNetworkOffering( |
| cls.apiclient, |
| cls.testdata["isolated_network_offering"] |
| ) |
| cls._cleanup.append(cls.isolated_network_offering_2) |
| |
| cls.isolated_network_offering_vpc = CreateEnabledNetworkOffering( |
| cls.apiclient, |
| cls.testdata["nw_offering_isolated_vpc"] |
| ) |
| cls._cleanup.append(cls.isolated_network_offering_vpc) |
| |
| cls.testdata["shared_network_offering_all_services"][ |
| "specifyVlan"] = "True" |
| cls.testdata["shared_network_offering_all_services"][ |
| "specifyIpRanges"] = "True" |
| |
| cls.shared_network_offering = CreateEnabledNetworkOffering( |
| cls.apiclient, |
| cls.testdata["shared_network_offering_all_services"] |
| ) |
| cls._cleanup.append(cls.shared_network_offering) |
| |
| configs = Configurations.list( |
| cls.apiclient, |
| name='usage.stats.job.aggregation.range' |
| ) |
| |
| # Set the value for one more minute than |
| # actual range to be on safer side |
| cls.usageJobAggregationRange = ( |
| int(configs[0].value) + 1) * 60 # in seconds |
| except Exception as e: |
| cls.tearDownClass() |
| raise e |
| return |
| |
| @classmethod |
| def tearDownClass(cls): |
| try: |
| cleanup_resources(cls.apiclient, cls._cleanup) |
| except Exception as e: |
| raise Exception("Warning: Exception during cleanup : %s" % e) |
| |
| def setUp(self): |
| self.apiclient = self.testClient.getApiClient() |
| self.dbclient = self.testClient.getDbConnection() |
| self.cleanup = [] |
| if self.usageJobNotRunning: |
| self.skipTest("Skipping test because usage job not running") |
| # Create an account |
| self.account = Account.create( |
| self.apiclient, |
| self.testdata["account"], |
| domainid=self.domain.id |
| ) |
| self.cleanup.append(self.account) |
| # Create user api client of the account |
| self.userapiclient = self.testClient.getUserApiClient( |
| UserName=self.account.name, |
| DomainName=self.account.domain |
| ) |
| |
| def tearDown(self): |
| try: |
| cleanup_resources(self.apiclient, self.cleanup) |
| except Exception as e: |
| raise Exception("Warning: Exception during cleanup : %s" % e) |
| return |
| |
| @classmethod |
| def setUsageConfiguration(cls): |
| """ Set the configuration parameters so that usage job runs |
| every 10 miuntes """ |
| |
| Configurations.update( |
| cls.apiclient, |
| name="enable.usage.server", |
| value="true" |
| ) |
| |
| Configurations.update( |
| cls.apiclient, |
| name="usage.aggregation.timezone", |
| value="GMT" |
| ) |
| |
| Configurations.update( |
| cls.apiclient, |
| name="usage.execution.timezone", |
| value="GMT" |
| ) |
| |
| Configurations.update( |
| cls.apiclient, |
| name="usage.stats.job.aggregation.range", |
| value="10" |
| ) |
| |
| currentMgtSvrTime = cls.getCurrentMgtSvrTime() |
| dateTimeSplit = currentMgtSvrTime.split("/") |
| cls.curDate = dateTimeSplit[0] |
| timeSplit = dateTimeSplit[1].split(":") |
| minutes = int(timeSplit[1]) |
| minutes += 5 |
| usageJobExecTime = timeSplit[0] + ":" + str(minutes) |
| |
| Configurations.update( |
| cls.apiclient, |
| name="usage.stats.job.exec.time", |
| value=usageJobExecTime |
| ) |
| |
| return |
| |
| @classmethod |
| def getCurrentMgtSvrTime(cls, format='%Y-%m-%d/%H:%M'): |
| """ Get the current time from Management Server """ |
| |
| sshClient = SshClient( |
| cls.mgtSvrDetails["mgtSvrIp"], |
| 22, |
| cls.mgtSvrDetails["user"], |
| cls.mgtSvrDetails["passwd"] |
| ) |
| command = "date +%s" % format |
| return sshClient.execute(command)[0] |
| |
| @classmethod |
| def RestartServers(cls): |
| """ Restart management server and usage server """ |
| |
| sshClient = SshClient( |
| cls.mgtSvrDetails["mgtSvrIp"], |
| 22, |
| cls.mgtSvrDetails["user"], |
| cls.mgtSvrDetails["passwd"] |
| ) |
| command = "service cloudstack-management restart" |
| sshClient.execute(command) |
| |
| command = "service cloudstack-usage restart" |
| sshClient.execute(command) |
| return |
| |
| @classmethod |
| def IsUsageJobRunning(cls): |
| """ Check that usage job is running on Management server or not""" |
| |
| sshClient = SshClient( |
| cls.mgtSvrDetails["mgtSvrIp"], |
| 22, |
| cls.mgtSvrDetails["user"], |
| cls.mgtSvrDetails["passwd"] |
| ) |
| |
| command = "service cloudstack-usage status" |
| response = str(sshClient.execute(command)).lower() |
| if "running" not in response: |
| return False |
| return True |
| |
| def getLatestUsageJobExecutionTime(self): |
| """ Get the end time of latest usage job that has run successfully""" |
| |
| try: |
| qresultset = self.dbclient.execute( |
| "SELECT max(end_date) FROM usage_job WHERE success=1;", |
| db="cloud_usage") |
| |
| self.assertNotEqual( |
| len(qresultset), |
| 0, |
| "Check DB Query result set" |
| ) |
| |
| lastUsageJobExecutionTime = qresultset[0][0] |
| self.debug( |
| "last usage job exec time: %s" % |
| lastUsageJobExecutionTime) |
| return [PASS, lastUsageJobExecutionTime] |
| except Exception as e: |
| return [FAIL, e] |
| |
| def getEventCreatedDateTime(self, resourceName): |
| """ Get the created date/time of particular entity |
| from cloud_usage.usage_event table """ |
| |
| try: |
| # Checking exact entity creation time |
| qresultset = self.dbclient.execute( |
| "select created from usage_event where resource_name = '%s';" % |
| str(resourceName), db="cloud_usage") |
| self.assertNotEqual( |
| len(qresultset), |
| 0, |
| "Check DB Query result set" |
| ) |
| eventCreatedDateTime = qresultset[0][0] |
| except Exception as e: |
| return [FAIL, e] |
| return [PASS, eventCreatedDateTime] |
| |
| def listUsageRecords(self, usagetype, apiclient=None, startdate=None, |
| enddate=None, account=None, sleep=True): |
| """List and return the usage record for given account |
| and given usage type""" |
| |
| if sleep: |
| # Sleep till usage job has run at least once after the operation |
| self.debug( |
| "Sleeping for %s seconds" % |
| self.usageJobAggregationRange) |
| time.sleep(self.usageJobAggregationRange) |
| |
| if not startdate: |
| startdate = self.curDate |
| if not enddate: |
| enddate = self.curDate |
| if not account: |
| account = self.account |
| if not apiclient: |
| self.apiclient |
| |
| Usage.generateRecords( |
| self.apiclient, |
| startdate=startdate, |
| enddate=enddate) |
| |
| try: |
| usageRecords = Usage.listRecords( |
| self.apiclient, |
| startdate=startdate, |
| enddate=enddate, |
| account=account.name, |
| domainid=account.domainid, |
| type=usagetype) |
| |
| self.assertEqual( |
| validateList(usageRecords)[0], |
| PASS, |
| "usage records list validation failed") |
| |
| return [PASS, usageRecords] |
| except Exception as e: |
| return [FAIL, e] |
| return |
| |
| def getCommandResultFromRouter(self, router, command): |
| """Run given command on router and return the result""" |
| |
| if (self.hypervisor.lower() == 'vmware' |
| or self.hypervisor.lower() == 'hyperv'): |
| result = get_process_status( |
| self.apiclient.connection.mgtSvr, |
| 22, |
| self.apiclient.connection.user, |
| self.apiclient.connection.passwd, |
| router.linklocalip, |
| command, |
| hypervisor=self.hypervisor |
| ) |
| else: |
| hosts = list_hosts( |
| self.apiclient, |
| id=router.hostid, |
| ) |
| self.assertEqual( |
| isinstance(hosts, list), |
| True, |
| "Check for list hosts response return valid data" |
| ) |
| host = hosts[0] |
| host.user = self.testdata["configurableData"]["host"]["username"] |
| host.passwd = self.testdata["configurableData"]["host"]["password"] |
| |
| result = get_process_status( |
| host.ipaddress, |
| 22, |
| host.user, |
| host.passwd, |
| router.linklocalip, |
| command |
| ) |
| return result |
| |
| @attr(tags=["advanced"], required_hardware="True") |
| def test_01_positive_tests_usage(self): |
| """ Positive test for usage test path |
| |
| # 1. Register a template and verify that usage usage is generated |
| for correct size of template |
| # 2. Register an ISO, verify usage is generate for the correct size |
| of ISO |
| # 3. Deploy a VM from the template and verify usage is generated |
| for the VM with correct Service Offering and template id |
| # 4. Delete template and iso |
| # 5. Stop and start the VM |
| # 6. Verify that allocated VM usage should be greater than |
| running VM usage |
| # 7. Destroy the Vm and recover it |
| # 8. Verify that the running VM usage stays the same after delete and |
| and after recover operation |
| # 9. Verify that allocated VM usage should be greater after recover |
| operation than after destroy operation |
| # 10. Change service offering of the VM |
| # 11. Verify that VM usage is generated for the VM with correct |
| service offering |
| # 12. Start the VM |
| # 13. Verify that the running VM usage after start operation is less |
| than the allocated VM usage |
| # 14. Verify that the running VM usage after start vm opearation |
| is greater running VM usage after recover VM operation |
| """ |
| |
| # Step 1 |
| # Register a private template in the account |
| builtin_info = get_builtin_template_info( |
| self.apiclient, |
| self.zone.id |
| ) |
| |
| self.testdata["privatetemplate"]["url"] = builtin_info[0] |
| self.testdata["privatetemplate"]["hypervisor"] = builtin_info[1] |
| self.testdata["privatetemplate"]["format"] = builtin_info[2] |
| |
| # Register new template |
| template = Template.register( |
| self.userapiclient, |
| self.testdata["privatetemplate"], |
| zoneid=self.zone.id, |
| account=self.account.name, |
| domainid=self.account.domainid |
| ) |
| self.cleanup.append(template) |
| template.download(self.userapiclient) |
| |
| templates = Template.list( |
| self.userapiclient, |
| listall=True, |
| id=template.id, |
| templatefilter="self") |
| |
| self.assertEqual( |
| validateList(templates)[0], |
| PASS, |
| "Templates list validation failed") |
| |
| # Checking template usage |
| response = self.listUsageRecords(usagetype=7) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateUsageRecords = [record for record in response[1] |
| if template.id == record.usageid] |
| |
| self.assertEqual(templateUsageRecords[0].virtualsize, |
| templates[0].size, |
| "The template size in the usage record and \ |
| does not match with the created template size") |
| |
| # Getting last usage job execution time |
| response = self.getLatestUsageJobExecutionTime() |
| self.assertEqual(response[0], PASS, response[1]) |
| lastUsageJobExecTime = response[1] |
| |
| # Checking exact template creation time |
| response = self.getEventCreatedDateTime(template.name) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateCreatedDateTime = response[1] |
| self.debug("Template creation date: %s" % templateCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - templateCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| |
| actualUsage = format(sum(float(record.rawusage) |
| for record in templateUsageRecords), ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| # step 2 |
| iso = Iso.create( |
| self.userapiclient, |
| self.testdata["iso"], |
| account=self.account.name, |
| domainid=self.account.domainid, |
| zoneid=self.zone.id |
| ) |
| self.cleanup.append(iso) |
| |
| iso.download(self.apiclient) |
| |
| isos = Iso.list( |
| self.userapiclient, |
| id=iso.id, |
| listall=True) |
| |
| self.assertEqual( |
| validateList(isos)[0], |
| PASS, |
| "Iso list validation failed" |
| ) |
| |
| # Checking usage for Iso |
| response = self.listUsageRecords(usagetype=8) |
| self.assertEqual(response[0], PASS, response[1]) |
| isoUsageRecords = [record for record in response[1] |
| if iso.id == record.usageid] |
| |
| self.assertEqual(isoUsageRecords[0].size, |
| isos[0].size, |
| "The iso size in the usage record and \ |
| does not match with the created iso size") |
| |
| # Getting last usage job execution time |
| response = self.getLatestUsageJobExecutionTime() |
| self.assertEqual(response[0], PASS, response[1]) |
| lastUsageJobExecTime = response[1] |
| |
| # Checking exact Iso creation time |
| response = self.getEventCreatedDateTime(iso.name) |
| self.assertEqual(response[0], PASS, response[1]) |
| isoCreatedDateTime = response[1] |
| self.debug("Iso creation date: %s" % isoCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - isoCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| |
| actualUsage = format(sum(float(record.rawusage) |
| for record in isoUsageRecords), ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| # step 3 |
| # Create VM in account |
| vm = VirtualMachine.create( |
| self.userapiclient, |
| self.testdata["small"], |
| templateid=template.id, |
| accountid=self.account.name, |
| domainid=self.account.domainid, |
| serviceofferingid=self.service_offering.id, |
| zoneid=self.zone.id |
| ) |
| |
| # Checking running VM usage |
| response = self.listUsageRecords(usagetype=1) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmRunningUsageRecords = [record for record in response[1] |
| if record.virtualmachineid == vm.id] |
| |
| vmRunningRawUsage = sum(float(record.rawusage) |
| for record in vmRunningUsageRecords) |
| |
| self.assertEqual(vmRunningUsageRecords[0].offeringid, |
| self.service_offering.id, |
| "The service offering id in the usage record\ |
| does not match with id of service offering\ |
| with which the VM was created") |
| |
| self.assertEqual(vmRunningUsageRecords[0].templateid, |
| template.id, |
| "The template id in the usage record\ |
| does not match with id of template\ |
| with which the VM was created") |
| |
| response = self.listUsageRecords(usagetype=2, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmAllocatedUsageRecords = [record for record in response[1] |
| if record.virtualmachineid == vm.id] |
| |
| vmAllocatedRawUsage = sum(float(record.rawusage) |
| for record in vmAllocatedUsageRecords) |
| |
| self.debug("running vm usage: %s" % vmRunningRawUsage) |
| self.debug("allocated vm usage: %s" % vmAllocatedRawUsage) |
| |
| self.assertTrue( |
| vmRunningRawUsage < vmAllocatedRawUsage, |
| "Allocated VM usage should be greater than Running VM usage") |
| |
| # Getting last usage job execution time |
| response = self.getLatestUsageJobExecutionTime() |
| self.assertEqual(response[0], PASS, response[1]) |
| lastUsageJobExecTime = response[1] |
| |
| # Checking exact VM creation time |
| response = self.getEventCreatedDateTime(vm.name) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmCreatedDateTime = response[1] |
| self.debug("Vm creation date: %s" % vmCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - vmCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| self.debug("VM expected usage: %s" % expectedUsage) |
| |
| actualUsage = format(vmAllocatedRawUsage, ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| # Step 4 - Deleting template and ISO |
| template.delete(self.userapiclient) |
| self.cleanup.remove(template) |
| |
| iso.delete(self.userapiclient) |
| self.cleanup.remove(iso) |
| |
| # Verifying that usage for template and ISO is stopped |
| response = self.listUsageRecords(usagetype=7) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateUsageRecords = response[1] |
| |
| usageForTemplateAfterDeletion_1 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in templateUsageRecords |
| if template.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=8, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| isoUsageRecords = response[1] |
| |
| usageForIsoAfterDeletion_1 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in isoUsageRecords |
| if iso.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=7) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateUsageRecords = response[1] |
| |
| usageForTemplateAfterDeletion_2 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in templateUsageRecords |
| if template.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=8, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| isoUsageRecords = response[1] |
| |
| usageForIsoAfterDeletion_2 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in isoUsageRecords |
| if iso.id == record.usageid]) |
| |
| self.assertTrue(usageForTemplateAfterDeletion_1 == |
| usageForTemplateAfterDeletion_2, |
| "usage for template after deletion should remain the same\ |
| after specific intervals of time") |
| |
| self.assertTrue(usageForIsoAfterDeletion_1 == |
| usageForIsoAfterDeletion_2, |
| "usage for iso after deletion should remain the same\ |
| after specific intervals of time") |
| |
| # Step 5 |
| vm.stop(self.userapiclient) |
| |
| # Sleep to get difference between allocated and running usage |
| time.sleep(120) |
| |
| vm.start(self.userapiclient) |
| |
| # Step 6: Verifying allocated usage is greater than running usage |
| response = self.listUsageRecords(usagetype=1) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmRunningUsageRecords = [record for record in response[1] |
| if record.virtualmachineid == vm.id] |
| |
| vmRunningRawUsage = sum(float(record.rawusage) |
| for record in vmRunningUsageRecords) |
| |
| response = self.listUsageRecords(usagetype=2, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmAllocatedUsageRecords = [record for record in response[1] |
| if record.virtualmachineid == vm.id] |
| |
| vmAllocatedRawUsage = sum(float(record.rawusage) |
| for record in vmAllocatedUsageRecords) |
| |
| self.debug("running vm usage: %s" % vmRunningRawUsage) |
| self.debug("allocated vm usage: %s" % vmAllocatedRawUsage) |
| |
| self.assertTrue( |
| vmRunningRawUsage < vmAllocatedRawUsage, |
| "Allocated VM usage should be greater than Running VM usage") |
| |
| # Step 7 |
| vm.delete(self.userapiclient, expunge=False) |
| |
| response = self.listUsageRecords(usagetype=1, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmRunningUsageRecordAfterDestroy = sum( |
| float( |
| record.rawusage) for record in response[1] if |
| record.virtualmachineid == vm.id) |
| |
| response = self.listUsageRecords(usagetype=2, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmAllocatedUsageRecordAfterDestroy = sum( |
| float( |
| record.rawusage) for record in response[1] if record.virtualmachineid == vm.id) |
| |
| vm.recover(self.apiclient) |
| |
| # Step 8 |
| response = self.listUsageRecords(usagetype=1) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmRunningUsageRecordAfterRecover = sum( |
| float( |
| record.rawusage) for record in response[1] if |
| record.virtualmachineid == vm.id) |
| |
| response = self.listUsageRecords(usagetype=2, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmAllocatedUsageRecordAfterRecover = sum( |
| float( |
| record.rawusage) for record in response[1] if |
| record.virtualmachineid == vm.id) |
| |
| self.debug( |
| "running vm usage T1: %s" % |
| vmRunningUsageRecordAfterDestroy) |
| self.debug( |
| "allocated vm usage T1: %s" % |
| vmRunningUsageRecordAfterRecover) |
| |
| self.assertEqual( |
| format(vmRunningUsageRecordAfterDestroy, ".1f"), |
| format(vmRunningUsageRecordAfterRecover, ".1f"), |
| "Running usage should remain the same") |
| |
| self.debug( |
| "allocated vm usage T2: %s" % |
| vmAllocatedUsageRecordAfterDestroy) |
| self.debug( |
| "allocated vm usage T2: %s" % |
| vmAllocatedUsageRecordAfterRecover) |
| |
| # Step 9 |
| self.assertTrue( |
| vmAllocatedUsageRecordAfterDestroy < |
| vmAllocatedUsageRecordAfterRecover, |
| "Allocated VM usage after recover should be greater than\ |
| before") |
| |
| # Step 10 |
| # Change service offering of VM and verify that it is changed |
| vm.change_service_offering( |
| self.userapiclient, |
| serviceOfferingId=self.service_offering_2.id |
| ) |
| |
| response = self.listUsageRecords(usagetype=2) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmAllocatedUsageRecord = response[1][-1] |
| |
| # Step 11: Veriying vm usage for new service offering |
| self.assertEqual(vmAllocatedUsageRecord.offeringid, |
| self.service_offering_2.id, |
| "The service offering id in the usage record\ |
| does not match with id of new service offering") |
| |
| # Step 12 |
| vm.start(self.userapiclient) |
| |
| response = self.listUsageRecords(usagetype=1) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmRunningUsageRecordAfterStart = sum( |
| float( |
| record.rawusage) for record in response[1] if |
| record.virtualmachineid == vm.id) |
| |
| response = self.listUsageRecords(usagetype=2, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmAllocatedUsageRecordAfterStart = sum( |
| float( |
| record.rawusage) for record in response[1] if |
| record.virtualmachineid == vm.id) |
| |
| self.debug("running vm usage T3: %s" % vmRunningUsageRecordAfterStart) |
| self.debug( |
| "allocated vm usage T3: %s" % |
| vmAllocatedUsageRecordAfterStart) |
| |
| # Step 13 |
| self.assertTrue( |
| vmRunningUsageRecordAfterStart < |
| vmAllocatedUsageRecordAfterStart, |
| "Allocated VM usage should be greater than Running usage") |
| |
| # Step 14 |
| self.assertTrue( |
| vmRunningUsageRecordAfterRecover < |
| vmRunningUsageRecordAfterStart, |
| "Running VM usage after start VM should be greater than\ |
| that after recover operation") |
| return |
| |
| @attr(tags=["advanced"], required_hardware="true") |
| def test_02_positive_tests_usage(self): |
| """ Positive test for usage test path |
| |
| # 1. Scale up VM and check that usage is generated for |
| new cpu and ram value (Check in usage_vm_instance table) |
| # 2. Scale down VM and check that usage is generated for |
| new cpu and ram value (Check in usage_vm_instance table) |
| # 3. Attach disk to VM and check that volume usage is |
| generated for correct disk offering |
| # 4. Detach volume from and verify that usage for volue remains |
| the same there afterwards |
| # 5. Create snapshot of the root disk and verify correct usage is |
| generated for snapshot with correct size |
| # 6. Create template from root disk and check correct usage is |
| generated for template with correct size |
| # 7. Delete the template and verify that usage is stopped for |
| template |
| # 8. Create volume from snaopshot and verify correct disk usage |
| is generated |
| # 9. Delete the volume and verify that the usage is stopped |
| # 10. Create template from snapshot and verify correct usage |
| is generated for the template with correct size |
| """ |
| |
| # Step 1 |
| # Create dynamic and static service offering |
| self.testdata["service_offering"]["cpunumber"] = "" |
| self.testdata["service_offering"]["cpuspeed"] = "" |
| self.testdata["service_offering"]["memory"] = "" |
| |
| serviceOffering_dynamic = ServiceOffering.create( |
| self.apiclient, |
| self.testdata["service_offering"] |
| ) |
| self.cleanup.append(serviceOffering_dynamic) |
| |
| customcpunumber = 1 |
| customcpuspeed = 256 |
| custommemory = 128 |
| |
| # Deploy VM with dynamic service offering |
| virtualMachine = VirtualMachine.create( |
| self.userapiclient, |
| self.testdata["virtual_machine"], |
| serviceofferingid=serviceOffering_dynamic.id, |
| templateid=self.template.id, |
| zoneid=self.zone.id, |
| accountid=self.account.name, |
| domainid=self.account.domainid, |
| customcpunumber=customcpunumber, |
| customcpuspeed=customcpuspeed, |
| custommemory=custommemory |
| ) |
| |
| # Stop VM and verify that it is in stopped state |
| virtualMachine.stop(self.userapiclient) |
| |
| scaledcpunumber = 2 |
| scaledcpuspeed = 512 |
| scaledmemory = 256 |
| |
| # Scale up VM |
| virtualMachine.scale( |
| self.userapiclient, |
| serviceOfferingId=serviceOffering_dynamic.id, |
| customcpunumber=scaledcpunumber, |
| customcpuspeed=scaledcpuspeed, |
| custommemory=scaledmemory |
| ) |
| |
| self.listUsageRecords(usagetype=1) |
| |
| qresultset = self.dbclient.execute( |
| "select cpu_cores, memory, cpu_speed from usage_vm_instance where vm_name = '%s';" % |
| str(virtualMachine.name), db="cloud_usage") |
| self.assertNotEqual( |
| len(qresultset), |
| 0, |
| "Check DB Query result set" |
| ) |
| dbcpucores = qresultset[-1][0] |
| dbmemory = qresultset[-1][1] |
| dbcpuspeed = qresultset[-1][2] |
| |
| self.assertEqual(int(dbcpucores), scaledcpunumber, |
| "scaled cpu number not matching with db record") |
| |
| self.assertEqual(int(dbmemory), scaledmemory, |
| "scaled memory not matching with db record") |
| |
| self.assertEqual(int(dbcpuspeed), scaledcpuspeed, |
| "scaled cpu speed not matching with db record") |
| |
| scaledcpunumber = 1 |
| scaledcpuspeed = 512 |
| scaledmemory = 256 |
| |
| # Step 2 |
| # Scale down VM |
| virtualMachine.scale( |
| self.userapiclient, |
| serviceOfferingId=serviceOffering_dynamic.id, |
| customcpunumber=scaledcpunumber, |
| customcpuspeed=scaledcpuspeed, |
| custommemory=scaledmemory |
| ) |
| |
| self.listUsageRecords(usagetype=1) |
| |
| qresultset = self.dbclient.execute( |
| "select cpu_cores, memory, cpu_speed from usage_vm_instance where vm_name = '%s';" % |
| str(virtualMachine.name), db="cloud_usage") |
| self.assertNotEqual( |
| len(qresultset), |
| 0, |
| "Check DB Query result set" |
| ) |
| dbcpucores = qresultset[-1][0] |
| dbmemory = qresultset[-1][1] |
| dbcpuspeed = qresultset[-1][2] |
| |
| self.assertEqual(int(dbcpucores), scaledcpunumber, |
| "scaled cpu number not matching with db record") |
| |
| self.assertEqual(int(dbmemory), scaledmemory, |
| "scaled memory not matching with db record") |
| |
| self.assertEqual(int(dbcpuspeed), scaledcpuspeed, |
| "scaled cpu speed not matching with db record") |
| |
| disk_offering = DiskOffering.create( |
| self.apiclient, |
| self.testdata["disk_offering"] |
| ) |
| self.cleanup.append(disk_offering) |
| |
| # Step 3 |
| volume = Volume.create( |
| self.userapiclient, self.testdata["volume"], |
| zoneid=self.zone.id, account=self.account.name, |
| domainid=self.account.domainid, diskofferingid=disk_offering.id |
| ) |
| |
| # Create VM in account |
| virtual_machine = VirtualMachine.create( |
| self.userapiclient, |
| self.testdata["small"], |
| templateid=self.template.id, |
| accountid=self.account.name, |
| domainid=self.account.domainid, |
| serviceofferingid=self.service_offering.id, |
| zoneid=self.zone.id |
| ) |
| |
| virtual_machine.attach_volume(self.userapiclient, volume=volume) |
| |
| # Verifying usage for Volume - START |
| response = self.listUsageRecords(usagetype=6) |
| self.assertEqual(response[0], PASS, response[1]) |
| volumeUsageRecords = [record for record in response[1] |
| if volume.id == record.usageid] |
| |
| self.assertTrue( |
| len(volumeUsageRecords) >= 1, |
| "Volume usage record for attached volume is not generated") |
| |
| volumeRawUsageBeforeDetach = sum(float(record.rawusage) for |
| record in [ |
| record for record in volumeUsageRecords |
| if volume.id == record.usageid]) |
| |
| # Getting last usage job execution time |
| response = self.getLatestUsageJobExecutionTime() |
| self.assertEqual(response[0], PASS, response[1]) |
| lastUsageJobExecTime = response[1] |
| |
| # Checking exact Volume creation time |
| response = self.getEventCreatedDateTime(volume.name) |
| self.assertEqual(response[0], PASS, response[1]) |
| volumeCreatedDateTime = response[1] |
| self.debug("Volume creation date: %s" % volumeCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - volumeCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| self.debug("Volume expected usage: %s" % expectedUsage) |
| |
| actualUsage = format(volumeRawUsageBeforeDetach, ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| # Verifying usage for Volume - END |
| |
| # Step 4 |
| virtual_machine.detach_volume(self.userapiclient, volume=volume) |
| |
| # Verifying usage for Volume after detaching - START |
| response = self.listUsageRecords(usagetype=6) |
| self.assertEqual(response[0], PASS, response[1]) |
| volumeUsageRecords = response[1] |
| |
| volumeRawUsageAfterDetach_time_1 = sum(float(record.rawusage) for |
| record in [ |
| record for record in volumeUsageRecords |
| if volume.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=6) |
| self.assertEqual(response[0], PASS, response[1]) |
| volumeUsageRecords = response[1] |
| |
| volumeRawUsageAfterDetach_time_2 = sum(float(record.rawusage) for |
| record in [ |
| record for record in volumeUsageRecords |
| if volume.id == record.usageid]) |
| |
| self.debug(volumeRawUsageAfterDetach_time_1) |
| self.debug(volumeRawUsageAfterDetach_time_2) |
| |
| self.assertTrue( |
| volumeRawUsageAfterDetach_time_1 < |
| volumeRawUsageAfterDetach_time_2, |
| "Raw volume usage should continue running after detach operation" |
| ) |
| |
| # Verifying usage for Volume after detaching - END |
| |
| volumes = Volume.list( |
| self.userapiclient, |
| virtualmachineid=virtual_machine.id, |
| type='ROOT', |
| listall=True |
| ) |
| self.assertEqual( |
| validateList(volumes)[0], |
| PASS, |
| "Volumes list validation failed" |
| ) |
| |
| rootVolume = volumes[0] |
| |
| # Step 5 |
| # Create a snapshot from the ROOTDISK |
| snapshotFromRootVolume = Snapshot.create( |
| self.userapiclient, |
| rootVolume.id) |
| |
| # Verifying usage for Snapshot - START |
| response = self.listUsageRecords(usagetype=9) |
| self.assertEqual(response[0], PASS, response[1]) |
| snapshotUsageRecords = [record for record in response[1] |
| if snapshotFromRootVolume.id == record.usageid] |
| |
| self.assertEqual(snapshotUsageRecords[0].size, |
| snapshotFromRootVolume.physicalsize, |
| "The snapshot size in the usage record and \ |
| does not match with the created snapshot size") |
| |
| # Getting last usage job execution time |
| response = self.getLatestUsageJobExecutionTime() |
| self.assertEqual(response[0], PASS, response[1]) |
| lastUsageJobExecTime = response[1] |
| |
| # Checking exact snapshot creation time |
| response = self.getEventCreatedDateTime(snapshotFromRootVolume.name) |
| self.assertEqual(response[0], PASS, response[1]) |
| snapshotCreatedDateTime = response[1] |
| self.debug("Snapshot creation date: %s" % snapshotCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - snapshotCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| |
| actualUsage = format(sum(float(record.rawusage) |
| for record in snapshotUsageRecords), ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| # Verifying usage for Snapshot - END |
| |
| virtual_machine.stop(self.userapiclient) |
| |
| # Step 6 |
| templateFromVolume = Template.create( |
| self.userapiclient, |
| self.testdata["templates"], |
| rootVolume.id, |
| self.account.name, |
| self.account.domainid |
| ) |
| |
| templates = Template.list( |
| self.userapiclient, |
| listall=True, |
| id=templateFromVolume.id, |
| templatefilter="self" |
| ) |
| |
| self.assertEqual( |
| validateList(templates)[0], |
| PASS, |
| "templates list validation failed" |
| ) |
| |
| # Verifying usage for Template - START |
| response = self.listUsageRecords(usagetype=7) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateUsageRecords = [record for record in response[1] |
| if templateFromVolume.id == record.usageid] |
| |
| self.assertEqual(templateUsageRecords[0].virtualsize, |
| templates[-1].size, |
| "The template size in the usage record and \ |
| does not match with the created template size") |
| |
| templateRawUsage = sum(float(record.rawusage) |
| for record in templateUsageRecords) |
| |
| # Getting last usage job execution time |
| response = self.getLatestUsageJobExecutionTime() |
| self.assertEqual(response[0], PASS, response[1]) |
| lastUsageJobExecTime = response[1] |
| |
| # Checking exact Template creation time |
| response = self.getEventCreatedDateTime(templateFromVolume.name) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateCreatedDateTime = response[1] |
| self.debug("Template creation date: %s" % templateCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - templateCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| self.debug("Template expected usage: %s" % expectedUsage) |
| |
| actualUsage = format(templateRawUsage, ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| # Verifying usage for Template - END |
| |
| # Step 7 |
| templateFromVolume.delete(self.userapiclient) |
| |
| # Verifying usage for Template is stoppd after deleting it - START |
| response = self.listUsageRecords(usagetype=7) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateUsageRecords = response[1] |
| |
| usageForTemplateFromVolumeAfterDeletion_1 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in templateUsageRecords |
| if templateFromVolume.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=7) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateUsageRecords = response[1] |
| |
| usageForTemplateFromVolumeAfterDeletion_2 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in templateUsageRecords |
| if templateFromVolume.id == record.usageid]) |
| |
| self.assertTrue(usageForTemplateFromVolumeAfterDeletion_1 == |
| usageForTemplateFromVolumeAfterDeletion_2, |
| "usage for template after deletion should remain the same\ |
| after specific intervals of time") |
| |
| # Verifying usage for Template is stoppd after deleting it - END |
| |
| # Step 8 |
| self.testdata["volume_from_snapshot"]["zoneid"] = self.zone.id |
| |
| volumeFromSnapshot = Volume.create_from_snapshot( |
| self.userapiclient, |
| snapshot_id=snapshotFromRootVolume.id, |
| services=self.testdata["volume_from_snapshot"], |
| account=self.account.name, |
| domainid=self.account.domainid |
| ) |
| |
| # Verifying usage for Volume from Snapshot - START |
| response = self.listUsageRecords(usagetype=6) |
| self.assertEqual(response[0], PASS, response[1]) |
| volumeUsageRecords = response[1] |
| |
| usageForVolumeFromSnapshotBeforeDeletion = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in volumeUsageRecords |
| if volumeFromSnapshot.id == record.usageid]) |
| |
| self.debug(usageForVolumeFromSnapshotBeforeDeletion) |
| |
| # Getting last usage job execution time |
| response = self.getLatestUsageJobExecutionTime() |
| self.assertEqual(response[0], PASS, response[1]) |
| lastUsageJobExecTime = response[1] |
| |
| # Checking exact Volume creation time |
| response = self.getEventCreatedDateTime(volumeFromSnapshot.name) |
| self.assertEqual(response[0], PASS, response[1]) |
| volumeCreatedDateTime = response[1] |
| self.debug("Volume creation date: %s" % volumeCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - volumeCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| self.debug("Volume expected usage: %s" % expectedUsage) |
| |
| actualUsage = format(usageForVolumeFromSnapshotBeforeDeletion, ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| # Verifying usage for Volume from Snapshot - END |
| |
| # Step 9 |
| volumeFromSnapshot.delete(self.userapiclient) |
| |
| # Verifying usage for Volume from Snapshot is stopped after delete - |
| # START |
| response = self.listUsageRecords(usagetype=6) |
| self.assertEqual(response[0], PASS, response[1]) |
| volumeUsageRecords = response[1] |
| |
| usageForVolumeFromSnapshotAfterDeletion_1 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in volumeUsageRecords |
| if volumeFromSnapshot.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=6) |
| self.assertEqual(response[0], PASS, response[1]) |
| volumeUsageRecords = response[1] |
| |
| usageForVolumeFromSnapshotAfterDeletion_2 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in volumeUsageRecords |
| if volumeFromSnapshot.id == record.usageid]) |
| |
| self.debug(usageForVolumeFromSnapshotAfterDeletion_1) |
| self.debug(usageForVolumeFromSnapshotAfterDeletion_2) |
| |
| self.assertTrue(usageForVolumeFromSnapshotAfterDeletion_1 == |
| usageForVolumeFromSnapshotAfterDeletion_2, |
| "usage for volume after deletion should remain the same\ |
| after specific intervals of time") |
| |
| # Verifying usage for Volume from Snapshot is stopped after delete - |
| # END |
| |
| # Step 10 |
| templateFromSnapshot = Template.create_from_snapshot( |
| self.userapiclient, |
| snapshotFromRootVolume, |
| self.testdata["privatetemplate"] |
| ) |
| |
| templates = Template.list( |
| self.userapiclient, |
| listall=True, |
| id=templateFromSnapshot.id, |
| templatefilter="self" |
| ) |
| |
| self.assertEqual( |
| validateList(templates)[0], |
| PASS, |
| "templates list validation failed" |
| ) |
| |
| # Verifying usage for Template from Snapshot - START |
| response = self.listUsageRecords(usagetype=7) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| templateUsageRecords = [record for record in usageRecords |
| if templateFromSnapshot.id == record.usageid] |
| |
| self.assertTrue(len(templateUsageRecords) >= 1, |
| "template usage record list is empty") |
| |
| self.assertEqual(templateUsageRecords[-1].virtualsize, |
| templates[0].size, |
| "The template size in the usage record and \ |
| does not match with the created template size") |
| |
| templateRawUsage = sum(float(record.rawusage) |
| for record in templateUsageRecords) |
| |
| # Getting last usage job execution time |
| response = self.getLatestUsageJobExecutionTime() |
| self.assertEqual(response[0], PASS, response[1]) |
| lastUsageJobExecTime = response[1] |
| |
| # Checking exact Template creation time |
| response = self.getEventCreatedDateTime(templateFromSnapshot.name) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateCreatedDateTime = response[1] |
| self.debug("Template creation date: %s" % templateCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - templateCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| self.debug("Template expected usage: %s" % expectedUsage) |
| |
| actualUsage = format(templateRawUsage, ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| # Verifying usage for Template from Snapshot - END |
| |
| templateFromSnapshot.delete(self.userapiclient) |
| |
| # Verifying usage for Template from Snapshot is stopped after delete - |
| # START |
| response = self.listUsageRecords(usagetype=7) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateUsageRecords = response[1] |
| |
| usageForTemplateAfterDeletion_1 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in templateUsageRecords |
| if templateFromSnapshot.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=7) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateUsageRecords = response[1] |
| |
| usageForTemplateAfterDeletion_2 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in templateUsageRecords |
| if templateFromSnapshot.id == record.usageid]) |
| |
| self.assertTrue(usageForTemplateAfterDeletion_1 == |
| usageForTemplateAfterDeletion_2, |
| "usage for volume after deletion should remain the same\ |
| after specific intervals of time") |
| |
| # Verifying usage for Template from Snapshot is stopped after delete - |
| # END |
| |
| snapshotFromRootVolume.delete(self.userapiclient) |
| |
| # Verifying usage for Snapshot from volume is stopped after delete - |
| # START |
| response = self.listUsageRecords(usagetype=9) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateUsageRecords = response[1] |
| |
| usageForSnapshotAfterDeletion_1 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in templateUsageRecords |
| if snapshotFromRootVolume.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=9) |
| self.assertEqual(response[0], PASS, response[1]) |
| templateUsageRecords = response[1] |
| |
| usageForSnapshotAfterDeletion_2 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in templateUsageRecords |
| if snapshotFromRootVolume.id == record.usageid]) |
| |
| self.assertTrue(usageForSnapshotAfterDeletion_1 == |
| usageForSnapshotAfterDeletion_2, |
| "usage for volume after deletion should remain the same\ |
| after specific intervals of time") |
| |
| # Verifying usage for Snapshot from volume is stopped after delete - |
| # END |
| return |
| |
| @attr(tags=["advanced"], required_hardware="true") |
| def test_03_positive_tests_usage(self): |
| """ Positive test for usage test path T28 - T35 |
| |
| Steps: |
| # 1. Add an isolated network to VM and verify that network offering |
| usage is generated for account |
| Also verify that IP usage is generated for source NAT IP of |
| network |
| # 2. Enabled VPN on source nat IP of default network of VM |
| # 3. Add two VPN users and check that usage is generated for VPN users |
| # 4. Acquire public IP in the network and verify that IP usage |
| is generated for the acquired IP |
| # 5. Create two PF rules on this IP and verify that PF rules usage |
| is generated for the account |
| # 6. Acquire another IP and enabled static NAT on it and create |
| egress firewall rule on it |
| # 7. Verify IP usage is generated for above acquired IP |
| # 8. SSH to VM with above IP and ping to google.com |
| # 9. Verify that Network bytes usage is generated for account |
| and it matches with the actual number of bytes |
| # 10. Repeat the same for other acquired IP |
| # 11. Delete one of the PF rules and verify that usage is stopped for the PF rule |
| # 12. Also verify that usage is not stopped for other PF rule which |
| # is still present |
| """ |
| |
| # Step 1 |
| # Create VM in account |
| virtual_machine = VirtualMachine.create( |
| self.userapiclient, |
| self.testdata["small"], |
| templateid=self.template.id, |
| accountid=self.account.name, |
| domainid=self.account.domainid, |
| serviceofferingid=self.service_offering.id, |
| zoneid=self.zone.id |
| ) |
| |
| self.testdata["isolated_network"]["zoneid"] = self.zone.id |
| isolated_network = Network.create( |
| self.userapiclient, |
| self.testdata["isolated_network"], |
| self.account.name, |
| self.account.domainid, |
| networkofferingid=self.isolated_network_offering_2.id) |
| |
| virtual_machine.add_nic(self.userapiclient, isolated_network.id) |
| |
| # Usages for steps are checked together in batch after the operations are done |
| # to avoid waiting for usage job to run for each operation separately |
| |
| # Listing source nat ip of newly added network |
| ipAddresses = PublicIPAddress.list( |
| self.apiclient, |
| associatednetworkid=isolated_network.id, |
| listall=True) |
| |
| sourceNatIP = ipAddresses[0] |
| |
| ipAddressesDefaultNetwork = PublicIPAddress.list( |
| self.apiclient, |
| associatednetworkid=virtual_machine.nic[0].networkid, |
| listall=True) |
| |
| sourceNatIPDefaultNetwork = ipAddressesDefaultNetwork[0] |
| |
| # Step 2 |
| # Create VPN for source NAT ip |
| Vpn.create(self.apiclient, |
| sourceNatIPDefaultNetwork.id, |
| account=self.account.name, |
| domainid=self.account.domainid) |
| |
| self.debug("Verifying the remote VPN access") |
| vpns = Vpn.list(self.apiclient, |
| publicipid=sourceNatIPDefaultNetwork.id, |
| listall=True) |
| self.assertEqual( |
| isinstance(vpns, list), |
| True, |
| "List VPNs shall return a valid response" |
| ) |
| |
| # Step 3: |
| vpnuser_1 = VpnUser.create( |
| self.apiclient, |
| self.testdata["vpn_user"]["username"], |
| self.testdata["vpn_user"]["password"], |
| account=self.account.name, |
| domainid=self.account.domainid, |
| rand_name=True |
| ) |
| |
| vpnuser_2 = VpnUser.create( |
| self.apiclient, |
| self.testdata["vpn_user"]["username"], |
| self.testdata["vpn_user"]["password"], |
| account=self.account.name, |
| domainid=self.account.domainid, |
| rand_name=True |
| ) |
| |
| # Step 4 |
| public_ip_1 = PublicIPAddress.create( |
| self.userapiclient, |
| accountid=virtual_machine.account, |
| zoneid=virtual_machine.zoneid, |
| domainid=virtual_machine.domainid, |
| services=self.testdata["server"], |
| networkid=virtual_machine.nic[0].networkid |
| ) |
| |
| FireWallRule.create( |
| self.userapiclient, |
| ipaddressid=public_ip_1.ipaddress.id, |
| protocol=self.testdata["fwrule"]["protocol"], |
| cidrlist=[self.testdata["fwrule"]["cidr"]], |
| startport=self.testdata["fwrule"]["startport"], |
| endport=self.testdata["fwrule"]["endport"] |
| ) |
| |
| # Step 5 |
| self.testdata["natrule"]["startport"] = 22 |
| self.testdata["natrule"]["endport"] = 22 |
| |
| nat_rule_1 = NATRule.create( |
| self.userapiclient, |
| virtual_machine, |
| self.testdata["natrule"], |
| public_ip_1.ipaddress.id |
| ) |
| |
| self.testdata["natrule"]["privateport"] = 23 |
| self.testdata["natrule"]["publicport"] = 23 |
| |
| nat_rule_2 = NATRule.create( |
| self.userapiclient, |
| virtual_machine, |
| self.testdata["natrule"], |
| public_ip_1.ipaddress.id |
| ) |
| |
| # Usages for above operations are checked here together |
| |
| # Checking usage for source nat IP of added network |
| response = self.listUsageRecords(usagetype=13) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| nwOfferingUsageRecords = [ |
| record for record in usageRecords if self.isolated_network_offering_2.id == record.offeringid] |
| |
| self.assertTrue(validateList(nwOfferingUsageRecords)[0] == PASS, |
| "IP usage record list validation failed") |
| |
| self.assertTrue(float(nwOfferingUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for source NAT ip") |
| |
| # Checking usage for source nat IP of default VM network |
| response = self.listUsageRecords(usagetype=3, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| ipUsageRecords = [record for record in usageRecords |
| if sourceNatIP.id == record.usageid] |
| |
| self.assertTrue(validateList(ipUsageRecords)[0] == PASS, |
| "IP usage record list validation failed") |
| |
| self.assertTrue(float(ipUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for source NAT ip") |
| |
| # Checking usage for acquired public IP |
| response = self.listUsageRecords(usagetype=3, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| ipUsageRecords = [record for record |
| in usageRecords |
| if public_ip_1.ipaddress.id == record.usageid |
| ] |
| |
| self.assertTrue(validateList(ipUsageRecords)[0] == PASS, |
| "IP usage record list validation failed") |
| |
| self.assertTrue(float(ipUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for acquired public ip") |
| |
| # Checking usage for NAT rules |
| response = self.listUsageRecords(usagetype=12, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| natRuleUsageRecords = [record for record in usageRecords |
| if nat_rule_1.id == record.usageid] |
| |
| self.assertTrue(validateList(natRuleUsageRecords)[0] == PASS, |
| "NAT rule usage record list validation failed") |
| |
| self.assertTrue(float(natRuleUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for nat rule") |
| |
| natRuleUsageRecords = [record for record in usageRecords |
| if nat_rule_2.id == record.usageid] |
| |
| self.assertTrue(validateList(natRuleUsageRecords)[0] == PASS, |
| "NAT rule usage record list validation failed") |
| |
| self.assertTrue(float(natRuleUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for nat rule") |
| |
| # Checking VPN usage |
| response = self.listUsageRecords(usagetype=14, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| vpnUserUsageRecords_1 = [record for record in usageRecords |
| if vpnuser_1.id == record.usageid] |
| |
| self.assertTrue(validateList(vpnUserUsageRecords_1)[0] == PASS, |
| "VPN user usage record list validation failed") |
| |
| vpnuser1_rawusage = sum(float(record.rawusage) |
| for record in vpnUserUsageRecords_1) |
| |
| # Getting last usage job execution time |
| response = self.getLatestUsageJobExecutionTime() |
| self.assertEqual(response[0], PASS, response[1]) |
| lastUsageJobExecTime = response[1] |
| |
| # Checking exact VPN user creation time |
| response = self.getEventCreatedDateTime(vpnuser_1.username) |
| self.assertEqual(response[0], PASS, response[1]) |
| vpnUserCreatedDateTime = response[1] |
| self.debug("VPN creation date: %s" % vpnUserCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - vpnUserCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| self.debug("VPN user expected usage: %s" % expectedUsage) |
| |
| actualUsage = format(vpnuser1_rawusage, ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| vpnUserUsageRecords_2 = [record for record in usageRecords |
| if vpnuser_2.id == record.usageid] |
| |
| self.assertTrue(validateList(vpnUserUsageRecords_2)[0] == PASS, |
| "VPN user usage record list validation failed") |
| |
| vpnuser2_rawusage = sum(float(record.rawusage) |
| for record in vpnUserUsageRecords_2) |
| |
| # Checking exact VPN user creation time |
| response = self.getEventCreatedDateTime(vpnuser_2.username) |
| self.assertEqual(response[0], PASS, response[1]) |
| vpnUserCreatedDateTime = response[1] |
| self.debug("VPN creation date: %s" % vpnUserCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - vpnUserCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| self.debug("VPN user expected usage: %s" % expectedUsage) |
| |
| actualUsage = format(vpnuser2_rawusage, ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| # Acquire another public IP and check usage |
| public_ip_2 = PublicIPAddress.create( |
| self.userapiclient, |
| accountid=virtual_machine.account, |
| zoneid=virtual_machine.zoneid, |
| domainid=virtual_machine.domainid, |
| services=self.testdata["server"], |
| networkid=virtual_machine.nic[0].networkid |
| ) |
| |
| # Step 6 |
| # Enabling static Nat for Ip Address associated |
| StaticNATRule.enable( |
| self.userapiclient, |
| ipaddressid=public_ip_2.ipaddress.id, |
| virtualmachineid=virtual_machine.id, |
| ) |
| |
| # Step 7 |
| response = self.listUsageRecords(usagetype=3) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| ipUsageRecords = [record for record |
| in usageRecords |
| if public_ip_2.ipaddress.id == record.usageid |
| ] |
| |
| self.assertTrue(validateList(ipUsageRecords)[0] == PASS, |
| "IP usage record list validation failed") |
| |
| self.assertTrue(float(ipUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for public ip") |
| |
| FireWallRule.create( |
| self.userapiclient, |
| ipaddressid=public_ip_2.ipaddress.id, |
| protocol=self.testdata["fwrule"]["protocol"], |
| cidrlist=[self.testdata["fwrule"]["cidr"]], |
| startport=self.testdata["fwrule"]["startport"], |
| endport=self.testdata["fwrule"]["endport"] |
| ) |
| |
| EgressFireWallRule.create( |
| self.userapiclient, |
| networkid=virtual_machine.nic[0].networkid, |
| protocol=self.testdata["icmprule"]["protocol"], |
| type=self.testdata["icmprule"]["icmptype"], |
| code=self.testdata["icmprule"]["icmpcode"], |
| cidrlist=self.testdata["icmprule"]["cidrlist"]) |
| |
| # Step 8: |
| ssh_client = virtual_machine.get_ssh_client( |
| ipaddress=public_ip_1.ipaddress.ipaddress |
| ) |
| |
| # Ping Internet and check the bytes received |
| res = ssh_client.execute("ping -c 1 www.google.com") |
| self.assertEqual( |
| str(res).count("1 received"), |
| 1, |
| "Ping to outside world from VM should be successful" |
| ) |
| |
| routers = list_routers( |
| self.apiclient, |
| networkid=virtual_machine.nic[0].networkid, |
| listall=True |
| ) |
| self.assertEqual( |
| validateList(routers)[0], |
| PASS, |
| "Routers list validation failed") |
| router = routers[0] |
| |
| result = self.getCommandResultFromRouter( |
| router, |
| "iptables -L NETWORK_STATS -n -v -x") |
| |
| self.debug("iptables -L NETWORK_STATS -n -v -x: %s" % result) |
| |
| bytesReceivedIptableRows = [record for record in result if |
| "eth2 eth0" in record] |
| self.debug("bytes received rows: %s" % bytesReceivedIptableRows) |
| bytesReceivedOnRouter = sum( |
| int(record[1]) for record in [x.split() for x in bytesReceivedIptableRows]) |
| |
| self.debug( |
| "Bytes received extracted from router: %s" % |
| bytesReceivedOnRouter) |
| |
| # Step 9: |
| # Verify that bytes received in usage are equal to |
| # as shown on router |
| response = self.listUsageRecords(usagetype=5) |
| self.assertEqual(response[0], PASS, response[1]) |
| bytesReceivedUsage = sum( |
| int(record.rawusage) for record in response[1]) |
| |
| self.assertTrue(bytesReceivedUsage == |
| bytesReceivedOnRouter, |
| "Total bytes received usage should be \ |
| equal to bytes received on router") |
| |
| # Step 10: |
| # Repeat the same for other public IP |
| ssh_client = virtual_machine.get_ssh_client( |
| ipaddress=public_ip_2.ipaddress.ipaddress |
| ) |
| |
| res = ssh_client.execute("ping -c 1 www.google.com") |
| self.assertEqual( |
| str(res).count("1 received"), |
| 1, |
| "Ping to outside world from VM should be successful" |
| ) |
| result = self.getCommandResultFromRouter( |
| router, |
| "iptables -L NETWORK_STATS -n -v -x") |
| |
| self.debug("iptables -L NETWORK_STATS -n -v -x: %s" % result) |
| |
| bytesReceivedIptableRows = [record for record in result if |
| "eth2 eth0" in record] |
| self.debug("bytes received rows: %s" % bytesReceivedIptableRows) |
| bytesReceivedOnRouter = sum( |
| int(record[1]) for record in [x.split() for x in bytesReceivedIptableRows]) |
| |
| self.debug( |
| "Bytes received extracted from router: %s" % |
| bytesReceivedOnRouter) |
| |
| # Step 9: |
| # Verify that bytes received in usage are equal to |
| # as shown on router |
| response = self.listUsageRecords(usagetype=5) |
| self.assertEqual(response[0], PASS, response[1]) |
| bytesReceivedUsage = sum( |
| int(record.rawusage) for record in response[1]) |
| |
| self.assertTrue(bytesReceivedUsage == |
| bytesReceivedOnRouter, |
| "Total bytes received usage should be \ |
| equal to bytes received on router") |
| |
| # Step 11: |
| # Delete NAT rule and verify that usage is stopped for the NAT rule |
| nat_rule_1.delete(self.userapiclient) |
| |
| response = self.listUsageRecords(usagetype=12, sleep=True) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| natRule_1_Usage_t1 = sum(float(record.rawusage) for record |
| in [record for record in usageRecords |
| if nat_rule_1.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=12) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| natRule_1_Usage_t2 = sum(float(record.rawusage) for record |
| in [record for record in usageRecords |
| if nat_rule_1.id == record.usageid]) |
| |
| self.assertTrue( |
| natRule_1_Usage_t1 == natRule_1_Usage_t2, |
| "NAT rule usage should be stopped once the rule is deleted") |
| |
| # Also verify that usage for other nat rule is running |
| natRule_2_Usage_t1 = sum(float(record.rawusage) for record |
| in [record for record in usageRecords |
| if nat_rule_2.id == record.usageid]) |
| |
| # Step 12: |
| response = self.listUsageRecords(usagetype=12) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| natRule_2_Usage_t2 = sum(float(record.rawusage) for record |
| in [record for record in usageRecords |
| if nat_rule_1.id == record.usageid]) |
| |
| self.assertTrue(natRule_2_Usage_t1 > natRule_2_Usage_t2, |
| "NAT rule usage for second rule should be running") |
| return |
| |
| @attr(tags=["advanced"], required_hardware="true") |
| def test_04_positive_tests_usage(self): |
| """ Positive test for usage test path |
| Steps: |
| # 1. Create a VM in the account |
| # 2. Acquire public IP in VM network and verify correct usage |
| is generated for IP |
| # 3. Create LB rule for the IP address and verify LB rule usage |
| is generated for the account |
| # 4. Create another LB rule with different ports and verify |
| separate usage is generated for new LB rule |
| |
| # 5. Create egress firewall rule for VM and SSH to VM |
| # 6. Ping external network from the VM and verify that |
| network byte usage is generated correctly |
| # 7. Delete one LB rule and verify that the usage |
| is stopped for the LB rule |
| # 8. Stop the network router and |
| # Verify iptables counters are reset when domR stops |
| # Verify current_bytes in user_statistics table are moved to |
| net_bytes |
| # Verify currnt_bytes becomes zero |
| # 9. Start the router and |
| # Verify iptables counters are reset when domR starts |
| # Verify a diff of total (current_bytes + net_bytes) in previous |
| aggregation period and current period will give the network usage |
| |
| """ |
| |
| # Step 1 |
| # Create VM in account |
| virtual_machine = VirtualMachine.create( |
| self.userapiclient, |
| self.testdata["small"], |
| templateid=self.template.id, |
| accountid=self.account.name, |
| domainid=self.account.domainid, |
| serviceofferingid=self.service_offering.id, |
| zoneid=self.zone.id |
| ) |
| |
| # Step 2 |
| public_ip_1 = PublicIPAddress.create( |
| self.userapiclient, |
| accountid=virtual_machine.account, |
| zoneid=virtual_machine.zoneid, |
| domainid=virtual_machine.domainid, |
| services=self.testdata["server"] |
| ) |
| |
| self.testdata["lbrule"]["privateport"] = 22 |
| self.testdata["lbrule"]["publicport"] = 2222 |
| publicport = self.testdata["lbrule"]["publicport"] |
| |
| # Step 3 |
| # Create LB Rule |
| lbrule_1 = LoadBalancerRule.create( |
| self.apiclient, |
| self.testdata["lbrule"], |
| ipaddressid=public_ip_1.ipaddress.id, |
| accountid=self.account.name, |
| networkid=virtual_machine.nic[0].networkid, |
| domainid=self.account.domainid) |
| |
| self.testdata["lbrule"]["privateport"] = 23 |
| self.testdata["lbrule"]["publicport"] = 2223 |
| |
| # Step 4 |
| # Create another LB Rule |
| lbrule_2 = LoadBalancerRule.create( |
| self.apiclient, |
| self.testdata["lbrule"], |
| ipaddressid=public_ip_1.ipaddress.id, |
| accountid=self.account.name, |
| networkid=virtual_machine.nic[0].networkid, |
| domainid=self.account.domainid) |
| |
| response = self.listUsageRecords(usagetype=3) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| ipUsageRecords = [record for record in usageRecords |
| if public_ip_1.ipaddress.id == record.usageid |
| ] |
| |
| self.assertTrue(validateList(ipUsageRecords)[0] == PASS, |
| "IP usage record list validation failed") |
| |
| self.assertTrue(float(ipUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for ip address") |
| |
| response = self.listUsageRecords(usagetype=11, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| lbRule_1_UsageRecords = [record for record in usageRecords |
| if lbrule_1.id == record.usageid] |
| |
| self.assertTrue(validateList(lbRule_1_UsageRecords)[0] == PASS, |
| "LB rule usage record list validation failed") |
| |
| self.assertTrue(float(lbRule_1_UsageRecords[0].rawusage) > 0, |
| "LB usage not started for nat rule") |
| |
| lbRule_2_UsageRecords = [record for record in usageRecords |
| if lbrule_2.id == record.usageid] |
| |
| self.assertTrue(validateList(lbRule_2_UsageRecords)[0] == PASS, |
| "LB rule usage record list validation failed") |
| |
| self.assertTrue(float(lbRule_2_UsageRecords[0].rawusage) > 0, |
| "LB usage not started for nat rule") |
| |
| # Step 5 |
| EgressFireWallRule.create( |
| self.userapiclient, |
| networkid=virtual_machine.nic[0].networkid, |
| protocol=self.testdata["icmprule"]["protocol"], |
| type=self.testdata["icmprule"]["icmptype"], |
| code=self.testdata["icmprule"]["icmpcode"], |
| cidrlist=self.testdata["icmprule"]["cidrlist"]) |
| |
| lbrule_1.assign(self.userapiclient, [virtual_machine]) |
| |
| ssh_client = virtual_machine.get_ssh_client( |
| ipaddress=public_ip_1.ipaddress.ipaddress, |
| port=publicport |
| ) |
| |
| # Step 6 |
| res = ssh_client.execute("ping -c 1 www.google.com") |
| self.assertEqual( |
| str(res).count("1 received"), |
| 1, |
| "Ping to outside world from VM should be successful" |
| ) |
| |
| # Verifying usage for bytes received - START |
| routers = list_routers( |
| self.apiclient, |
| networkid=virtual_machine.nic[0].networkid, |
| listall=True |
| ) |
| self.assertEqual( |
| validateList(routers)[0], |
| PASS, |
| "Routers list validation failed") |
| router = routers[0] |
| result = self.getCommandResultFromRouter( |
| router, |
| "iptables -L NETWORK_STATS -n -v -x") |
| |
| self.debug("iptables -L NETWORK_STATS -n -v -x: %s" % result) |
| |
| bytesReceivedIptableRows = [record for record in result if |
| "eth2 eth0" in record] |
| self.debug("bytes received rows: %s" % bytesReceivedIptableRows) |
| bytesReceivedOnRouter = sum( |
| int(record[1]) for record in [x.split() for x in bytesReceivedIptableRows]) |
| |
| self.debug( |
| "Bytes received extracted from router: %s" % |
| bytesReceivedOnRouter) |
| |
| # Verify that bytes received in usage are equal to |
| # as shown on router |
| response = self.listUsageRecords(usagetype=5) |
| self.assertEqual(response[0], PASS, response[1]) |
| bytesReceivedUsage = sum( |
| int(record.rawusage) for record in response[1]) |
| |
| self.assertTrue(bytesReceivedUsage == |
| bytesReceivedOnRouter, |
| "Total bytes received usage should be \ |
| equal to bytes received on router") |
| |
| # Verifying usage for bytes received - END |
| |
| lbrule_1.delete(self.userapiclient) |
| # Step 7 Verify that usage is stopped for the LB rule |
| |
| response = self.listUsageRecords(usagetype=11) |
| self.assertEqual(response[0], PASS, response[1]) |
| lbUsageRecords = response[1] |
| |
| usageForLbRuleAfterDeletion_t1 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in lbUsageRecords |
| if lbrule_1.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=11) |
| self.assertEqual(response[0], PASS, response[1]) |
| lbUsageRecords = response[1] |
| |
| usageForLbRuleAfterDeletion_t2 = sum( |
| float( |
| record.rawusage) for record in [ |
| record for record in lbUsageRecords |
| if lbrule_1.id == record.usageid]) |
| |
| self.assertTrue(usageForLbRuleAfterDeletion_t1 == |
| usageForLbRuleAfterDeletion_t2, |
| "usage for LB rule after deletion should remain the same\ |
| after specific intervals of time") |
| |
| qresultset = self.dbclient.execute( |
| "select id from account where account_name = '%s';" |
| % self.account.name |
| ) |
| accountid = qresultset[0][0] |
| self.debug("accountid: %s" % accountid) |
| |
| qresultset = self.dbclient.execute( |
| "select current_bytes_sent, current_bytes_received from user_statistics where account_id = '%s';" % |
| accountid, |
| db="cloud_usage")[0] |
| |
| currentBytesSentBeforeRouterStop = qresultset[0] |
| currentBytesReceivedBeforeRouterStop = qresultset[1] |
| |
| self.debug(currentBytesSentBeforeRouterStop) |
| self.debug(currentBytesReceivedBeforeRouterStop) |
| |
| # Step 8 |
| routers = Router.list( |
| self.apiclient, |
| account=self.account.name, |
| domainid=self.account.domainid, |
| ) |
| |
| self.assertEqual( |
| validateList(routers)[0], |
| PASS, |
| "Check for list routers response return valid data" |
| ) |
| router = routers[0] |
| |
| # Stop the router |
| Router.stop( |
| self.apiclient, |
| id=router.id |
| ) |
| |
| response = verifyRouterState( |
| self.apiclient, |
| router.id, |
| "stopped") |
| self.assertEqual(response[0], PASS, response[1]) |
| |
| qresultset = self.dbclient.execute( |
| "select current_bytes_sent, current_bytes_received, net_bytes_sent, net_bytes_received from user_statistics where account_id = '%s';" % |
| accountid, |
| db="cloud_usage")[0] |
| |
| currentBytesSentAfterRouterStop = int(qresultset[0]) |
| currentBytesReceivedAfterRouterStop = int(qresultset[1]) |
| netBytesSentAfterRouterStop = int(qresultset[0]) |
| netBytesReceivedAfterRouterStop = int(qresultset[1]) |
| |
| self.debug(currentBytesSentAfterRouterStop) |
| self.debug(currentBytesReceivedAfterRouterStop) |
| self.debug(netBytesSentAfterRouterStop) |
| self.debug(netBytesReceivedAfterRouterStop) |
| |
| self.assertTrue( |
| (currentBytesSentAfterRouterStop + |
| currentBytesReceivedAfterRouterStop) == 0, |
| "Current bytes should be 0") |
| |
| self.assertTrue( |
| (currentBytesSentBeforeRouterStop + |
| currentBytesReceivedBeforeRouterStop) == ( |
| netBytesSentAfterRouterStop + |
| netBytesReceivedAfterRouterStop), |
| "current bytes should be moved to net bytes") |
| |
| # TODO: Verify iptables counters are reset when domR starts |
| |
| # Step 9 |
| # Start the router |
| Router.start( |
| self.apiclient, |
| id=router.id |
| ) |
| |
| response = verifyRouterState( |
| self.apiclient, |
| router.id, |
| "running") |
| self.assertEqual(response[0], PASS, response[1]) |
| |
| # TODO: Verify iptables counters are reset when domR starts |
| # Verify a diff of total (current_bytes + net_bytes) in previous |
| # aggregation period and current period will give the network usage |
| return |
| |
| @attr(tags=["advanced"], required_hardware="true") |
| def test_05_positive_tests_usage(self): |
| """ Positive test for usage test path T61 - T62 |
| Steps: |
| # 1. Deploy a VM |
| # 2. Take Vm snapshot and verify usage is generated for VM snapshot |
| # 3. Delete VM snapshot and verify that usage stops |
| """ |
| |
| time.sleep(180) |
| |
| if self.hypervisor.lower() in ['kvm', 'hyperv']: |
| self.skipTest("This feature is not supported on %s" % |
| self.hypervisor) |
| |
| # Step 1 |
| # Create VM in account |
| virtual_machine = VirtualMachine.create( |
| self.userapiclient, |
| self.testdata["small"], |
| templateid=self.template.id, |
| accountid=self.account.name, |
| domainid=self.account.domainid, |
| serviceofferingid=self.service_offering.id, |
| zoneid=self.zone.id |
| ) |
| |
| # Step 2 |
| vmsnapshot = VmSnapshot.create( |
| self.userapiclient, |
| virtual_machine.id) |
| |
| response = self.listUsageRecords(usagetype=25) |
| self.assertEqual(response[0], PASS, response[1]) |
| |
| # Step 3 |
| VmSnapshot.deleteVMSnapshot( |
| self.userapiclient, |
| vmsnapshot.id |
| ) |
| |
| response = self.listUsageRecords(usagetype=25) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmSnapshotUsageRecords_t1 = response[1] |
| |
| vmSnapshotUsage_t1 = sum(float(record.rawusage) |
| for record in vmSnapshotUsageRecords_t1) |
| |
| response = self.listUsageRecords(usagetype=25) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmSnapshotUsageRecords_t2 = response[1] |
| |
| vmSnapshotUsage_t2 = sum(float(record.rawusage) |
| for record in vmSnapshotUsageRecords_t2) |
| |
| self.debug(vmSnapshotUsage_t1) |
| self.debug(vmSnapshotUsage_t2) |
| |
| self.assertEqual( |
| vmSnapshotUsage_t1, |
| vmSnapshotUsage_t2, |
| "VmSnapshot usage should remain the same\ |
| once snapshot is deleted") |
| return |
| |
| @attr(tags=["advanced"], required_hardware="true") |
| def test_06_positive_tests_usage(self): |
| """Migrate VM and verify usage""" |
| |
| # Validate the following |
| # 1. Create a VM, and verify that usage is generated for it |
| # with correct service offering and template id |
| # 2. Migrate the VM to suitable host |
| # 3. Verify that after migration, VM usage continues to be running |
| |
| if self.hypervisor.lower() in ['lxc']: |
| self.skipTest( |
| "vm migrate feature is not supported on %s" % |
| self.hypervisor.lower()) |
| |
| # Step 1: |
| self.vm = VirtualMachine.create( |
| self.userapiclient, |
| self.testdata["small"], |
| templateid=self.template.id, |
| accountid=self.account.name, |
| domainid=self.account.domainid, |
| serviceofferingid=self.service_offering.id, |
| zoneid=self.zone.id |
| ) |
| |
| response = self.listUsageRecords(usagetype=1) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmUsageRecord = response[1][0] |
| |
| self.assertEqual(vmUsageRecord.offeringid, |
| self.service_offering.id, |
| "The service offering id in the usage record\ |
| does not match with id of service offering\ |
| with which the VM was created") |
| |
| self.assertEqual(vmUsageRecord.templateid, |
| self.template.id, |
| "The template id in the usage record\ |
| does not match with id of template\ |
| with which the VM was created") |
| |
| # Step 2: |
| host = findSuitableHostForMigration(self.apiclient, self.vm.id) |
| if host is None: |
| self.skipTest(ERROR_NO_HOST_FOR_MIGRATION) |
| |
| try: |
| self.vm.migrate(self.apiclient, host.id) |
| except Exception as e: |
| self.fail("Failed to migrate instance: %s" % e) |
| |
| # Step 3: |
| response = self.listUsageRecords(usagetype=1) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmUsageRecords_t1 = response[1] |
| |
| vmUsage_t1 = sum(float(record.rawusage) |
| for record in vmUsageRecords_t1) |
| |
| response = self.listUsageRecords(usagetype=1) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmUsageRecords_t2 = response[1] |
| |
| vmUsage_t2 = sum(float(record.rawusage) |
| for record in vmUsageRecords_t2) |
| |
| self.debug(vmUsage_t1) |
| self.debug(vmUsage_t2) |
| |
| self.assertTrue( |
| vmUsage_t1 < |
| vmUsage_t2, |
| "Vm usage should be running after\ |
| vm is migrated") |
| |
| @attr(tags=["advanced"], required_hardware="true") |
| def test_07_positive_tests_usage(self): |
| """ |
| Steps: |
| # 1. Add VM in VPC network, verify that |
| # usage is generated for source nat ip pf network in vpc |
| # 2. Acquire a public ip in VPC network and verify |
| usage is generated for the public ip |
| # 3. Create multiple PF rule on this ip in VPC network, |
| and verify that usage is generated for both pf rules |
| # 4. Enable vpn on source nat ip in vpc network |
| # 5. Add 2 vpn user |
| And verify that usage is generated for both the vpn users |
| # 6. Delete one VPn user, and verify that usage is stopped |
| for deleted user |
| # 7. Open Egress rules on this VPC network |
| # 8. Create network traffic on this network ping www.google.com, |
| and verify that usage is generated for network traffic |
| # 9. Delete onePF rule in VPC network |
| And verify that usage is stopped for the pf rule |
| # 10. Stop router for VPC network |
| Verify iptables counters are reset when domR stops |
| # Verify current_bytes in user_statistics table are moved to |
| net_bytes |
| # Verify currnt_bytes becomes zero |
| # 11. Start router for VPC network |
| Verify iptables counters are reset when domR starts |
| # Verify a diff of total (current_bytes + net_bytes) in previous |
| aggregation period and current period will give the network usage |
| """ |
| |
| # Step 1 |
| # Create VM in account |
| vpc_off = VpcOffering.create( |
| self.apiclient, |
| self.testdata["vpc_offering"] |
| ) |
| |
| vpc_off.update(self.apiclient, state='Enabled') |
| |
| self.testdata["vpc"]["cidr"] = '10.1.1.0/24' |
| vpc = VPC.create( |
| self.userapiclient, |
| self.testdata["vpc"], |
| vpcofferingid=vpc_off.id, |
| zoneid=self.zone.id, |
| account=self.account.name, |
| domainid=self.account.domainid |
| ) |
| |
| self.testdata["isolated_network"]["zoneid"] = self.zone.id |
| isolated_network = Network.create( |
| self.userapiclient, |
| self.testdata["isolated_network"], |
| self.account.name, |
| self.account.domainid, |
| vpcid=vpc.id, |
| networkofferingid=self.isolated_network_offering_vpc.id, |
| gateway="10.1.1.1", |
| netmask="255.255.255.0") |
| |
| # Create VM in account |
| virtual_machine = VirtualMachine.create( |
| self.userapiclient, |
| self.testdata["small"], |
| templateid=self.template.id, |
| accountid=self.account.name, |
| domainid=self.account.domainid, |
| serviceofferingid=self.service_offering.id, |
| zoneid=self.zone.id, |
| networkids=[isolated_network.id] |
| ) |
| |
| # Checking usage for newly added network in VPC |
| response = self.listUsageRecords(usagetype=13) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| nwOfferingUsageRecords = [ |
| record for record in usageRecords if self.isolated_network_offering_vpc.id == record.offeringid] |
| |
| self.assertTrue(validateList(nwOfferingUsageRecords)[0] == PASS, |
| "Network Offering usage record list validation failed") |
| |
| self.assertTrue(float(nwOfferingUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for isolated network offering") |
| |
| # Step 2 (Verification of usage is done together for |
| # multiple steps) |
| # Acquiring public IP |
| public_ip = PublicIPAddress.create(self.userapiclient, |
| accountid=self.account.name, |
| zoneid=self.zone.id, |
| domainid=self.account.domainid, |
| networkid=isolated_network.id, |
| vpcid=vpc.id |
| ) |
| |
| # Step 3 |
| # Create NAT rule |
| nat_rule_1 = NATRule.create(self.userapiclient, |
| virtual_machine, |
| self.testdata["natrule"], |
| ipaddressid=public_ip.ipaddress.id, |
| openfirewall=False, |
| networkid=isolated_network.id, |
| vpcid=vpc.id |
| ) |
| |
| self.debug("Adding NetworkACL rules to make NAT rule accessible") |
| NetworkACL.create(self.userapiclient, |
| networkid=isolated_network.id, |
| services=self.testdata["natrule"], |
| traffictype='Ingress' |
| ) |
| |
| # Step 7: |
| NetworkACL.create(self.userapiclient, |
| networkid=isolated_network.id, |
| services=self.testdata["natrule"], |
| traffictype='Egress' |
| ) |
| |
| self.testdata["natrule"]["privateport"] = 23 |
| self.testdata["natrule"]["publicport"] = 23 |
| |
| nat_rule_2 = NATRule.create(self.userapiclient, |
| virtual_machine, |
| self.testdata["natrule"], |
| ipaddressid=public_ip.ipaddress.id, |
| openfirewall=False, |
| networkid=isolated_network.id, |
| vpcid=vpc.id |
| ) |
| |
| ipAddresses = PublicIPAddress.list( |
| self.userapiclient, |
| vpcid=vpc.id, |
| issourcenat=True, |
| listall=True, |
| forvirtualnetwork=True) |
| |
| sourceNatIP = ipAddresses[0] |
| |
| # Usage verification section |
| # Checking source nat IP usage |
| response = self.listUsageRecords(usagetype=3) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| ipUsageRecords = [record for record in usageRecords |
| if sourceNatIP.id == record.usageid] |
| |
| self.assertTrue(validateList(ipUsageRecords)[0] == PASS, |
| "IP usage record list validation failed") |
| |
| self.assertTrue(float(ipUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for source NAT ip") |
| |
| # Checking public IP usage |
| ipUsageRecords = [record for record in usageRecords |
| if public_ip.ipaddress.id == record.usageid] |
| |
| self.assertTrue(validateList(ipUsageRecords)[0] == PASS, |
| "IP usage record list validation failed") |
| |
| self.assertTrue(float(ipUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for source NAT ip") |
| |
| # Verifying NAT rule usage |
| response = self.listUsageRecords(usagetype=12, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| natRuleUsageRecords = [record for record in usageRecords |
| if nat_rule_1.id == record.usageid] |
| |
| self.assertTrue(validateList(natRuleUsageRecords)[0] == PASS, |
| "NAT rule usage record list validation failed") |
| |
| self.assertTrue(float(natRuleUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for nat rule") |
| |
| natRuleUsageRecords = [record for record in usageRecords |
| if nat_rule_2.id == record.usageid] |
| |
| self.assertTrue(validateList(natRuleUsageRecords)[0] == PASS, |
| "NAT rule usage record list validation failed") |
| |
| self.assertTrue(float(natRuleUsageRecords[0].rawusage) > 0, |
| "Raw usage not started for nat rule") |
| |
| # Step 4: |
| # Create VPN for source NAT ip |
| Vpn.create(self.apiclient, |
| sourceNatIP.id, |
| account=self.account.name, |
| domainid=self.account.domainid) |
| |
| self.debug("Verifying the remote VPN access") |
| vpns = Vpn.list(self.apiclient, |
| publicipid=sourceNatIP.id, |
| listall=True) |
| self.assertEqual( |
| isinstance(vpns, list), |
| True, |
| "List VPNs shall return a valid response" |
| ) |
| |
| # Step 5: |
| vpnuser_1 = VpnUser.create( |
| self.apiclient, |
| self.testdata["vpn_user"]["username"], |
| self.testdata["vpn_user"]["password"], |
| account=self.account.name, |
| domainid=self.account.domainid, |
| rand_name=True |
| ) |
| |
| vpnuser_2 = VpnUser.create( |
| self.apiclient, |
| self.testdata["vpn_user"]["username"], |
| self.testdata["vpn_user"]["password"], |
| account=self.account.name, |
| domainid=self.account.domainid, |
| rand_name=True |
| ) |
| |
| # Checking VPN usage |
| response = self.listUsageRecords(usagetype=14) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| vpnUserUsageRecords_1 = [record for record in usageRecords |
| if vpnuser_1.id == record.usageid] |
| |
| vpnuser1_rawusage = sum(float(record.rawusage) |
| for record in vpnUserUsageRecords_1) |
| |
| # Getting last usage job execution time |
| response = self.getLatestUsageJobExecutionTime() |
| self.assertEqual(response[0], PASS, response[1]) |
| lastUsageJobExecTime = response[1] |
| |
| # Checking exact VPN user creation time |
| response = self.getEventCreatedDateTime(vpnuser_1.username) |
| self.assertEqual(response[0], PASS, response[1]) |
| vpnUserCreatedDateTime = response[1] |
| self.debug("VPN creation date: %s" % vpnUserCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - vpnUserCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| self.debug("VPN user expected usage: %s" % expectedUsage) |
| |
| actualUsage = format(vpnuser1_rawusage, ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| vpnUserUsageRecords_2 = [record for record in usageRecords |
| if vpnuser_2.id == record.usageid] |
| |
| self.assertTrue(validateList(vpnUserUsageRecords_2)[0] == PASS, |
| "VPN user usage record list validation failed") |
| |
| vpnuser2_rawusage = sum(float(record.rawusage) |
| for record in vpnUserUsageRecords_2) |
| |
| # Checking exact VPN user creation time |
| response = self.getEventCreatedDateTime(vpnuser_2.username) |
| self.assertEqual(response[0], PASS, response[1]) |
| vpnUserCreatedDateTime = response[1] |
| self.debug("VPN creation date: %s" % vpnUserCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - vpnUserCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| self.debug("VPN user expected usage: %s" % expectedUsage) |
| |
| actualUsage = format(vpnuser2_rawusage, ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| # Step 6: |
| vpnuser_1.delete(self.apiclient) |
| |
| # Verify that VPN usage for user stopped |
| response = self.listUsageRecords(usagetype=14) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| vpnuser_1_Usage_t1 = sum(float(record.rawusage) for record |
| in [record for record in usageRecords |
| if vpnuser_1.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=14) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| vpnuser_1_Usage_t2 = sum(float(record.rawusage) for record |
| in [record for record in usageRecords |
| if vpnuser_1.id == record.usageid]) |
| |
| self.assertTrue( |
| vpnuser_1_Usage_t1 == vpnuser_1_Usage_t2, |
| "vpn user usage should be stopped once the user is deleted") |
| |
| # Step 7: |
| |
| # Step 8: |
| ssh_client = virtual_machine.get_ssh_client( |
| ipaddress=public_ip.ipaddress.ipaddress |
| ) |
| |
| res = ssh_client.execute("ping -c 1 www.google.com") |
| self.assertEqual( |
| str(res).count("1 received"), |
| 1, |
| "Ping to outside world from VM should be successful" |
| ) |
| # Verifying usage for bytes received - START |
| routers = list_routers( |
| self.apiclient, |
| networkid=isolated_network.id, |
| listall=True |
| ) |
| self.assertEqual( |
| validateList(routers)[0], |
| PASS, |
| "Routers list validation failed") |
| router = routers[0] |
| result = self.getCommandResultFromRouter( |
| router, |
| "iptables -L NETWORK_STATS -n -v -x") |
| |
| self.debug("iptables -L NETWORK_STATS -n -v -x: %s" % result) |
| |
| bytesReceivedIptableRows = [record for record in result if |
| "eth2 eth0" in record] |
| self.debug("bytes received rows: %s" % bytesReceivedIptableRows) |
| bytesReceivedOnRouter = sum( |
| int(record[1]) for record in [x.split() for x in bytesReceivedIptableRows]) |
| |
| self.debug( |
| "Bytes received extracted from router: %s" % |
| bytesReceivedOnRouter) |
| |
| # Verify that bytes received in usage are equal to |
| # as shown on router |
| response = self.listUsageRecords(usagetype=5) |
| self.assertEqual(response[0], PASS, response[1]) |
| bytesReceivedUsage = sum( |
| int(record.rawusage) for record in response[1]) |
| |
| self.assertTrue(bytesReceivedUsage == |
| bytesReceivedOnRouter, |
| "Total bytes received usage should be \ |
| equal to bytes received on router") |
| |
| # Verifying usage for bytes received - END |
| |
| # Step 9: |
| # Delete one NAT rule |
| nat_rule_2.delete(self.userapiclient) |
| |
| response = self.listUsageRecords(usagetype=12) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| natRule_2_Usage_t1 = sum(float(record.rawusage) for record |
| in [record for record in usageRecords |
| if nat_rule_2.id == record.usageid]) |
| |
| response = self.listUsageRecords(usagetype=12) |
| self.assertEqual(response[0], PASS, response[1]) |
| usageRecords = response[1] |
| |
| natRule_2_Usage_t2 = sum(float(record.rawusage) for record |
| in [record for record in usageRecords |
| if nat_rule_2.id == record.usageid]) |
| |
| self.assertTrue( |
| natRule_2_Usage_t1 == natRule_2_Usage_t2, |
| "NAT rule usage should be stopped once the rule is deleted") |
| |
| # Step 10: |
| |
| qresultset = self.dbclient.execute( |
| "select id from account where account_name = '%s';" |
| % self.account.name |
| ) |
| accountid = qresultset[0][0] |
| self.debug("accountid: %s" % accountid) |
| |
| qresultset = self.dbclient.execute( |
| "select current_bytes_sent, current_bytes_received from user_statistics where account_id = '%s';" % |
| accountid, |
| db="cloud_usage")[0] |
| |
| currentBytesSentBeforeRouterStop = qresultset[0] |
| currentBytesReceivedBeforeRouterStop = qresultset[1] |
| |
| self.debug(currentBytesSentBeforeRouterStop) |
| self.debug(currentBytesReceivedBeforeRouterStop) |
| |
| # Stop the VPC Router |
| routers = Router.list( |
| self.api_client, |
| account=self.account.name, |
| domainid=self.account.domainid, |
| listall=True |
| ) |
| self.assertEqual( |
| isinstance(routers, list), |
| True, |
| "List Routers should return a valid list" |
| ) |
| router = routers[0] |
| self.debug("Stopping the router with ID: %s" % router.id) |
| |
| Router.stop( |
| self.apiclient, |
| id=router.id |
| ) |
| |
| response = verifyRouterState( |
| self.apiclient, |
| router.id, |
| "stopped") |
| self.assertEqual(response[0], PASS, response[1]) |
| |
| # TODO: Verify iptables counters are reset when domR stops |
| |
| qresultset = self.dbclient.execute( |
| "select current_bytes_sent, current_bytes_received, net_bytes_sent, net_bytes_received from user_statistics where account_id = '%s';" % |
| accountid, |
| db="cloud_usage")[0] |
| |
| currentBytesSentAfterRouterStop = int(qresultset[0]) |
| currentBytesReceivedAfterRouterStop = int(qresultset[1]) |
| netBytesSentAfterRouterStop = int(qresultset[0]) |
| netBytesReceivedAfterRouterStop = int(qresultset[1]) |
| |
| self.debug(currentBytesSentAfterRouterStop) |
| self.debug(currentBytesReceivedAfterRouterStop) |
| self.debug(netBytesSentAfterRouterStop) |
| self.debug(netBytesReceivedAfterRouterStop) |
| |
| self.assertTrue( |
| (currentBytesSentAfterRouterStop + |
| currentBytesReceivedAfterRouterStop) == 0, |
| "Current bytes should be 0") |
| |
| self.assertTrue( |
| (currentBytesSentBeforeRouterStop + |
| currentBytesReceivedBeforeRouterStop) == ( |
| netBytesSentAfterRouterStop + |
| netBytesReceivedAfterRouterStop), |
| "current bytes should be moved to net bytes") |
| |
| # Step 11: |
| # Start the router |
| Router.start( |
| self.apiclient, |
| id=router.id |
| ) |
| |
| response = verifyRouterState( |
| self.apiclient, |
| router.id, |
| "running") |
| self.assertEqual(response[0], PASS, response[1]) |
| |
| # TODO |
| # Verify iptables counters are reset when domR starts |
| # Verify a diff of total (current_bytes + net_bytes) in previous |
| # aggregation period and current period will give the network usage |
| return |
| |
| @attr(tags=["advanced", "basic"], required_hardware="false") |
| def test_08_checkNewVolumein_listUsageRecords(self): |
| """ Test case to check if new volume crated after |
| restore VM is listed in listUsageRecords |
| # 1. Launch a VM |
| # 2. Restore the VM |
| # 3. Check if the new volume created is listed in listUsageRecords API |
| """ |
| |
| # Step 1 |
| vm = VirtualMachine.create( |
| self.userapiclient, |
| self.testdata["small"], |
| templateid=self.template.id, |
| accountid=self.account.name, |
| domainid=self.account.domainid, |
| serviceofferingid=self.service_offering.id, |
| zoneid=self.zone.id, |
| ) |
| |
| volumes_root_list = list_volumes( |
| self.apiclient, |
| virtualmachineid=vm.id, |
| type='ROOT', |
| listall=True |
| ) |
| list_validation = validateList(volumes_root_list) |
| |
| self.assertEqual( |
| list_validation[0], |
| PASS, |
| "Volume list validation failed due to %s" % |
| list_validation[2]) |
| |
| root_volume = volumes_root_list[0] |
| |
| # Step 2 |
| vm.restore(self.apiclient) |
| |
| qresultset = self.dbclient.execute( |
| "select id from volumes where name='%s' and state='Ready';" % |
| root_volume.name) |
| |
| db_list_validation = validateList(qresultset) |
| |
| self.assertEqual( |
| db_list_validation[0], |
| PASS, |
| "Database list validation failed due to %s" % |
| db_list_validation[2]) |
| |
| self.assertNotEqual( |
| len(qresultset), |
| 0, |
| "Check DB Query result set" |
| ) |
| |
| volumeCheck = "Volume Id: " + str(qresultset[0][0]) + " usage time" |
| |
| response = self.listUsageRecords(usagetype=6) |
| self.assertEqual(response[0], PASS, response[1]) |
| UsageRecords = [record for record in response[1] |
| if volumeCheck in record.description] |
| # Step 3 |
| if not UsageRecords: |
| self.fail( |
| "listUsageRecords not returning usage for newly created volume") |
| |
| |
| class TestUsageDataAggregatior(cloudstackTestCase): |
| |
| @classmethod |
| def setUpClass(cls): |
| testClient = super(TestUsageDataAggregatior, cls).getClsTestClient() |
| cls.apiclient = testClient.getApiClient() |
| return |
| |
| def setUp(self): |
| self.apiclient = self.testClient.getApiClient() |
| self.cleanup = [] |
| |
| def listUsageTypes(self, apiclient=None): |
| """ List Usage Types |
| """ |
| try: |
| usageTypes = Usage.listTypes( |
| self.apiclient |
| ) |
| |
| self.assertEqual( |
| validateList(usageTypes)[0], |
| PASS, |
| "usage types list validation failed") |
| |
| return [PASS, usageTypes] |
| except Exception as e: |
| return [FAIL, e] |
| |
| return |
| |
| @attr(tags=["advanced"], required_hardware="true") |
| def test_01_positive_tests_usagetypes_listTypes(self): |
| """ 1. List Usage Types |
| 2. Verify Usage Id and Type mapping |
| """ |
| usageTypes = [ |
| { |
| "usagetypeid": 1, "description": 'Running Vm Usage'}, { |
| "usagetypeid": 2, "description": 'Allocated Vm Usage'}, { |
| "usagetypeid": 3, "description": 'IP Address Usage'}, { |
| "usagetypeid": 4, "description": 'Network Usage (Bytes Sent)'}, { |
| "usagetypeid": 5, "description": 'Network Usage (Bytes Received)'}, { |
| "usagetypeid": 6, "description": 'Volume Usage'}, { |
| "usagetypeid": 7, "description": 'Template Usage'}, { |
| "usagetypeid": 8, "description": 'ISO Usage'}, { |
| "usagetypeid": 9, "description": 'Snapshot Usage'}, { |
| "usagetypeid": 11, "description": 'Load Balancer Usage'}, { |
| "usagetypeid": 12, "description": 'Port Forwarding Usage'}, { |
| "usagetypeid": 13, "description": 'Network Offering Usage'}, { |
| "usagetypeid": 14, "description": 'VPN users usage' |
| } |
| ] |
| listTypes = [] |
| response = self.listUsageTypes() |
| respTypes = response[1] |
| |
| for res in respTypes: |
| dictTypes = { |
| "usagetypeid": res.usagetypeid, |
| "description": res.description} |
| listTypes.append(dictTypes) |
| |
| for type in usageTypes: |
| if type not in listTypes: |
| self.fail("Usage Type %s not present in list" % type) |
| |
| return |
| |
| |
| class TestUsageDirectMeteringBasicZone(cloudstackTestCase): |
| |
| @classmethod |
| def setUpClass(cls): |
| testClient = super( |
| TestUsageDirectMeteringBasicZone, |
| cls).getClsTestClient() |
| cls.apiclient = testClient.getApiClient() |
| cls.testdata = testClient.getParsedTestDataConfig() |
| cls._cleanup = [] |
| # Get Zone, Domain and templates |
| cls.domain = get_domain(cls.apiclient) |
| cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) |
| |
| cls.mgtSvrDetails = cls.config.__dict__["mgtSvr"][0].__dict__ |
| |
| isUsageJobRunning = cls.IsUsageJobRunning() |
| cls.usageJobNotRunning = False |
| if not isUsageJobRunning: |
| cls.usageJobNotRunning = True |
| return |
| |
| if cls.testdata["configurableData"][ |
| "setUsageConfigurationThroughTestCase"]: |
| cls.setUsageConfiguration() |
| cls.RestartServers() |
| else: |
| currentMgtSvrTime = cls.getCurrentMgtSvrTime() |
| dateTimeSplit = currentMgtSvrTime.split("/") |
| cls.curDate = dateTimeSplit[0] |
| |
| cls.template = get_template( |
| cls.apiclient, |
| cls.zone.id, |
| cls.testdata["ostype"]) |
| |
| try: |
| # If local storage is enabled, alter the offerings to use |
| # localstorage |
| if cls.zone.localstorageenable: |
| cls.testdata["service_offering"]["storagetype"] = 'local' |
| |
| # Create 2 service offerings with different values for |
| # for cpunumber, cpuspeed, and memory |
| |
| cls.testdata["service_offering"]["cpunumber"] = "1" |
| cls.testdata["service_offering"]["cpuspeed"] = "128" |
| cls.testdata["service_offering"]["memory"] = "256" |
| |
| cls.service_offering = ServiceOffering.create( |
| cls.apiclient, |
| cls.testdata["service_offering"] |
| ) |
| cls._cleanup.append(cls.service_offering) |
| |
| configs = Configurations.list( |
| cls.apiclient, |
| name='usage.stats.job.aggregation.range' |
| ) |
| |
| # Set the value for one more minute than |
| # actual range to be on safer side |
| cls.usageJobAggregationRange = ( |
| int(configs[0].value) + 1) * 60 # in seconds |
| except Exception as e: |
| cls.tearDownClass() |
| raise e |
| return |
| |
| @classmethod |
| def tearDownClass(cls): |
| try: |
| cleanup_resources(cls.apiclient, cls._cleanup) |
| except Exception as e: |
| raise Exception("Warning: Exception during cleanup : %s" % e) |
| |
| def setUp(self): |
| self.apiclient = self.testClient.getApiClient() |
| self.dbclient = self.testClient.getDbConnection() |
| self.cleanup = [] |
| if self.usageJobNotRunning: |
| self.skipTest("Skipping test because usage job not running") |
| # Create an account |
| self.account = Account.create( |
| self.apiclient, |
| self.testdata["account"], |
| domainid=self.domain.id |
| ) |
| self.cleanup.append(self.account) |
| # Create user api client of the account |
| self.userapiclient = self.testClient.getUserApiClient( |
| UserName=self.account.name, |
| DomainName=self.account.domain |
| ) |
| |
| def tearDown(self): |
| try: |
| cleanup_resources(self.apiclient, self.cleanup) |
| except Exception as e: |
| raise Exception("Warning: Exception during cleanup : %s" % e) |
| return |
| |
| @classmethod |
| def setUsageConfiguration(cls): |
| """ Set the configuration parameters so that usage job runs |
| every 10 miuntes """ |
| |
| Configurations.update( |
| cls.apiclient, |
| name="enable.usage.server", |
| value="true" |
| ) |
| |
| Configurations.update( |
| cls.apiclient, |
| name="usage.aggregation.timezone", |
| value="GMT" |
| ) |
| |
| Configurations.update( |
| cls.apiclient, |
| name="usage.execution.timezone", |
| value="GMT" |
| ) |
| |
| Configurations.update( |
| cls.apiclient, |
| name="usage.stats.job.aggregation.range", |
| value="10" |
| ) |
| |
| currentMgtSvrTime = cls.getCurrentMgtSvrTime() |
| dateTimeSplit = currentMgtSvrTime.split("/") |
| cls.curDate = dateTimeSplit[0] |
| timeSplit = dateTimeSplit[1].split(":") |
| minutes = int(timeSplit[1]) |
| minutes += 5 |
| usageJobExecTime = timeSplit[0] + ":" + str(minutes) |
| |
| Configurations.update( |
| cls.apiclient, |
| name="usage.stats.job.exec.time", |
| value=usageJobExecTime |
| ) |
| |
| return |
| |
| @classmethod |
| def getCurrentMgtSvrTime(cls, format='%Y-%m-%d/%H:%M'): |
| """ Get the current time from Management Server """ |
| |
| sshClient = SshClient( |
| cls.mgtSvrDetails["mgtSvrIp"], |
| 22, |
| cls.mgtSvrDetails["user"], |
| cls.mgtSvrDetails["passwd"] |
| ) |
| command = "date +%s" % format |
| return sshClient.execute(command)[0] |
| |
| @classmethod |
| def RestartServers(cls): |
| """ Restart management server and usage server """ |
| |
| sshClient = SshClient( |
| cls.mgtSvrDetails["mgtSvrIp"], |
| 22, |
| cls.mgtSvrDetails["user"], |
| cls.mgtSvrDetails["passwd"] |
| ) |
| command = "service cloudstack-management restart" |
| sshClient.execute(command) |
| |
| command = "service cloudstack-usage restart" |
| sshClient.execute(command) |
| return |
| |
| @classmethod |
| def IsUsageJobRunning(cls): |
| """ Check that usage job is running on Management server or not""" |
| |
| sshClient = SshClient( |
| cls.mgtSvrDetails["mgtSvrIp"], |
| 22, |
| cls.mgtSvrDetails["user"], |
| cls.mgtSvrDetails["passwd"] |
| ) |
| |
| command = "service cloudstack-usage status" |
| response = str(sshClient.execute(command)).lower() |
| if "unknown" in response: |
| return False |
| return True |
| |
| def listUsageRecords(self, usagetype, apiclient=None, startdate=None, |
| enddate=None, account=None, sleep=True): |
| """List and return the usage record for given account |
| and given usage type""" |
| |
| if sleep: |
| # Sleep till usage job has run at least once after the operation |
| self.debug( |
| "Sleeping for %s seconds" % |
| self.usageJobAggregationRange) |
| time.sleep(self.usageJobAggregationRange) |
| |
| if not startdate: |
| startdate = self.curDate |
| if not enddate: |
| enddate = self.curDate |
| if not account: |
| account = self.account |
| if not apiclient: |
| self.apiclient |
| |
| Usage.generateRecords( |
| self.apiclient, |
| startdate=startdate, |
| enddate=enddate) |
| |
| try: |
| usageRecords = Usage.listRecords( |
| self.apiclient, |
| startdate=startdate, |
| enddate=enddate, |
| account=account.name, |
| domainid=account.domainid, |
| type=usagetype) |
| |
| self.assertEqual( |
| validateList(usageRecords)[0], |
| PASS, |
| "usage records list validation failed") |
| |
| return [PASS, usageRecords] |
| except Exception as e: |
| return [FAIL, e] |
| return |
| |
| def getLatestUsageJobExecutionTime(self): |
| """ Get the end time of latest usage job that has run successfully""" |
| |
| try: |
| qresultset = self.dbclient.execute( |
| "SELECT max(end_date) FROM usage_job WHERE success=1;", |
| db="cloud_usage") |
| |
| self.assertNotEqual( |
| len(qresultset), |
| 0, |
| "Check DB Query result set" |
| ) |
| |
| lastUsageJobExecutionTime = qresultset[0][0] |
| self.debug( |
| "last usage job exec time: %s" % |
| lastUsageJobExecutionTime) |
| return [PASS, lastUsageJobExecutionTime] |
| except Exception as e: |
| return [FAIL, e] |
| |
| def getEventCreatedDateTime(self, resourceName): |
| """ Get the created date/time of particular entity |
| from cloud_usage.usage_event table """ |
| |
| try: |
| # Checking exact entity creation time |
| qresultset = self.dbclient.execute( |
| "select created from usage_event where resource_name = '%s';" % |
| str(resourceName), db="cloud_usage") |
| self.assertNotEqual( |
| len(qresultset), |
| 0, |
| "Check DB Query result set" |
| ) |
| eventCreatedDateTime = qresultset[0][0] |
| except Exception as e: |
| return [FAIL, e] |
| return [PASS, eventCreatedDateTime] |
| |
| @attr(tags=["basic"], required_hardware="true") |
| def test_01_positive_tests_usage_basic_zone(self): |
| """ Positive test for usage test path Basic Zone |
| |
| # 1. Deploy VM in basic zone and verify that VM usage is generated |
| for the account with correct service offering |
| # 2. SSH to VM and ping to external network |
| # 3. Verify correct network byte usage is generated for the account |
| """ |
| # Create VM in account |
| vm = VirtualMachine.create( |
| self.userapiclient, |
| self.testdata["small"], |
| templateid=self.template.id, |
| accountid=self.account.name, |
| domainid=self.account.domainid, |
| serviceofferingid=self.service_offering.id, |
| zoneid=self.zone.id, |
| mode=self.zone.networktype |
| ) |
| |
| # Checking running VM usage |
| response = self.listUsageRecords(usagetype=1) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmRunningUsageRecords = [record for record in response[1] |
| if record.virtualmachineid == vm.id] |
| |
| vmRunningRawUsage = sum(float(record.rawusage) |
| for record in vmRunningUsageRecords) |
| |
| self.assertEqual(vmRunningUsageRecords[0].offeringid, |
| self.service_offering.id, |
| "The service offering id in the usage record\ |
| does not match with id of service offering\ |
| with which the VM was created") |
| |
| self.assertEqual(vmRunningUsageRecords[0].templateid, |
| self.template.id, |
| "The template id in the usage record\ |
| does not match with id of template\ |
| with which the VM was created") |
| |
| response = self.listUsageRecords(usagetype=2, sleep=False) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmAllocatedUsageRecords = [record for record in response[1] |
| if record.virtualmachineid == vm.id] |
| |
| vmAllocatedRawUsage = sum(float(record.rawusage) |
| for record in vmAllocatedUsageRecords) |
| |
| self.debug("running vm usage: %s" % vmRunningRawUsage) |
| self.debug("allocated vm usage: %s" % vmAllocatedRawUsage) |
| |
| self.assertTrue( |
| vmRunningRawUsage < vmAllocatedRawUsage, |
| "Allocated VM usage should be greater than Running VM usage") |
| |
| # Getting last usage job execution time |
| response = self.getLatestUsageJobExecutionTime() |
| self.assertEqual(response[0], PASS, response[1]) |
| lastUsageJobExecTime = response[1] |
| |
| # Checking exact VM creation time |
| response = self.getEventCreatedDateTime(vm.name) |
| self.assertEqual(response[0], PASS, response[1]) |
| vmCreatedDateTime = response[1] |
| self.debug("Vm creation date: %s" % vmCreatedDateTime) |
| |
| # We have to get the expected usage count in hours as the rawusage returned by listUsageRecords |
| # is also in hours |
| expectedUsage = format( |
| ((lastUsageJobExecTime - vmCreatedDateTime).total_seconds() / 3600), |
| ".2f") |
| self.debug("VM expected usage: %s" % expectedUsage) |
| |
| actualUsage = format(vmAllocatedRawUsage, ".2f") |
| |
| self.assertEqual( |
| expectedUsage, |
| actualUsage, |
| "expected usage %s and actual usage %s not matching" % |
| (expectedUsage, |
| actualUsage)) |
| |
| # TODO: Add traffic sentinel, because it is needed in basic zone |
| # to gather network traffic values |
| """ssh_client = vm.get_ssh_client() |
| |
| res = ssh_client.execute("ping -c 1 www.google.com") |
| result = str(res) |
| |
| self.assertEqual( |
| result.count("1 received"), |
| 1, |
| "Ping to outside world from VM should be successful" |
| ) |
| |
| result = str(res[1]) |
| bytesReceived = int(result.split("bytes", 1)[0]) |
| response = self.listUsageRecords(usagetype=5) |
| self.assertEqual(response[0], PASS, response[1]) |
| bytesReceivedUsageRecord = sum( |
| int(record.rawusage) for record in response[1]) |
| |
| self.assertTrue(bytesReceivedUsageRecord >= |
| bytesReceived, |
| "Total bytes received usage should be greater than\ |
| or equal to bytes received by pinging\ |
| www.google.com")""" |
| return |