# 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