Fix an issue with product naming and swift policy names

Change-Id: Ib05c9c0302189c3d28ee10a6b789b8588d5a9d8c
This commit is contained in:
Adrian Turjak 2019-12-13 09:49:00 +13:00
parent 1d0a81a1dd
commit bdcb202736
3 changed files with 89 additions and 43 deletions

View File

@ -90,12 +90,6 @@ ODOO_OPTS = [
help='Region name mappings between Keystone and Odoo. For ' help='Region name mappings between Keystone and Odoo. For '
'example, ' 'example, '
'region_mapping=region1:RegionOne,region2:RegionTwo'), 'region_mapping=region1:RegionOne,region2:RegionTwo'),
cfg.StrOpt('object_storage_product_name',
default='NZ.o1.standard',
help='Product name in Odoo for object storage.'),
cfg.StrOpt('object_storage_service_name',
default='o1.standard',
help='Service name for object storage.'),
cfg.ListOpt('extra_product_category_list', cfg.ListOpt('extra_product_category_list',
default=[], default=[],
help='Additional product categories which should be easily ' help='Additional product categories which should be easily '

View File

@ -157,41 +157,59 @@ class OdooDriver(driver.BaseDriver):
prices[actual_region][category.lower()].append( prices[actual_region][category.lower()].append(
{'name': name, {'name': name,
'full_name': product['name_template'],
'rate': rate, 'rate': rate,
'unit': unit, 'unit': unit,
'description': desc} 'description': desc}
) )
# Handle object storage product that does not belong to any # Handle object storage products
# region in odoo. c = self.category.search([('name', '=', OBJECTSTORAGE_CATEGORY)])
obj_p_name = self.conf.odoo.object_storage_product_name product_ids = self.product.search([('categ_id', 'in', c),
obj_s_name = self.conf.odoo.object_storage_service_name ('sale_ok', '=', True),
('active', '=', True)])
products = self.product.read(product_ids, fields=product_fields)
obj_pids = self.product.search( for product in products:
[('name_template', '=', obj_p_name), product_region = None
('sale_ok', '=', True), for region in odoo_regions:
('active', '=', True)] if region.upper() in product['name_template']:
) product_region = region
if len(obj_pids) > 0: category = product['categ_id'][1].split('/')[-1].strip()
obj_p = self.product.read(obj_pids[0],
fields=["lst_price", "default_code", name = product['name_template'].lower()
"description"])
self.product_category_mapping[obj_pids[0]] = \ rate = round(product['lst_price'], constants.RATE_DIGITS)
OBJECTSTORAGE_CATEGORY # NOTE(flwang): default_code is Internal Reference on
for region in regions: # Odoo GUI
# Ensure returned region name is same with what user see unit = product['default_code']
# from Keystone. desc = product['description']
self.product_unit_mapping[product['id']] = unit
product_dict = {
'name': name,
'full_name': product['name_template'],
'rate': rate,
'unit': unit,
'description': desc
}
if product_region:
# add it to just the one region
actual_region = self.reverse_region_mapping.get( actual_region = self.reverse_region_mapping.get(
region, region) product_region, product_region)
prices[actual_region]['object storage'].append( prices[actual_region][category.lower()].append(
{'name': obj_s_name, product_dict)
'rate': round(obj_p["lst_price"], else:
constants.RATE_DIGITS), # add it to all regions
'unit': obj_p["default_code"], for region in odoo_regions:
'description': obj_p["description"]} actual_region = self.reverse_region_mapping.get(
) region, region)
prices[actual_region][category.lower()].append(
product_dict)
except odoorpc.error.Error as e: except odoorpc.error.Error as e:
LOG.exception(e) LOG.exception(e)
return {} return {}
@ -392,26 +410,52 @@ class OdooDriver(driver.BaseDriver):
"""Get service price information from price definitions.""" """Get service price information from price definitions."""
price = {'service_name': service_name} price = {'service_name': service_name}
# NOTE(adriant): We do this to handle the object storage policy
# name to product translation
formatted_name = service_name.lower().replace("--", ".")
if service_type in products: if service_type in products:
for s in products[service_type]: for s in products[service_type]:
if s['name'] == service_name: if s['name'] == formatted_name:
price.update({'rate': s['rate'], 'unit': s['unit']}) price.update({
'rate': s['rate'], 'unit': s['unit'],
'product_name': s['full_name']})
break break
else: else:
found = False found = False
for category, services in products.items(): for category, services in products.items():
for s in services: for s in services:
if s['name'] == service_name: if s['name'] == formatted_name:
price.update({'rate': s['rate'], 'unit': s['unit']}) price.update({
'rate': s['rate'], 'unit': s['unit'],
'product_name': s['full_name']})
found = True found = True
break break
if not found:
for category, services in products.items():
for s in services:
# NOTE(adriant): this will find a partial match like:
# 'o1.standard' in 'NZ.o1.standard'
if formatted_name in s['name']:
price.update({
'rate': s['rate'], 'unit': s['unit'],
'product_name': s['full_name']})
found = True
break
if not found: if not found:
raise exceptions.NotFoundException( raise exceptions.NotFoundException(
'Price not found, service name: %s, service type: %s' % 'Price not found, service name: %s, service type: %s' %
(service_name, service_type) (formatted_name, service_type)
) )
if 'unit' in price and not price['unit']:
raise exceptions.ERPException(
"Product: %s is missing 'unit' definition." %
formatted_name
)
return price return price
def _get_entry_info(self, entry, resources_info, service_mapping): def _get_entry_info(self, entry, resources_info, service_mapping):
@ -455,8 +499,6 @@ class OdooDriver(driver.BaseDriver):
price_mapping = {} price_mapping = {}
cost_details = {} cost_details = {}
odoo_region = self.region_mapping.get(region, region).upper()
resources_info = {} resources_info = {}
for row in resources: for row in resources:
info = json.loads(row.info) info = json.loads(row.info)
@ -517,14 +559,12 @@ class OdooDriver(driver.BaseDriver):
total_cost += cost total_cost += cost
if detailed: if detailed:
odoo_service_name = "%s.%s" % (odoo_region, service_name)
cost_details[service_type]['total_cost'] = round( cost_details[service_type]['total_cost'] = round(
(cost_details[service_type]['total_cost'] + cost), (cost_details[service_type]['total_cost'] + cost),
constants.PRICE_DIGITS constants.PRICE_DIGITS
) )
cost_details[service_type]['breakdown'][ cost_details[service_type]['breakdown'][
odoo_service_name price_spec['product_name']
].append( ].append(
{ {
"resource_name": resource.get('name', ''), "resource_name": resource.get('name', ''),

View File

@ -58,7 +58,7 @@ class TestOdooDriver(base.DistilTestCase):
def test_get_products(self, mock_odoo): def test_get_products(self, mock_odoo):
odoodriver = odoo.OdooDriver(self.conf) odoodriver = odoo.OdooDriver(self.conf)
odoodriver.product.search.return_value = [] odoodriver.product.search.return_value = []
odoodriver.product.read.return_value = PRODUCTS odoodriver.product.read.side_effect = [PRODUCTS, []]
products = odoodriver.get_products(regions=['nz_1']) products = odoodriver.get_products(regions=['nz_1'])
@ -68,14 +68,17 @@ class TestOdooDriver(base.DistilTestCase):
'block storage': [{'description': 'Block storage', 'block storage': [{'description': 'Block storage',
'rate': 0.00035, 'rate': 0.00035,
'name': 'b1.volume', 'name': 'b1.volume',
'full_name': 'NZ-1.b1.volume',
'unit': 'hour'}], 'unit': 'hour'}],
'compute': [{'description': '1 CPU, 1GB RAM', 'compute': [{'description': '1 CPU, 1GB RAM',
'rate': 0.00015, 'rate': 0.00015,
'name': 'c1.c1r1', 'name': 'c1.c1r1',
'full_name': 'NZ-1.c1.c1r1',
'unit': 'hour'}], 'unit': 'hour'}],
'network': [{'description': 'Router', 'network': [{'description': 'Router',
'rate': 0.00025, 'rate': 0.00025,
'name': 'n1.router', 'name': 'n1.router',
'full_name': 'NZ-1.n1.router',
'unit': 'hour'}] 'unit': 'hour'}]
} }
}, },
@ -270,12 +273,14 @@ class TestOdooDriver(base.DistilTestCase):
'Compute': [ 'Compute': [
{ {
'name': 'c1.c2r16', 'description': 'c1.c2r16', 'name': 'c1.c2r16', 'description': 'c1.c2r16',
'full_name': 'NZ-1.c1.c2r16',
'rate': 0.01, 'unit': 'hour' 'rate': 0.01, 'unit': 'hour'
} }
], ],
'Block Storage': [ 'Block Storage': [
{ {
'name': 'b1.standard', 'description': 'b1.standard', 'name': 'b1.standard', 'description': 'b1.standard',
'full_name': 'NZ-1.b1.standard',
'rate': 0.02, 'unit': 'gigabyte' 'rate': 0.02, 'unit': 'gigabyte'
} }
] ]
@ -326,12 +331,14 @@ class TestOdooDriver(base.DistilTestCase):
'Compute': [ 'Compute': [
{ {
'name': 'c1.c2r16', 'description': 'c1.c2r16', 'name': 'c1.c2r16', 'description': 'c1.c2r16',
'full_name': 'NZ-1.c1.c2r16',
'rate': 0.01, 'unit': 'hour' 'rate': 0.01, 'unit': 'hour'
} }
], ],
'Block Storage': [ 'Block Storage': [
{ {
'name': 'b1.standard', 'description': 'b1.standard', 'name': 'b1.standard', 'description': 'b1.standard',
'full_name': 'NZ-1.b1.standard',
'rate': 0.02, 'unit': 'gigabyte' 'rate': 0.02, 'unit': 'gigabyte'
} }
] ]
@ -417,19 +424,23 @@ class TestOdooDriver(base.DistilTestCase):
'Compute': [ 'Compute': [
{ {
'name': 'c1.c2r16', 'description': 'c1.c2r16', 'name': 'c1.c2r16', 'description': 'c1.c2r16',
'full_name': 'NZ-1.c1.c2r16',
'rate': 0.01, 'unit': 'hour' 'rate': 0.01, 'unit': 'hour'
}, },
{ {
'name': 'c1.c4r32', 'description': 'c1.c4r32', 'name': 'c1.c4r32', 'description': 'c1.c4r32',
'full_name': 'NZ-1.c1.c4r32',
'rate': 0.04, 'unit': 'hour' 'rate': 0.04, 'unit': 'hour'
}, },
{ {
'name': 'c1.c2r16-windows', 'name': 'c1.c2r16-windows',
'full_name': 'NZ-1.c1.c2r16-windows',
'description': 'c1.c2r16-windows', 'description': 'c1.c2r16-windows',
'rate': 0.02, 'unit': 'hour' 'rate': 0.02, 'unit': 'hour'
}, },
{ {
'name': 'c1.c4r32-sql-server-standard-windows', 'name': 'c1.c4r32-sql-server-standard-windows',
'full_name': 'NZ-1.c1.c4r32-sql-server-standard-windows',
'description': 'c1.c4r32-sql-server-standard-windows', 'description': 'c1.c4r32-sql-server-standard-windows',
'rate': 0.04, 'unit': 'hour' 'rate': 0.04, 'unit': 'hour'
} }
@ -437,6 +448,7 @@ class TestOdooDriver(base.DistilTestCase):
'Block Storage': [ 'Block Storage': [
{ {
'name': 'b1.standard', 'description': 'b1.standard', 'name': 'b1.standard', 'description': 'b1.standard',
'full_name': 'NZ-1.b1.standard',
'rate': 0.02, 'unit': 'gigabyte' 'rate': 0.02, 'unit': 'gigabyte'
} }
] ]