Update Error Types, Log Heat Errors

Some error types were updated to recommendations
which better fit their use cases, providing
better information. Heat errors are now
logged when seen in rds status checking,
to make debugging of heat errors such
as stack validation more readily apparent.

Change-Id: Ifd11edaead65bf2fcd6d828e397bf41ba0816b63
This commit is contained in:
jh629g 2020-11-05 14:04:57 -06:00 committed by Jeremy Houser
parent 64bd786367
commit baecd4b567
13 changed files with 92 additions and 89 deletions

View File

@ -38,7 +38,7 @@ class NotAllowedError(wsme.exc.ClientSideError):
class NoContentError(wsme.exc.ClientSideError):
def __init__(self, message="Main json body empty", status_code=204):
def __init__(self, message="Main json body empty", status_code=406):
self.message = message
self.status_code = status_code
super().__init__(msg=message, status_code=status_code)

View File

@ -2,7 +2,8 @@ from pecan import rest, request, response
from wsmeext.pecan import wsexpose
from orm.common.orm_common.utils import api_error_utils as err_utils
from orm.common.orm_common.utils.error_base import ErrorStatus, NotAllowedError, NotFoundError
from orm.common.orm_common.utils.error_base import (
ConflictError, ErrorStatus, NotAllowedError, NotFoundError)
from orm.common.orm_common.utils import utils
from orm.services.customer_manager.cms_rest.controllers.v1.orm.customer.enabled import EnabledController
from orm.services.customer_manager.cms_rest.controllers.v1.orm.customer.metadata import MetadataController
@ -72,7 +73,7 @@ class CustomerController(rest.RestController):
event_details=event_details)
return result
except ErrorStatus as exception:
except (ConflictError, ErrorStatus) as exception:
LOG.log_exception("CustomerController - Failed to CreateCustomer", exception)
raise err_utils.get_error(request.transaction_id,
message=str(exception),

View File

@ -8,8 +8,8 @@ from orm.common.orm_common.utils.cross_api_utils import (get_regions_of_group,
from orm.services.customer_manager.cms_rest.data.data_manager import DataManager
from orm.services.customer_manager.cms_rest.data.sql_alchemy.models import CustomerMetadata
from orm.services.customer_manager.cms_rest.logger import get_logger
from orm.common.orm_common.utils.error_base import (ConflictError, ErrorStatus,
NotFoundError, NotAllowedError)
from orm.common.orm_common.utils.error_base import (
ConflictError, ErrorStatus, InputValueError, NotFoundError, NotAllowedError)
from orm.services.customer_manager.cms_rest.model.Models import (CustomerResultWrapper, CustomerSummary,
CustomerSummaryResponse,
RegionResultWrapper, UserResultWrapper)
@ -22,10 +22,10 @@ class CustomerLogic(object):
def build_full_customer(self, customer, uuid, datamanager):
cust_metadata = CustomerMetadata()
if any(char in ":" for char in customer.name):
raise NotAllowedError("Customer Name does not allow colon(:)")
raise InputValueError("Customer Name does not allow colon(:)")
if customer.name.strip() == '':
raise NotAllowedError("Customer Name can not be blank")
raise InputValueError("Customer Name can not be blank")
if not customer.customerDomain:
customer.customerDomain = conf.rds.customer_domain

View File

@ -125,7 +125,7 @@ class RdsProxy(object):
content = resp.json()
return content
raise ErrorStatus(resp.status_code, content)
raise ErrorStatus(content, resp.status_code)
@staticmethod
def send_group_dict(group_dict, transaction_id, method):
@ -206,4 +206,4 @@ class RdsProxy(object):
content = resp.json()
return content
raise ErrorStatus(resp.status_code, content)
raise ErrorStatus(content, resp.status_code)

View File

@ -1,6 +1,6 @@
from orm.common.orm_common.injector import injector
from orm.common.orm_common.utils import api_error_utils as err_utils
from orm.common.orm_common.utils.error_base import ErrorStatus
from orm.common.orm_common.utils.error_base import ErrorStatus, NotFoundError
from orm.services.flavor_manager.fms_rest.data.wsme.models import TenantWrapper
from orm.services.flavor_manager.fms_rest.logger import get_logger
from orm.services.flavor_manager.fms_rest.utils import authentication
@ -69,7 +69,7 @@ class TenantController(rest.RestController):
request.headers, flavor_id,
event_details=event_details)
except ErrorStatus as exception:
except (ErrorStatus, NotFoundError) as exception:
LOG.log_exception("TenantController - Failed to delete tenant", str(exception))
raise err_utils.get_error(request.transaction_id,
message=str(exception),

View File

@ -3,7 +3,7 @@ import wsme
from orm.common.orm_common.utils.cross_api_utils import (set_utils_conf,
get_regions_of_group,
validate_description)
from orm.common.orm_common.utils.error_base import ErrorStatus
from orm.common.orm_common.utils.error_base import ErrorStatus, InputValueError
from orm.services.flavor_manager.fms_rest.data.sql_alchemy import db_models
from orm.services.flavor_manager.fms_rest.data.wsme.model import Model
@ -266,8 +266,8 @@ class Flavor(Model):
invalid_opt_vals = [x for x in option_values if (x.lower()
not in ['true', 'false'])]
if invalid_opt_vals:
raise ErrorStatus("All flavor option values must have"
" a value of 'true' or 'false'")
raise InputValueError("All flavor option values must have"
" a value of 'true' or 'false'")
# validate series and set flavor vcpu and vram limits
requested_numa = [n for n in valid_numa if n in
@ -287,69 +287,69 @@ class Flavor(Model):
isValid = validate_description(self.description)
if not isValid:
raise ErrorStatus("Flavor description does not allow"
" special characters: only dashes,"
" commas, and period allowed.")
raise InputValueError("Flavor description does not allow"
" special characters: only dashes,"
" commas, and period allowed.")
if not self.ram.isdigit():
raise ErrorStatus("ram must be a number")
raise InputValueError("ram must be a number")
if not self.vcpus.isdigit():
raise ErrorStatus("vcpus must be a number")
raise InputValueError("vcpus must be a number")
if not self.validInt(self.disk):
raise ErrorStatus("disk must be a number")
raise InputValueError("disk must be a number")
if not self.swap.isdigit():
raise ErrorStatus("swap must be a number")
raise InputValueError("swap must be a number")
if self.ephemeral and not self.ephemeral.isdigit():
raise ErrorStatus("ephemeral must be a number")
raise InputValueError("ephemeral must be a number")
if int(self.ram) not in list(range(1024, vram_limit + 1, 1024)):
raise ErrorStatus("ram value % is out of range. Expected range"
" is 1024(1GB)-% (% GB) and must be a"
" multiple of 1024".format(
self.ram,
vram_limit,
vram_limit // 1024))
raise InputValueError("ram value % is out of range. Expected range"
" is 1024(1GB)-% (% GB) and must be a"
" multiple of 1024".format(
self.ram,
vram_limit,
vram_limit // 1024))
if int(self.vcpus) not in list(range(1, vcpu_limit + 1)):
raise ErrorStatus("vcpus value % is out of range. Expected"
"range is 1-%" % (str(self.vcpus), str(vcpu_limit)))
raise InputValueError("vcpus value % is out of range. Expected"
" range is 1-%" % (str(self.vcpus), str(vcpu_limit)))
if int(self.disk) < 0:
raise ErrorStatus("disk cannot be less than zero")
raise InputValueError("disk cannot be less than zero")
if not self.ephemeral:
self.ephemeral = "0"
elif (self.ephemeral
and int(self.ephemeral) not in
list(range(0, ephemeral_limit + 1))):
raise ErrorStatus("ephemeral value {} is out of range. Expected"
" range is 0-{} ({}TB)".format(
self.ephemeral,
ephemeral_limit,
ephemeral_limit // 1000))
raise InputValueError("ephemeral value {} is out of range. Expected"
" range is 0-{} ({}TB)".format(
self.ephemeral,
ephemeral_limit,
ephemeral_limit // 1000))
if int(self.swap) not in list(range(0, swap_file_limit + 1, 1024)):
raise ErrorStatus("Swap value {} is out of range. Expected"
" range is 0-{}({}GB) and must be a"
" multiple of 1024".format(
self.swap,
swap_file_limit,
swap_file_limit // 1024))
raise InputValueError("Swap value {} is out of range. Expected"
" range is 0-{}({}GB) and must be a"
" multiple of 1024".format(
self.swap,
swap_file_limit,
swap_file_limit // 1024))
except ValueError:
raise ErrorStatus("Ram, vcpus, disk, ephemeral and swap must"
" be integers")
raise InputValueError("Ram, vcpus, disk, ephemeral and swap must"
" be integers")
for symbol, value in self.extra_specs.items():
if symbol == 'numa_override' and value not in valid_numa:
raise ErrorStatus("Invalid value. numa_override possible"
" values: " + str(valid_numa))
raise InputValueError("Invalid value. numa_override possible"
" values: " + str(valid_numa))
if symbol == 'vlan_category' and value not in valid_vnf:
raise ErrorStatus("Invalid value. vlan_category possible"
" values: " + str(valid_vnf))
raise InputValueError("Invalid value. vlan_category possible"
" values: " + str(valid_vnf))
# region type can be group only in create flavor!!
if not context == "create":
for region in self.regions:
if region.type == "group":
raise ErrorStatus("region type \'group\' is invalid in"
" this action, \'group\' can be only"
" in create flavor action")
raise InputValueError("region type \'group\' is invalid in"
" this action, \'group\' can be only"
" in create flavor action")
def to_db_model(self):
flavor = db_models.Flavor()

View File

@ -7,7 +7,8 @@ from orm.services.flavor_manager.fms_rest.data.wsme.models import (
TenantWrapper)
from orm.services.flavor_manager.fms_rest.logger import get_logger
from orm.common.orm_common.utils.error_base import (
ConflictError, EntityNotFound, ErrorStatus, NotAllowedError, NotFoundError)
ConflictError, EntityNotFound, ErrorStatus, InputValueError,
NotAllowedError, NotFoundError)
from orm.common.orm_common.injector import injector
from orm.common.orm_common.utils import utils
@ -265,10 +266,10 @@ def add_regions(flavor_uuid, regions, transaction_id):
flvr_tenant_list, flvr_region_list = [], []
for region in regions.regions:
if region.name == '' or region.name.isspace():
raise ErrorStatus('Cannot add region with an empty name')
raise InputValueError('Cannot add region with an empty name')
if region.type == "group":
raise ErrorStatus("Adding \'group\' type region is supported"
" only when creating a flavor")
raise InputValueError("Adding \'group\' type region is supported"
" only when creating a flavor")
db_region = FlavorRegion(region_name=region.name,
region_type='single')
sql_flavor.add_region(db_region)
@ -416,7 +417,7 @@ def add_tenants(flavor_uuid, tenants, transaction_id):
raise NotFoundError('Flavor id {0} not found'.format(flavor_uuid))
if sql_flavor.visibility == "public":
raise NotAllowedError('Cannot add tenant to a public flavor')
raise InputValueError('Cannot add tenant to a public flavor')
existing_region_list = sql_flavor.get_existing_region_names()

View File

@ -4,7 +4,7 @@ from orm.common.orm_common.injector import injector
from orm.common.orm_common.utils import utils
from orm.services.image_manager.ims.logger import get_logger
from orm.common.orm_common.utils.error_base import \
ErrorStatus, NotFoundError
ConflictError, ErrorStatus, NotAllowedError, NotFoundError
from orm.services.image_manager.ims.persistency.sql_alchemy.db_models import \
ImageCustomer, ImageRegion
from orm.services.image_manager.ims.persistency.wsme.models import (
@ -48,10 +48,8 @@ def create_image(image_wrapper, image_uuid, transaction_id):
except oslo_db.exception.DBDuplicateEntry as exception:
utils.delete_uuid(image_uuid)
raise ErrorStatus(
"Image name '{}' already exists".format(
image_wrapper.image.name),
409)
raise ConflictError("Image name '{}' already exists".format(
image_wrapper.image.name))
except Exception as exp:
LOG.log_exception("ImageLogic - Failed to CreateImage", exp)
@ -144,10 +142,9 @@ def delete_image_by_uuid(image_uuid, transaction_id):
image_existing_region_names = sql_image.get_existing_region_names()
if len(image_existing_region_names) > 0:
# Do not delete an image that still has region(s)
raise ErrorStatus("Cannot delete a image with regions. "
"Please delete the regions first and then "
"delete the image.",
405)
raise NotAllowedError("Cannot delete an image with regions. "
"Please delete the regions first and then "
"delete the image.")
# Get status from resource status table
uuid = [sql_image.id]
@ -387,7 +384,7 @@ def replace_customers(image_uuid, customers, transaction_id):
except Exception as exp:
if 'conflicts with persistent instance' in str(exp) or \
'Duplicate entry' in str(exp):
raise ErrorStatus("Duplicate Customer for Image", 409)
raise ConflictError("Duplicate Customer for Image")
LOG.log_exception("ImageLogic - Failed to add Customers", exp)
datamanager.rollback()
raise

View File

@ -1,7 +1,8 @@
import logging
from orm.common.orm_common.utils import api_error_utils as err_utils
from orm.common.orm_common.utils import error_base
from orm.common.orm_common.utils.error_base import \
ErrorStatus, InputValueError
from orm.common.orm_common.utils import utils
from orm.services.region_manager.rms.services import services as RegionService
from orm.services.region_manager.rms.utils import authentication
@ -51,7 +52,7 @@ class RegionStatusController(rest.RestController):
if new_status.status not in allowed_status:
logger.error("Invalid status. Region status "
"must be one of {}".format(allowed_status))
raise error_base.InputValueError(
raise InputValueError(
message="Invalid status. Region status "
"must be one of {}".format(allowed_status))
@ -72,12 +73,7 @@ class RegionStatusController(rest.RestController):
return RegionStatus(status, link)
except error_base.ErrorStatus as e:
logger.error(e.message)
raise err_utils.get_error(request.transaction_id,
message=e.message,
status_code=e.status_code)
except error_base.InputValueError as e:
except (ErrorStatus, InputValueError) as e:
logger.error(e.message)
raise err_utils.get_error(request.transaction_id,
message=e.message,

View File

@ -141,7 +141,13 @@ class Status(rest.RestController):
and status_input.rds_listener.resource_extra_metadata != wsme.Unset:
data_to_save['resource_extra_metadata'] =\
status_input.rds_listener.resource_extra_metadata.to_dict()
if status_input.rds_listener.status == "Error":
logger.error(("{} {} is in error status on region {}."
" Error message: {}").format(
status_input.rds_listener.resource_type,
status_input.rds_listener.resource_id,
status_input.rds_listener.region,
status_input.rds_listener.error_msg))
logger.debug("Saving data to database.. data :- %s" % data_to_save)
try:
regionResourceIdStatus.add_status(data_to_save)

View File

@ -1,4 +1,5 @@
from orm.common.orm_common.utils.error_base import ErrorStatus, NotFoundError, NotAllowedError
from orm.common.orm_common.utils.error_base import \
ErrorStatus, InputValueError, NotAllowedError, NotFoundError
from orm.services.customer_manager.cms_rest.data.sql_alchemy import models as sql_models
from orm.services.customer_manager.cms_rest.logic import customer_logic
import orm.services.customer_manager.cms_rest.model.Models as models
@ -127,7 +128,7 @@ class TestCustomerLogic(FunctionalTest):
customer.name = ''
logic = customer_logic.CustomerLogic()
self.assertRaises(NotAllowedError,
self.assertRaises(InputValueError,
logic.create_customer,
customer, 'some_uuid', 'some_trans_id')

View File

@ -1,7 +1,7 @@
from orm.common.orm_common.injector import injector
from orm.common.orm_common.utils import utils
from orm.common.orm_common.utils.error_base import \
ConflictError, ErrorStatus, NotAllowedError, NotFoundError
ConflictError, ErrorStatus, InputValueError, NotAllowedError, NotFoundError
from orm.services.flavor_manager.fms_rest.data.sql_alchemy import db_models
from orm.services.flavor_manager.fms_rest.data.wsme import models
from orm.services.flavor_manager.fms_rest.data.wsme.models import (
@ -85,7 +85,7 @@ class TestFlavorLogic(FunctionalTest):
# Test that flavor validate model works by passing bad swap value
flavor = get_flavor_mock()
flavor.flavor.swap = '1024000'
self.assertRaises(ErrorStatus, flavor_logic.create_flavor,
self.assertRaises(InputValueError, flavor_logic.create_flavor,
flavor, 'uuid', 'transaction')
# Flavor is private - test success
@ -469,10 +469,10 @@ class TestFlavorLogic(FunctionalTest):
'uuid', RegionWrapper([Region(name='test_region')]),
'transaction')
self.assertRaises(ErrorStatus, flavor_logic.add_regions,
self.assertRaises(InputValueError, flavor_logic.add_regions,
'uuid', RegionWrapper([Region(name='')]),
'transaction')
self.assertRaises(ErrorStatus, flavor_logic.add_regions,
self.assertRaises(InputValueError, flavor_logic.add_regions,
'uuid', RegionWrapper([Region(name='test_region', type='group')]),
'transaction')
@ -551,7 +551,7 @@ class TestFlavorLogic(FunctionalTest):
# Flavor is public
error = 5
self.assertRaises(NotAllowedError,
self.assertRaises(InputValueError,
flavor_logic.add_tenants, 'uuid',
TenantWrapper(tenants),
'transaction')

View File

@ -1,4 +1,5 @@
from orm.common.orm_common.utils.error_base import NotFoundError
from orm.common.orm_common.utils.error_base import \
ConflictError, ErrorStatus, NotAllowedError, NotFoundError
from orm.common.orm_common.utils import utils
from orm.services.image_manager.ims.logic import image_logic
from orm.services.image_manager.ims.persistency.sql_alchemy.db_models import Image
@ -89,7 +90,7 @@ class TestImageLogic(FunctionalTest):
try:
image_logic.get_image_by_uuid('te')
except image_logic.NotFoundError as e:
except NotFoundError as e:
self.assertEqual(e.status_code, 404)
@mock.patch.object(utils, 'get_resource_status_from_db')
@ -174,7 +175,7 @@ class TestDeleteImageLogic(FunctionalTest):
_, mock_data_manager = get_data_manager_mock()
mock_di.resolver.unpack.return_value = (mock_data_manager)
self.assertRaises(image_logic.ErrorStatus,
self.assertRaises(NotAllowedError,
image_logic.delete_image_by_uuid,
"image_uuid",
"transaction_id")
@ -506,7 +507,7 @@ class TestDeleteRegion(FunctionalTest):
mock_send_to_rds_if_needed):
rds_proxy, mock_data_manager = get_data_manager_mock(protected=True)
mock_di.resolver.unpack.return_value = mock_data_manager
self.assertRaises(image_logic.ErrorStatus, image_logic.delete_region,
self.assertRaises(ErrorStatus, image_logic.delete_region,
'uuid', mock.MagicMock(), 'transaction', False)
@mock.patch.object(image_logic, 'get_image_by_uuid',
@ -570,7 +571,7 @@ class TestAddCustomers(FunctionalTest):
visibility = 'public'
rds_proxy, mock_data_manager = get_data_manager_mock()
mock_di.resolver.unpack.return_value = mock_data_manager
self.assertRaises(image_logic.ErrorStatus, image_logic.add_customers,
self.assertRaises(ErrorStatus, image_logic.add_customers,
'uuid', mock.MagicMock(),
'transaction')
visibility = 'shared'
@ -587,7 +588,7 @@ class TestAddCustomers(FunctionalTest):
mock_get_image_by_uuid):
rds_proxy, mock_data_manager = get_data_manager_mock()
mock_di.resolver.unpack.return_value = mock_data_manager
self.assertRaises(image_logic.ErrorStatus, image_logic.add_customers,
self.assertRaises(ErrorStatus, image_logic.add_customers,
'uuid', mock.MagicMock(),
'transaction')
@ -661,7 +662,7 @@ class TestReplaceCustomers(FunctionalTest):
mock_get_image_by_uuid):
rds_proxy, mock_data_manager = get_data_manager_mock()
mock_di.resolver.unpack.return_value = mock_data_manager
self.assertRaises(image_logic.ErrorStatus,
self.assertRaises(ConflictError,
image_logic.replace_customers,
'uuid', mock.MagicMock(),
'transaction')