Merge "Include windows vm usage in quotation"

This commit is contained in:
Jenkins 2017-10-10 01:33:05 +00:00 committed by Gerrit Code Review
commit 09bddd5cdf
2 changed files with 157 additions and 15 deletions

View File

@ -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})

View File

@ -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'],