Merge "Include windows vm usage in quotation"
This commit is contained in:
commit
09bddd5cdf
@ -14,7 +14,9 @@
|
||||
# limitations under the License.
|
||||
|
||||
import collections
|
||||
import copy
|
||||
from decimal import Decimal
|
||||
import itertools
|
||||
import json
|
||||
import re
|
||||
|
||||
@ -372,6 +374,19 @@ class OdooDriver(driver.BaseDriver):
|
||||
|
||||
return price
|
||||
|
||||
def _get_entry_info(self, entry, resources_info, service_mapping):
|
||||
service_name = entry.get('service')
|
||||
volume = entry.get('volume')
|
||||
unit = entry.get('unit')
|
||||
res_id = entry.get('resource_id')
|
||||
resource = resources_info.get(res_id, {})
|
||||
# resource_type is the type defined in meter_mappings.yml.
|
||||
resource_type = resource.get('type')
|
||||
service_type = service_mapping.get(service_name, resource_type)
|
||||
|
||||
return (service_name, service_type, volume, unit, resource,
|
||||
resource_type)
|
||||
|
||||
def get_quotations(self, region, project_id, measurements=[], resources=[],
|
||||
detailed=False):
|
||||
"""Get current month quotation.
|
||||
@ -401,7 +416,12 @@ class OdooDriver(driver.BaseDriver):
|
||||
cost_details = {}
|
||||
|
||||
odoo_region = self.region_mapping.get(region, region).upper()
|
||||
resources = {row.id: json.loads(row.info) for row in resources}
|
||||
|
||||
resources_info = {}
|
||||
for row in resources:
|
||||
info = json.loads(row.info)
|
||||
info.update({'id': row.id})
|
||||
resources_info[row.id] = info
|
||||
|
||||
# NOTE(flwang): For most of the cases of Distil API, the request comes
|
||||
# from billing panel. Billing panel sends 1 API call for /invoices and
|
||||
@ -411,15 +431,25 @@ class OdooDriver(driver.BaseDriver):
|
||||
products = self.get_products()[region]
|
||||
service_mapping = self._get_service_mapping(products)
|
||||
|
||||
# Find windows VM usage entries
|
||||
windows_vm_entries = []
|
||||
for entry in measurements:
|
||||
service_name = entry.get('service')
|
||||
volume = entry.get('volume')
|
||||
unit = entry.get('unit')
|
||||
res_id = entry.get('resource_id')
|
||||
(service_name, service_type, _, _, resource,
|
||||
resource_type) = self._get_entry_info(entry, resources_info,
|
||||
service_mapping)
|
||||
|
||||
# resource_type is the type defined in meter_mappings.yml.
|
||||
resource_type = resources[res_id]['type']
|
||||
service_type = service_mapping.get(service_name, resource_type)
|
||||
if (service_type == COMPUTE_CATEGORY
|
||||
and resource_type == 'Virtual Machine'
|
||||
and resource.get('os_distro') == 'windows'):
|
||||
new_entry = copy.deepcopy(entry)
|
||||
setattr(new_entry, 'service', '%s-windows' % service_name)
|
||||
windows_vm_entries.append(new_entry)
|
||||
|
||||
for entry in itertools.chain(measurements, windows_vm_entries):
|
||||
(service_name, service_type, volume, unit, resource,
|
||||
resource_type) = self._get_entry_info(entry, resources_info,
|
||||
service_mapping)
|
||||
res_id = resource['id']
|
||||
|
||||
if service_type not in cost_details:
|
||||
cost_details[service_type] = {
|
||||
@ -436,10 +466,10 @@ class OdooDriver(driver.BaseDriver):
|
||||
price_spec = price_mapping[service_name]
|
||||
|
||||
# Convert volume according to unit in price definition.
|
||||
volume = float(general.convert_to(volume, unit,
|
||||
price_spec['unit']))
|
||||
cost = (round(volume * price_spec['rate'],
|
||||
constants.PRICE_DIGITS)
|
||||
volume = float(
|
||||
general.convert_to(volume, unit, price_spec['unit'])
|
||||
)
|
||||
cost = (round(volume * price_spec['rate'], constants.PRICE_DIGITS)
|
||||
if price_spec['rate'] else 0)
|
||||
|
||||
total_cost += cost
|
||||
@ -455,7 +485,7 @@ class OdooDriver(driver.BaseDriver):
|
||||
odoo_service_name
|
||||
].append(
|
||||
{
|
||||
"resource_name": resources[res_id].get('name', ''),
|
||||
"resource_name": resource.get('name', ''),
|
||||
"resource_id": res_id,
|
||||
"cost": cost,
|
||||
"quantity": round(volume, 3),
|
||||
@ -465,8 +495,10 @@ class OdooDriver(driver.BaseDriver):
|
||||
}
|
||||
)
|
||||
|
||||
result = {'total_cost': round(float(total_cost),
|
||||
constants.PRICE_DIGITS)}
|
||||
result = {
|
||||
'total_cost': round(float(total_cost), constants.PRICE_DIGITS)
|
||||
}
|
||||
|
||||
if detailed:
|
||||
result.update({'details': cost_details})
|
||||
|
||||
|
@ -399,6 +399,116 @@ class TestOdooDriver(base.DistilTestCase):
|
||||
quotations
|
||||
)
|
||||
|
||||
@mock.patch('odoorpc.ODOO')
|
||||
@mock.patch('distil.erp.drivers.odoo.OdooDriver.get_products')
|
||||
def test_get_quotations_with_details_windows_vm(self, mock_get_products,
|
||||
mock_odoo):
|
||||
mock_get_products.return_value = {
|
||||
'nz_1': {
|
||||
'Compute': [
|
||||
{
|
||||
'name': 'c1.c2r16', 'description': 'c1.c2r16',
|
||||
'rate': 0.01, 'unit': 'hour'
|
||||
},
|
||||
{
|
||||
'name': 'c1.c2r16-windows',
|
||||
'description': 'c1.c2r16-windows',
|
||||
'rate': 0.02, 'unit': 'hour'
|
||||
}
|
||||
],
|
||||
'Block Storage': [
|
||||
{
|
||||
'name': 'b1.standard', 'description': 'b1.standard',
|
||||
'rate': 0.02, 'unit': 'gigabyte'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
class Resource(object):
|
||||
def __init__(self, id, info):
|
||||
self.id = id
|
||||
self.info = info
|
||||
|
||||
resources = [
|
||||
Resource(1, '{"name": "volume1", "type": "Volume"}'),
|
||||
Resource(
|
||||
2,
|
||||
'{"name": "instance2", "type": "Virtual Machine", '
|
||||
'"os_distro": "windows"}'
|
||||
)
|
||||
]
|
||||
|
||||
class Usage(object):
|
||||
def __init__(self, service, resource_id, volume, unit):
|
||||
self.service = service
|
||||
self.resource_id = resource_id
|
||||
self.volume = volume
|
||||
self.unit = unit
|
||||
|
||||
def get(self, attr):
|
||||
return getattr(self, attr)
|
||||
|
||||
usage = [
|
||||
Usage('b1.standard', 1, 1024 * 1024 * 1024, 'byte'),
|
||||
Usage('c1.c2r16', 2, 3600, 'second')
|
||||
]
|
||||
|
||||
odoodriver = odoo.OdooDriver(self.conf)
|
||||
quotations = odoodriver.get_quotations(
|
||||
'nz_1', 'fake_id', measurements=usage, resources=resources,
|
||||
detailed=True
|
||||
)
|
||||
|
||||
self.assertDictEqual(
|
||||
{
|
||||
'total_cost': 0.05,
|
||||
'details': {
|
||||
'Compute': {
|
||||
'total_cost': 0.03,
|
||||
'breakdown': {
|
||||
'NZ-1.c1.c2r16': [
|
||||
{
|
||||
"resource_name": "instance2",
|
||||
"resource_id": 2,
|
||||
"cost": 0.01,
|
||||
"quantity": 1.0,
|
||||
"rate": 0.01,
|
||||
"unit": "hour",
|
||||
}
|
||||
],
|
||||
'NZ-1.c1.c2r16-windows': [
|
||||
{
|
||||
"resource_name": "instance2",
|
||||
"resource_id": 2,
|
||||
"cost": 0.02,
|
||||
"quantity": 1.0,
|
||||
"rate": 0.02,
|
||||
"unit": "hour",
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
'Block Storage': {
|
||||
'total_cost': 0.02,
|
||||
'breakdown': {
|
||||
'NZ-1.b1.standard': [
|
||||
{
|
||||
"resource_name": "volume1",
|
||||
"resource_id": 1,
|
||||
"cost": 0.02,
|
||||
"quantity": 1.0,
|
||||
"rate": 0.02,
|
||||
"unit": "gigabyte",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
quotations
|
||||
)
|
||||
|
||||
@mock.patch('odoorpc.ODOO')
|
||||
def test_get_credits(self, mock_odoo):
|
||||
fake_credits = [{'create_uid': [182, 'OpenStack Testing'],
|
||||
|
Loading…
x
Reference in New Issue
Block a user