def test_price_estimate_of_resource_is_keeped_up_to_date(self): start_time = datetime.datetime(2016, 8, 8, 11, 0) with freeze_time(start_time): today = timezone.now() old_disk = 20 * 1024 resource = structure_factories.TestNewInstanceFactory( state=TestNewInstance.States.OK, runtime_state='online', disk=old_disk) price_estimate = models.PriceEstimate.objects.get( scope=resource, month=today.month, year=today.year) # after resource creation price estimate should be calculate for whole month month_end = datetime.datetime(2016, 8, 31, 23, 59, 59) expected = (int((month_end - start_time).total_seconds() / 60) * self.price_list_item.minute_rate * old_disk) self.assertAlmostEqual(price_estimate.total, expected) # after some time resource disk was updated - resource price should be recalculated change_time = datetime.datetime(2016, 8, 9, 13, 0) with freeze_time(change_time): new_disk = 40 * 1024 resource.disk = new_disk resource.save() price_estimate.refresh_from_db() expected = (int((change_time - start_time).total_seconds() / 60) * self.price_list_item.minute_rate * old_disk + int( (month_end - change_time).total_seconds() / 60) * self.price_list_item.minute_rate * new_disk) self.assertAlmostEqual(price_estimate.total, expected)
def test_if_resource_becomes_offline_start_time_is_resetted(self): vm = factories.TestNewInstanceFactory(runtime_state='paused', start_time=timezone.now()) vm.runtime_state = 'offline' vm.save() vm.refresh_from_db() self.assertEqual(vm.start_time, None)
def test_consumed_is_recalculated_properly_for_ancestors(self): with freeze_time(self.start_time): self.second_resource = structure_factories.TestNewInstanceFactory( disk=10 * 1024, service_project_link=self.spl) calculation_time = datetime.datetime(2016, 8, 8, 15, 0) with freeze_time(calculation_time): tasks.recalculate_estimate() price_estimates = [ models.PriceEstimate.objects.get_current(scope=ancestor) for ancestor in (self.customer, self.service, self.spl, self.project) ] working_minutes = (calculation_time - self.start_time).total_seconds() / 60 # each ancestor is connected with 2 resources expected = working_minutes * self.price_list_item.minute_rate * ( self.resource.disk + self.second_resource.disk) for price_estimate in price_estimates: message = 'Price estimate "consumed" is calculated wrongly for "%s". Real value: %s, expected: %s.' % ( price_estimate.scope, price_estimate.consumed, expected) self.assertAlmostEqual(price_estimate.consumed, expected, msg=message)
def create_resource(self, customer, project): settings = factories.ServiceSettingsFactory(customer=customer) service = factories.TestServiceFactory(customer=customer, settings=settings) spl = factories.TestServiceProjectLinkFactory(service=service, project=project) resource = factories.TestNewInstanceFactory(service_project_link=spl) return resource
def test_if_runtime_state_changed_to_other_state_start_time_is_not_modified( self): vm = factories.TestNewInstanceFactory(runtime_state='online', start_time=None) vm.runtime_state = 'extending' vm.save() vm.refresh_from_db() self.assertEqual(vm.start_time, None)
def test_new_resource_unlinked_immediately(self): vm = factories.TestNewInstanceFactory(state=NewResource.States.OK) url = factories.TestNewInstanceFactory.get_url(vm, 'unlink') response = self.client.post(url) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT, response.data)
def test_resource_can_be_filtered_by_tag(self): self.fixture.resource.tags.add('tag1') resource2 = factories.TestNewInstanceFactory( service_project_link=self.fixture.service_project_link) resource2.tags.add('tag2') url = factories.TestNewInstanceFactory.get_list_url() response = self.client.get(url, {'tag': 'tag1'}) self.assertEqual(len(response.data), 1)
def test_if_resource_becomes_online_start_time_is_initialized(self): now = timezone.now() with freeze_time(now): vm = factories.TestNewInstanceFactory(runtime_state='in-progress', start_time=None) vm.runtime_state = 'online' vm.save() vm.refresh_from_db() self.assertEqual(vm.start_time, now)
def setUp(self): self.customer = factories.CustomerFactory() self.settings = factories.ServiceSettingsFactory(shared=True) self.service = factories.TestServiceFactory(customer=self.customer, settings=self.settings) self.user1 = factories.UserFactory() self.project1 = factories.ProjectFactory(customer=self.customer) self.project1.add_user(self.user1, ProjectRole.ADMINISTRATOR) self.spl1 = factories.TestServiceProjectLinkFactory(service=self.service, project=self.project1) self.vm1 = factories.TestNewInstanceFactory(service_project_link=self.spl1) self.user2 = factories.UserFactory() self.project2 = factories.ProjectFactory(customer=self.customer) self.project2.add_user(self.user2, ProjectRole.ADMINISTRATOR) self.spl2 = factories.TestServiceProjectLinkFactory(service=self.service, project=self.project2) self.vm2 = factories.TestNewInstanceFactory(service_project_link=self.spl2) self.service_url = factories.TestServiceFactory.get_url(self.service)
def setUp(self): super(CustomerFilterTest, self).setUp() resource = structure_factories.TestNewInstanceFactory() link = resource.service_project_link customer = link.customer project = link.project service = link.service scopes = {link, customer, project, service, resource} self.estimates = { models.PriceEstimate.objects.get(scope=scope) for scope in scopes } self.customer = customer resource2 = structure_factories.TestNewInstanceFactory() resource2_estimate = factories.PriceEstimateFactory(scope=resource2) resource2_estimate.create_ancestors()
def test_when_service_is_unlinked_all_related_resources_are_unlinked_too(self): resource = factories.TestNewInstanceFactory() service = resource.service_project_link.service unlink_url = factories.TestServiceFactory.get_url(service, 'unlink') self.client.force_authenticate(factories.UserFactory(is_staff=True)) response = self.client.post(unlink_url) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) self.assertRaises(models.ObjectDoesNotExist, service.refresh_from_db)
def test_task_does_not_set_coordinates_if_response_is_not_ok( self, mock_request_get): ip_address = "127.0.0.1" instance = factories.TestNewInstanceFactory() mock_request_get.return_value.ok = False tasks.detect_vm_coordinates(utils.serialize_instance(instance)) instance.refresh_from_db() self.assertIsNone(instance.latitude) self.assertIsNone(instance.longitude)
def test_historical_estimates_are_initialized(self): creation_time = timezone.make_aware( datetime.datetime(2016, 7, 15, 11, 0)) import_time = timezone.make_aware(datetime.datetime(2016, 9, 2, 10, 0)) with freeze_time(import_time): resource = structure_factories.TestNewInstanceFactory( state=TestNewInstance.States.OK, runtime_state='online', disk=20 * 1024, created=creation_time) ancestors = [ resource.service_project_link, resource.service_project_link.service, resource.service_project_link.project, resource.service_project_link.project.customer ] # signal should init estimates for resource and its ancestors for previous months for scope in [resource] + ancestors: self.assertTrue( models.PriceEstimate.objects.filter(scope=scope, month=7, year=2016)) self.assertTrue( models.PriceEstimate.objects.filter(scope=scope, month=8, year=2016)) # Check price estimates total calculation for month #7 month_end = timezone.make_aware( datetime.datetime(2016, 7, 31, 23, 59, 59)) work_minutes = int((month_end - creation_time).total_seconds() / 60) expected = work_minutes * self.price_list_item.minute_rate * resource.disk for scope in [resource] + ancestors: estimate = models.PriceEstimate.objects.get(scope=scope, month=7, year=2016) self.assertEqual(estimate.total, expected) # Check price estimates total calculation for month #8 month_start = timezone.make_aware(datetime.datetime(2016, 8, 1)) month_end = timezone.make_aware( datetime.datetime(2016, 8, 31, 23, 59, 59)) work_minutes = int((month_end - month_start).total_seconds() / 60) expected = work_minutes * self.price_list_item.minute_rate * resource.disk for scope in [resource] + ancestors: estimate = models.PriceEstimate.objects.get(scope=scope, month=8, year=2016) self.assertAlmostEqual(estimate.total, expected)
def test_when_virtual_machine_is_deleted_descendant_resources_unlinked( self): # Arrange vm = factories.TestNewInstanceFactory() settings = factories.ServiceSettingsFactory(scope=vm) service = factories.TestServiceFactory(settings=settings) link = factories.TestServiceProjectLinkFactory(service=service) child_vm = factories.TestNewInstanceFactory(service_project_link=link) other_vm = factories.TestNewInstanceFactory() # Act vm.delete() # Assert self.assertFalse( test_models.TestNewInstance.objects.filter( id=child_vm.id).exists()) self.assertFalse( test_models.TestService.objects.filter(id=service.id).exists()) self.assertFalse( ServiceSettings.objects.filter(id=settings.id).exists()) self.assertTrue( test_models.TestNewInstance.objects.filter( id=other_vm.id).exists())
def test_if_limit_is_reached_provisioning_is_delayed(self, params): link = factories.TestServiceProjectLinkFactory() factories.TestNewInstanceFactory.create_batch( size=params['size'], state=models.TestNewInstance.States.CREATING, service_project_link=link) vm = factories.TestNewInstanceFactory( state=models.TestNewInstance.States.CREATION_SCHEDULED, service_project_link=link) serialized_vm = utils.serialize_instance(vm) mocked_retry = Mock() tasks.ThrottleProvisionTask.retry = mocked_retry tasks.ThrottleProvisionTask().si( serialized_vm, 'create', state_transition='begin_starting').apply() self.assertEqual(mocked_retry.called, params['retried'])
def test_consumption_details_of_resource_is_keeped_up_to_date_on_quota_change( self): today = timezone.now() resource = structure_factories.TestNewInstanceFactory() quota_item = ConsumableItem('quotas', 'test_quota') price_estimate = models.PriceEstimate.objects.get(scope=resource, month=today.month, year=today.year) consumption_details = price_estimate.consumption_details self.assertEqual(consumption_details.configuration[quota_item], 0) resource.set_quota_usage(TestNewInstance.Quotas.test_quota, 5) consumption_details.refresh_from_db() self.assertEqual(consumption_details.configuration[quota_item], 5)
def setUp(self): super(ScopeTypeFilterTest, self).setUp() resource = structure_factories.TestNewInstanceFactory( service_project_link=self.service_project_link) self.estimates = { 'customer': models.PriceEstimate.objects.get(scope=self.customer), 'service': models.PriceEstimate.objects.get(scope=self.service), 'project': models.PriceEstimate.objects.get(scope=self.project), 'service_project_link': models.PriceEstimate.objects.get(scope=self.service_project_link), 'resource': models.PriceEstimate.objects.get(scope=resource), }
def test_task_sets_coordinates(self, mock_request_get): ip_address = "127.0.0.1" expected_latitude = 20 expected_longitude = 20 instance = factories.TestNewInstanceFactory() mock_request_get.return_value.ok = True response = { "ip": ip_address, "latitude": expected_latitude, "longitude": expected_longitude } mock_request_get.return_value.json.return_value = response tasks.detect_vm_coordinates(utils.serialize_instance(instance)) instance.refresh_from_db() self.assertEqual(instance.latitude, expected_latitude) self.assertEqual(instance.longitude, expected_longitude)
def setUp(self): resource_content_type = ContentType.objects.get_for_model( TestNewInstance) self.price_list_item = models.DefaultPriceListItem.objects.create( item_type='storage', key='1 MB', resource_content_type=resource_content_type, value=2) CostTrackingRegister.register_strategy( factories.TestNewInstanceCostTrackingStrategy) self.start_time = datetime.datetime(2016, 8, 8, 11, 0) with freeze_time(self.start_time): self.resource = structure_factories.TestNewInstanceFactory( disk=20 * 1024) self.spl = self.resource.service_project_link self.project = self.spl.project self.customer = self.project.customer self.service = self.spl.service
def test_consumption_details_of_resource_is_keeped_up_to_date(self): today = timezone.now() configuration = dict(ram=2048, disk=20 * 1024, cores=2) resource = structure_factories.TestNewInstanceFactory( state=TestNewInstance.States.OK, runtime_state='online', **configuration) price_estimate = models.PriceEstimate.objects.get(scope=resource, month=today.month, year=today.year) consumption_details = price_estimate.consumption_details expected = { ConsumableItem('ram', '1 MB'): 2048, ConsumableItem('storage', '1 MB'): 20 * 1024, ConsumableItem('cores', '1 core'): 2, ConsumableItem('quotas', 'test_quota'): 0, } self.assertDictEqual(consumption_details.configuration, expected) resource.ram = 1024 resource.save() consumption_details.refresh_from_db() self.assertEqual( consumption_details.configuration[ConsumableItem('ram', '1 MB')], resource.ram) resource.runtime_state = 'offline' resource.save() # test resource uses only storage and quota when it is offline expected = { ConsumableItem('storage', '1 MB'): 20 * 1024, ConsumableItem('quotas', 'test_quota'): 0 } consumption_details.refresh_from_db() self.assertDictEqual(consumption_details.configuration, expected) resource.flavor_name = 'small' resource.save() consumption_details.refresh_from_db() self.assertEqual( consumption_details.configuration[ConsumableItem( 'flavor', 'small')], 1)
def test_price_estimate_of_resource_ancestors_is_keeped_up_to_date(self): """ On resource configuration tests handlers should update resource ancestors estimates """ start_time = datetime.datetime(2016, 8, 8, 11, 0) with freeze_time(start_time): today = timezone.now() old_disk = 20 * 1024 resource = structure_factories.TestNewInstanceFactory( state=TestNewInstance.States.OK, runtime_state='online', disk=old_disk) ancestors = [ resource.service_project_link, resource.service_project_link.service, resource.service_project_link.project, resource.service_project_link.project.customer ] # after resource creation price for it ancestors should be calculate for whole month month_end = datetime.datetime(2016, 8, 31, 23, 59, 59) expected = (int((month_end - start_time).total_seconds() / 60) * self.price_list_item.minute_rate * old_disk) for ancestor in ancestors: ancestor_estimate = models.PriceEstimate.objects.get( scope=ancestor, month=today.month, year=today.year) self.assertAlmostEqual(ancestor_estimate.total, expected) # after some time resource disk was updated - resource ancestors price should be recalculated change_time = datetime.datetime(2016, 8, 9, 13, 0) with freeze_time(change_time): new_disk = 40 * 1024 resource.disk = new_disk resource.save() expected = (int((change_time - start_time).total_seconds() / 60) * self.price_list_item.minute_rate * old_disk + int( (month_end - change_time).total_seconds() / 60) * self.price_list_item.minute_rate * new_disk) for ancestor in ancestors: ancestor_estimate = models.PriceEstimate.objects.get( scope=ancestor, month=today.month, year=today.year) self.assertAlmostEqual(ancestor_estimate.total, expected)
def test_get_for_resource(self): resource = structure_factories.TestNewInstanceFactory() resource_content_type = ContentType.objects.get_for_model(resource) service = resource.service_project_link.service # resource has two default price list items default_item1 = models.DefaultPriceListItem.objects.create( resource_content_type=resource_content_type, item_type='flavor', key='small', value=10) default_item2 = models.DefaultPriceListItem.objects.create( resource_content_type=resource_content_type, item_type='storage', key='1 GB', value=0.5) # the second item is overridden be regular price list item item = models.PriceListItem.objects.create( default_price_list_item=default_item2, service=service) expected = {default_item1, item} self.assertSetEqual(models.PriceListItem.get_for_resource(resource), expected)
def test_vm_unlinked_immediately_anyway(self): vm = factories.TestNewInstanceFactory(state=States.UPDATING) url = factories.TestNewInstanceFactory.get_url(vm, 'unlink') response = self.client.post(url) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT, response.data)