def calculate_usage_cost(self, usages): from model import Service, Category, ServicePrice from task.notifications import notify_managers_about_new_service_in_tariff total_cost = Decimal() tariff = self.tariff if not tariff: raise Exception("Tariff is not set for customer %s" % self) services = tariff.services_as_dict(lower=True) for usage in usages: db.session.add(usage) service_id = usage.service_id.lower() if isinstance(usage.service_id, str) else str(usage.service_id) service_price = services.get(service_id) service = Service.get_by_id(service_id) usage.tariff_id = tariff.tariff_id usage.customer_mode = self.customer_mode if service is None: logbook.error("Not found declaration service {} during calculate usage for {}", usage.service_id, self) continue usage_volume = service.calculate_volume_usage(usage) usage.usage_volume = usage_volume if service_price is None: if service.category_id == Category.VM: if service.deleted: logbook.error("Service {} not found in {} for {}. But this service is archived", service_id, tariff, self) else: service_price = ServicePrice(service_id=service_id, price=Decimal(0), need_changing=True) self.tariff.services.append(service_price) services = tariff.services_as_dict(lower=True) flavor_name = Service.get_by_id(service_id).flavor.flavor_id notify_managers_about_new_service_in_tariff.delay(self.customer_id, flavor_name) else: logbook.warning("Service {} not found in {} for {}. Allowed services: {}", service_id, tariff, self, services.keys()) if service_price: usage_cost = usage_volume * service_price.price / service.hours else: usage_cost = Decimal(0) total_cost += usage_cost usage.cost = usage_cost logbook.info("Found {} usages for customer {}. Total cost of used resources is: {}", len(usages), self, total_cost) return total_cost
def get_service(self, service_id): service = self.services.get(service_id) if not service: service = Service.get_by_id(service_id) if not service: raise ValueError("Service %s not found" % service_id) return service
def test_for_nonexistent_flavor(self): """ Tests that transformer doesn't stop when flavor.name isn't in database and creates fake entry in DB for that flavor. """ state = [ {'timestamp': testdata.t0, 'counter_volume': states['active'], 'metadata': {'flavor.name': testdata.flavor}}, {'timestamp': testdata.t0_30, 'counter_volume': states['active'], 'metadata': {'flavor.name': testdata.fake_flavor}}, {'timestamp': testdata.t1, 'counter_volume': states['active'], 'metadata': {'flavor.name': testdata.fake_flavor}} ] with mock.patch('os_interfaces.openstack_wrapper.openstack.get_nova_flavor', mock.MagicMock(side_effect=self.create_flavor_mock)): result = self._run_transform(state) result.sort(key=attrgetter("service_id")) flavor = Service.get_by_id(result[1].service_id).flavor self.assertEqual(flavor.flavor_id, testdata.fake_flavor) self.assertEqual(openstack.get_nova_flavor.call_count, 1) self.assertEqual(openstack.create_flavor.call_count, 10) self.assertEqual(result[1].end - result[1].start, datetime.timedelta(minutes=30, seconds=-1))
def test_create_flavor(self): service_id = self.admin_client.service.create_vm(**self.new_flavor_info)['service_id'] with self.expect_error(errors.ServiceAlreadyExisted): self.admin_client.service.create_vm(**self.new_flavor_info) self.new_flavor_info['localized_name'] = '{"ru": "Флавор Test Flavor", "en": "Flavor Test Flavor"}' with self.expect_error(errors.FlavorAlreadyExists): self.admin_client.service.create_vm(**self.new_flavor_info) self.assertEqual(openstack.create_flavor.call_count, 10) service = Service.get_by_id(service_id) service.mark_immutable() self.assertEqual(openstack.create_flavor.call_count, 11) self.new_flavor_info['localized_name'] = '{"ru": "Флавор TestFlavor1", "en": "Flavor TestFlavor1"}' self.new_flavor_info['flavor_id'] = "TestFlavor1" self.new_flavor_info.pop('network') service_id = self.admin_client.service.create_vm(**self.new_flavor_info)['service_id'] service = Service.get_by_id(service_id) self.assertIsNone(service.flavor.network) with mock.patch('os_interfaces.openstack_wrapper.openstack.get_nova_flavor', mock.MagicMock(side_effect=self.create_flavor_mock)): self.new_flavor_info['localized_name'] = '{"ru": "Флавор TestFlavor2", "en": "Flavor TestFlavor2"}' self.new_flavor_info['flavor_id'] = "TestFlavor2" with self.expect_error(errors.Conflict): service_id = self.admin_client.service.create_vm(**self.new_flavor_info)['service_id'] self.new_flavor_info['disk'] = 30 service_id = self.admin_client.service.create_vm(**self.new_flavor_info)['service_id'] service = Service.get_by_id(service_id) self.assertFalse(service.mutable)
def __call__(self, value): service_price_list = super().__call__(value) for service_price in service_price_list: service_id = service_price.get("service_id") service = Service.get_by_id(service_id) if not service: raise errors.ServiceNotFound() if service.deleted: raise errors.RemovedServiceInTariff() if service.mutable: raise errors.OnlyImmutableService() return service_price_list
def __init__(self, service_id, customer, tariff): self.currency = tariff.currency self.service = Service.get_by_id(service_id) if self.service: self.name = self.service.get_localized_name(customer.locale_language()) self.category = self.service.category.get_localized_name(customer.locale_language()) self.measure = self.service.measure.get_localized_name(customer.locale_language()) self.hours = self.service.hours else: self.name = str(service_id) self.category = "" self.measure = "" self.hours = 1 self.price = tariff.service_price(service_id) self.service_id = service_id self.resources = {}
def __init__(self, service_usage, customer, tariff): self.currency = tariff.currency service_id, tariff_id, total_cost, total_usage_volume = service_usage service = Service.get_by_id(service_id) if service: self.name = service.get_localized_name(customer.locale_language()) self.category = service.category.get_localized_name(customer.locale_language()) self.measure = service.measure.get_localized_name(customer.locale_language()) self.hours = service.hours else: self.name = str(service_id) self.category = "" self.measure = "" self.hours = 1 self.total_cost = total_cost or Decimal(0) self.total_usage_volume = total_usage_volume or 0 self.price = tariff.service_price(service_id) or Decimal(0) self.service_id = service_id
def get_service(self, service_id): """ Return service description :param Id service_id: Service Id :return dict service_info: Dict with service parameters **Example**:: { "service_info": { "service_id": "storage.volume", "measure": { "measure_type": "time_quant", "measure_id": "gigabyte*month", "localized_name": { "ru": "Гб*месяц", "en": "Gb*month" } }, "category": { "localized_name": { "ru": "Хранение данных", "en": "Storage" }, "category_id": "storage" }, "localized_name": { "ru": "Диск", "en": "Volume" } } } """ service = Service.get_by_id(service_id) if not service: raise errors.ServiceNotFound() return {"service_info": display(service)}
def get_service(self, service_id): """ Return service description :param Id service_id: Service Id :return dict service_info: Dict with service parameters **Example**:: { "service_info": { "service_id": "storage.volume", "measure": { "measure_type": "time_quant", "measure_id": "gigabyte*month", "localized_name": { "ru": "Гб*месяц", "en": "Gb*month" } }, "category": { "localized_name": { "ru": "Хранение данных", "en": "Storage" }, "category_id": "storage" }, "localized_name": { "ru": "Диск", "en": "Volume" } } } """ service = Service.get_by_id(service_id) if not service: raise errors.ServiceNotFound() return {"service_info": display(service)}
def __init__(self, service_id, customer, tariff): self.currency = tariff.currency self.service = Service.get_by_id(service_id) if self.service: self.name = self.service.get_localized_name( customer.locale_language()) self.category = self.service.category.get_localized_name( customer.locale_language()) self.measure = self.service.measure.get_localized_name( customer.locale_language()) self.hours = self.service.hours else: self.name = str(service_id) self.category = "" self.measure = "" self.hours = 1 self.price = tariff.service_price(service_id) self.service_id = service_id self.resources = {}
def __init__(self, service_usage, customer, tariff): self.currency = tariff.currency service_id, tariff_id, total_cost, total_usage_volume = service_usage service = Service.get_by_id(service_id) if service: self.name = service.get_localized_name(customer.locale_language()) self.category = service.category.get_localized_name( customer.locale_language()) self.measure = service.measure.get_localized_name( customer.locale_language()) self.hours = service.hours else: self.name = str(service_id) self.category = "" self.measure = "" self.hours = 1 self.total_cost = total_cost or Decimal(0) self.total_usage_volume = total_usage_volume or 0 self.price = tariff.service_price(service_id) or Decimal(0) self.service_id = service_id
def test_for_nonexistent_flavor(self): """ Tests that transformer doesn't stop when flavor.name isn't in database and creates fake entry in DB for that flavor. """ state = [{ 'timestamp': testdata.t0, 'counter_volume': states['active'], 'metadata': { 'flavor.name': testdata.flavor } }, { 'timestamp': testdata.t0_30, 'counter_volume': states['active'], 'metadata': { 'flavor.name': testdata.fake_flavor } }, { 'timestamp': testdata.t1, 'counter_volume': states['active'], 'metadata': { 'flavor.name': testdata.fake_flavor } }] with mock.patch( 'os_interfaces.openstack_wrapper.openstack.get_nova_flavor', mock.MagicMock(side_effect=self.create_flavor_mock)): result = self._run_transform(state) result.sort(key=attrgetter("service_id")) flavor = Service.get_by_id(result[1].service_id).flavor self.assertEqual(flavor.flavor_id, testdata.fake_flavor) self.assertEqual(openstack.get_nova_flavor.call_count, 1) self.assertEqual(openstack.create_flavor.call_count, 10) self.assertEqual(result[1].end - result[1].start, datetime.timedelta(minutes=30, seconds=-1))
def service(self): # we can't do it by relationship, because some services # can be fixed services which are configured from config file return Service.get_by_id(self.service_id)
def display(self, short=True): service = Service.get_by_id(self.service_id) return {"service": service.display(short), "price": decimal_to_string(self.price), "need_changing": self.need_changing}