Centralise imports of wsme types

Instead of importing wsme types directly from the wsme packages,
import them from ironic.api.types. This reduces the number of wsme
imports throughout the codebase, and confines much of the future code
changes to the new types.py and a few other files.

Change-Id: I231a1f82915ab9e07c00857aa6210c0764b8ce4b
Story: 1651346
This commit is contained in:
Steve Baker 2020-01-27 12:32:44 +13:00
parent 8a143378cb
commit dffc71287e
29 changed files with 305 additions and 278 deletions

View File

@ -16,8 +16,8 @@ import datetime
import functools
from webob import exc
import wsme
from ironic.api import types as atypes
from ironic.common.i18n import _
@ -39,7 +39,7 @@ class AsDictMixin(object):
return dict((k, _attr_as_pod(getattr(self, k)))
for k in self.fields
if hasattr(self, k)
and getattr(self, k) != wsme.Unset)
and getattr(self, k) != atypes.Unset)
class Base(AsDictMixin):
@ -60,15 +60,15 @@ class Base(AsDictMixin):
for k in self.as_dict():
if k not in except_list:
setattr(self, k, wsme.Unset)
setattr(self, k, atypes.Unset)
class APIBase(Base):
created_at = wsme.wsattr(datetime.datetime, readonly=True)
created_at = atypes.wsattr(datetime.datetime, readonly=True)
"""The time in UTC at which the object is created"""
updated_at = wsme.wsattr(datetime.datetime, readonly=True)
updated_at = atypes.wsattr(datetime.datetime, readonly=True)
"""The time in UTC at which the object is updated"""

View File

@ -13,10 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
from ironic.api import types as atypes
def build_url(resource, resource_args, bookmark=False, base_url=None):
@ -45,7 +44,7 @@ class Link(base.Base):
@staticmethod
def make_link(rel_name, url, resource, resource_args,
bookmark=False, type=wtypes.Unset):
bookmark=False, type=atypes.Unset):
href = build_url(resource, resource_args,
bookmark=bookmark, base_url=url)
return Link(href=href, rel=rel_name, type=type)

View File

@ -18,7 +18,6 @@ from oslo_utils import uuidutils
import pecan
from webob import exc as webob_exc
import wsme
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
@ -28,6 +27,7 @@ from ironic.api.controllers.v1 import notification_utils as notify
from ironic.api.controllers.v1 import types
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import policy
@ -40,7 +40,7 @@ METRICS = metrics_utils.get_metrics_logger(__name__)
def hide_fields_in_newer_versions(obj):
# if requested version is < 1.60, hide owner field
if not api_utils.allow_allocation_owner():
obj.owner = wsme.Unset
obj.owner = atypes.Unset
class Allocation(base.APIBase):
@ -57,36 +57,36 @@ class Allocation(base.APIBase):
extra = {str: types.jsontype}
"""This allocation's meta data"""
node_uuid = wsme.wsattr(types.uuid, readonly=True)
node_uuid = atypes.wsattr(types.uuid, readonly=True)
"""The UUID of the node this allocation belongs to"""
node = wsme.wsattr(str)
node = atypes.wsattr(str)
"""The node to backfill the allocation for (POST only)"""
name = wsme.wsattr(str)
name = atypes.wsattr(str)
"""The logical name for this allocation"""
links = wsme.wsattr([link.Link], readonly=True)
links = atypes.wsattr([link.Link], readonly=True)
"""A list containing a self link and associated allocation links"""
state = wsme.wsattr(str, readonly=True)
state = atypes.wsattr(str, readonly=True)
"""The current state of the allocation"""
last_error = wsme.wsattr(str, readonly=True)
last_error = atypes.wsattr(str, readonly=True)
"""Last error that happened to this allocation"""
resource_class = wsme.wsattr(wtypes.StringType(max_length=80))
resource_class = atypes.wsattr(atypes.StringType(max_length=80))
"""Requested resource class for this allocation"""
owner = wsme.wsattr(str)
owner = atypes.wsattr(str)
"""Owner of allocation"""
# NOTE(dtantsur): candidate_nodes is a list of UUIDs on the database level,
# but the API level also accept names, converting them on fly.
candidate_nodes = wsme.wsattr([str])
candidate_nodes = atypes.wsattr([str])
"""Candidate nodes for this allocation"""
traits = wsme.wsattr([str])
traits = atypes.wsattr([str])
"""Requested traits for the allocation"""
def __init__(self, **kwargs):
@ -100,13 +100,13 @@ class Allocation(base.APIBase):
if not hasattr(self, field):
continue
self.fields.append(field)
setattr(self, field, kwargs.get(field, wtypes.Unset))
setattr(self, field, kwargs.get(field, atypes.Unset))
@staticmethod
def _convert_with_links(allocation, url):
"""Add links to the allocation."""
# This field is only used in POST, never return it.
allocation.node = wsme.Unset
allocation.node = atypes.Unset
allocation.links = [
link.Link.make_link('self', url, 'allocations', allocation.uuid),
link.Link.make_link('bookmark', url, 'allocations',
@ -399,7 +399,7 @@ class AllocationsController(pecan.rest.RestController):
api_utils.validate_trait(trait)
node = None
if allocation.node is not wtypes.Unset:
if allocation.node is not atypes.Unset:
if api_utils.allow_allocation_backfill():
try:
node = api_utils.get_rpc_node(allocation.node)
@ -507,7 +507,7 @@ class AllocationsController(pecan.rest.RestController):
except AttributeError:
# Ignore fields that aren't exposed in the API
continue
if patch_val == wtypes.Unset:
if patch_val == atypes.Unset:
patch_val = None
if rpc_allocation[field] != patch_val:
rpc_allocation[field] = patch_val

View File

@ -15,8 +15,6 @@
from ironic_lib import metrics_utils
from pecan import rest
import wsme
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
@ -24,6 +22,7 @@ from ironic.api.controllers import link
from ironic.api.controllers.v1 import types
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common import policy
from ironic import objects
@ -34,11 +33,11 @@ METRICS = metrics_utils.get_metrics_logger(__name__)
class BIOSSetting(base.APIBase):
"""API representation of a BIOS setting."""
name = wsme.wsattr(str)
name = atypes.wsattr(str)
value = wsme.wsattr(str)
value = atypes.wsattr(str)
links = wsme.wsattr([link.Link], readonly=True)
links = atypes.wsattr([link.Link], readonly=True)
def __init__(self, **kwargs):
self.fields = []
@ -46,7 +45,7 @@ class BIOSSetting(base.APIBase):
for k in fields:
if hasattr(self, k):
self.fields.append(k)
value = kwargs.get(k, wtypes.Unset)
value = kwargs.get(k, atypes.Unset)
setattr(self, k, value)
@staticmethod

View File

@ -20,7 +20,6 @@ from ironic_lib import metrics_utils
from oslo_utils import uuidutils
from pecan import rest
import wsme
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
@ -31,6 +30,7 @@ from ironic.api.controllers.v1 import notification_utils as notify
from ironic.api.controllers.v1 import types
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import policy
@ -53,16 +53,16 @@ class Chassis(base.APIBase):
uuid = types.uuid
"""The UUID of the chassis"""
description = wtypes.StringType(max_length=255)
description = atypes.StringType(max_length=255)
"""The description of the chassis"""
extra = {str: types.jsontype}
"""The metadata of the chassis"""
links = wsme.wsattr([link.Link], readonly=True)
links = atypes.wsattr([link.Link], readonly=True)
"""A list containing a self link and associated chassis links"""
nodes = wsme.wsattr([link.Link], readonly=True)
nodes = atypes.wsattr([link.Link], readonly=True)
"""Links to the collection of nodes contained in this chassis"""
def __init__(self, **kwargs):
@ -72,7 +72,7 @@ class Chassis(base.APIBase):
if not hasattr(self, field):
continue
self.fields.append(field)
setattr(self, field, kwargs.get(field, wtypes.Unset))
setattr(self, field, kwargs.get(field, atypes.Unset))
@staticmethod
def _convert_with_links(chassis, url, fields=None):
@ -336,7 +336,7 @@ class ChassisController(rest.RestController):
except AttributeError:
# Ignore fields that aren't exposed in the API
continue
if patch_val == wtypes.Unset:
if patch_val == atypes.Unset:
patch_val = None
if rpc_chassis[field] != patch_val:
rpc_chassis[field] = patch_val

View File

@ -13,11 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
from ironic.api.controllers import link
from ironic.api import types as atypes
class Collection(base.Base):
@ -40,7 +39,7 @@ class Collection(base.Base):
def get_next(self, limit, url=None, **kwargs):
"""Return a link to the next subset of the collection."""
if not self.has_next(limit):
return wtypes.Unset
return atypes.Unset
resource_url = url or self._type
fields = kwargs.pop('fields', None)

View File

@ -16,8 +16,6 @@ from ironic_lib import metrics_utils
from oslo_log import log
from oslo_utils import timeutils
from pecan import rest
import wsme
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
@ -26,6 +24,7 @@ from ironic.api.controllers.v1 import collection
from ironic.api.controllers.v1 import types
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import policy
@ -42,19 +41,19 @@ _DEFAULT_RETURN_FIELDS = ('hostname', 'conductor_group', 'alive')
class Conductor(base.APIBase):
"""API representation of a bare metal conductor."""
hostname = wsme.wsattr(str)
hostname = atypes.wsattr(str)
"""The hostname for this conductor"""
conductor_group = wsme.wsattr(str)
conductor_group = atypes.wsattr(str)
"""The conductor group this conductor belongs to"""
alive = types.boolean
"""Indicates whether this conductor is considered alive"""
drivers = wsme.wsattr([str])
drivers = atypes.wsattr([str])
"""The drivers enabled on this conductor"""
links = wsme.wsattr([link.Link])
links = atypes.wsattr([link.Link])
"""A list containing a self link and associated conductor links"""
def __init__(self, **kwargs):
@ -69,7 +68,7 @@ class Conductor(base.APIBase):
if not hasattr(self, field):
continue
self.fields.append(field)
setattr(self, field, kwargs.get(field, wtypes.Unset))
setattr(self, field, kwargs.get(field, atypes.Unset))
@staticmethod
def _convert_with_links(conductor, url, fields=None):

View File

@ -22,7 +22,6 @@ import pecan
from pecan import rest
from webob import exc as webob_exc
import wsme
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
@ -32,6 +31,7 @@ from ironic.api.controllers.v1 import notification_utils as notify
from ironic.api.controllers.v1 import types
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.conductor import steps as conductor_steps
@ -44,30 +44,30 @@ METRICS = metrics_utils.get_metrics_logger(__name__)
_DEFAULT_RETURN_FIELDS = ('uuid', 'name')
_DEPLOY_INTERFACE_TYPE = wtypes.Enum(
_DEPLOY_INTERFACE_TYPE = atypes.Enum(
str, *conductor_steps.DEPLOYING_INTERFACE_PRIORITY)
class DeployStepType(wtypes.Base, base.AsDictMixin):
class DeployStepType(atypes.Base, base.AsDictMixin):
"""A type describing a deployment step."""
interface = wsme.wsattr(_DEPLOY_INTERFACE_TYPE, mandatory=True)
interface = atypes.wsattr(_DEPLOY_INTERFACE_TYPE, mandatory=True)
step = wsme.wsattr(str, mandatory=True)
step = atypes.wsattr(str, mandatory=True)
args = wsme.wsattr({str: types.jsontype}, mandatory=True)
args = atypes.wsattr({str: types.jsontype}, mandatory=True)
priority = wsme.wsattr(wtypes.IntegerType(0), mandatory=True)
priority = atypes.wsattr(atypes.IntegerType(0), mandatory=True)
def __init__(self, **kwargs):
self.fields = ['interface', 'step', 'args', 'priority']
for field in self.fields:
value = kwargs.get(field, wtypes.Unset)
value = kwargs.get(field, atypes.Unset)
setattr(self, field, value)
def sanitize(self):
"""Removes sensitive data."""
if self.args != wtypes.Unset:
if self.args != atypes.Unset:
self.args = strutils.mask_dict_password(self.args, "******")
@ -77,13 +77,13 @@ class DeployTemplate(base.APIBase):
uuid = types.uuid
"""Unique UUID for this deploy template."""
name = wsme.wsattr(str, mandatory=True)
name = atypes.wsattr(str, mandatory=True)
"""The logical name for this deploy template."""
steps = wsme.wsattr([DeployStepType], mandatory=True)
steps = atypes.wsattr([DeployStepType], mandatory=True)
"""The deploy steps of this deploy template."""
links = wsme.wsattr([link.Link])
links = atypes.wsattr([link.Link])
"""A list containing a self link and associated deploy template links."""
extra = {str: types.jsontype}
@ -98,8 +98,8 @@ class DeployTemplate(base.APIBase):
if not hasattr(self, field):
continue
value = kwargs.get(field, wtypes.Unset)
if field == 'steps' and value != wtypes.Unset:
value = kwargs.get(field, atypes.Unset)
if field == 'steps' and value != atypes.Unset:
value = [DeployStepType(**step) for step in value]
self.fields.append(field)
setattr(self, field, value)
@ -110,7 +110,7 @@ class DeployTemplate(base.APIBase):
return
# The name is mandatory, but the 'mandatory' attribute support in
# wtypes.wsattr allows None.
# wsattr allows None.
if value.name is None:
err = _("Deploy template name cannot be None")
raise exception.InvalidDeployTemplate(err=err)
@ -182,7 +182,7 @@ class DeployTemplate(base.APIBase):
list of fields to preserve, or ``None`` to preserve them all
:type fields: list of str
"""
if self.steps != wtypes.Unset:
if self.steps != atypes.Unset:
for step in self.steps:
step.sanitize()
@ -276,7 +276,7 @@ class DeployTemplatesController(rest.RestController):
except AttributeError:
# Ignore fields that aren't exposed in the API.
continue
if patch_val == wtypes.Unset:
if patch_val == atypes.Unset:
patch_val = None
if rpc_template[field] != patch_val:
if field == 'steps' and patch_val is not None:

View File

@ -17,7 +17,6 @@ from http import client as http_client
from ironic_lib import metrics_utils
from pecan import rest
import wsme
from ironic import api
from ironic.api.controllers import base
@ -25,6 +24,7 @@ from ironic.api.controllers import link
from ironic.api.controllers.v1 import types
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import policy
@ -72,16 +72,16 @@ def hide_fields_in_newer_versions(obj):
matches or exceeds the versions when these fields were introduced.
"""
if not api_utils.allow_storage_interface():
obj.default_storage_interface = wsme.Unset
obj.enabled_storage_interfaces = wsme.Unset
obj.default_storage_interface = atypes.Unset
obj.enabled_storage_interfaces = atypes.Unset
if not api_utils.allow_rescue_interface():
obj.default_rescue_interface = wsme.Unset
obj.enabled_rescue_interfaces = wsme.Unset
obj.default_rescue_interface = atypes.Unset
obj.enabled_rescue_interfaces = atypes.Unset
if not api_utils.allow_bios_interface():
obj.default_bios_interface = wsme.Unset
obj.enabled_bios_interfaces = wsme.Unset
obj.default_bios_interface = atypes.Unset
obj.enabled_bios_interfaces = atypes.Unset
class Driver(base.Base):
@ -96,10 +96,10 @@ class Driver(base.Base):
type = str
"""Whether the driver is classic or dynamic (hardware type)"""
links = wsme.wsattr([link.Link], readonly=True)
links = atypes.wsattr([link.Link], readonly=True)
"""A list containing self and bookmark links"""
properties = wsme.wsattr([link.Link], readonly=True)
properties = atypes.wsattr([link.Link], readonly=True)
"""A list containing links to driver properties"""
"""Default interface for a hardware type"""

View File

@ -24,7 +24,6 @@ from oslo_utils import uuidutils
import pecan
from pecan import rest
import wsme
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
@ -40,6 +39,7 @@ from ironic.api.controllers.v1 import utils as api_utils
from ironic.api.controllers.v1 import versions
from ironic.api.controllers.v1 import volume
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import policy
@ -131,7 +131,7 @@ def hide_fields_in_newer_versions(obj):
matches or exceeds the versions when these fields were introduced.
"""
for field in api_utils.disallowed_fields():
setattr(obj, field, wsme.Unset)
setattr(obj, field, atypes.Unset)
def reject_fields_in_newer_versions(obj):
@ -146,7 +146,7 @@ def reject_fields_in_newer_versions(obj):
# explicitly even in old API versions..
continue
else:
empty_value = wtypes.Unset
empty_value = atypes.Unset
if getattr(obj, field, empty_value) != empty_value:
LOG.debug('Field %(field)s is not acceptable in version %(ver)s',
@ -298,7 +298,7 @@ class IndicatorAtComponent(object):
class IndicatorState(base.APIBase):
"""API representation of indicator state."""
state = wsme.wsattr(wtypes.text)
state = atypes.wsattr(str)
def __init__(self, **kwargs):
self.state = kwargs.get('state')
@ -307,15 +307,15 @@ class IndicatorState(base.APIBase):
class Indicator(base.APIBase):
"""API representation of an indicator."""
name = wsme.wsattr(wtypes.text)
name = atypes.wsattr(str)
component = wsme.wsattr(wtypes.text)
component = atypes.wsattr(str)
readonly = types.BooleanType()
states = wtypes.ArrayType(str)
states = atypes.ArrayType(str)
links = wsme.wsattr([link.Link], readonly=True)
links = atypes.wsattr([link.Link], readonly=True)
def __init__(self, **kwargs):
self.name = kwargs.get('name')
@ -348,7 +348,7 @@ class Indicator(base.APIBase):
node_uuid, indicator, pecan.request.host_url)
class IndicatorsCollection(wtypes.Base):
class IndicatorsCollection(atypes.Base):
"""API representation of the indicators for a node."""
indicators = [Indicator]
@ -374,7 +374,7 @@ class IndicatorsCollection(wtypes.Base):
class IndicatorController(rest.RestController):
@METRICS.timer('IndicatorController.put')
@expose.expose(None, types.uuid_or_name, wtypes.text, wtypes.text,
@expose.expose(None, types.uuid_or_name, str, str,
status_code=http_client.NO_CONTENT)
def put(self, node_ident, indicator, state):
"""Set node hardware component indicator to the desired state.
@ -398,7 +398,7 @@ class IndicatorController(rest.RestController):
state, topic=topic)
@METRICS.timer('IndicatorController.get_one')
@expose.expose(IndicatorState, types.uuid_or_name, wtypes.text)
@expose.expose(IndicatorState, types.uuid_or_name, str)
def get_one(self, node_ident, indicator):
"""Get node hardware component indicator and its state.
@ -421,7 +421,7 @@ class IndicatorController(rest.RestController):
return IndicatorState(state=state)
@METRICS.timer('IndicatorController.get_all')
@expose.expose(IndicatorsCollection, types.uuid_or_name, wtypes.text,
@expose.expose(IndicatorsCollection, types.uuid_or_name, str,
ignore_extra_args=True)
def get_all(self, node_ident):
"""Get node hardware components and their indicators.
@ -576,11 +576,11 @@ class NodeStates(base.APIBase):
"""Any error from the most recent (last) asynchronous transaction that
started but failed to finish."""
raid_config = wsme.wsattr({str: types.jsontype}, readonly=True)
raid_config = atypes.wsattr({str: types.jsontype}, readonly=True)
"""Represents the RAID configuration that the node is configured with."""
target_raid_config = wsme.wsattr({str: types.jsontype},
readonly=True)
target_raid_config = atypes.wsattr({str: types.jsontype},
readonly=True)
"""The desired RAID configuration, to be used the next time the node
is configured."""
@ -670,7 +670,7 @@ class NodeStatesController(rest.RestController):
@METRICS.timer('NodeStatesController.power')
@expose.expose(None, types.uuid_or_name, str,
wtypes.IntegerType(minimum=1),
atypes.IntegerType(minimum=1),
status_code=http_client.ACCEPTED)
def power(self, node_ident, target, timeout=None):
"""Set the power state of the node.
@ -699,7 +699,7 @@ class NodeStatesController(rest.RestController):
or timeout) and not api_utils.allow_soft_power_off()):
raise exception.NotAcceptable()
# FIXME(naohirot): This check is workaround because
# wtypes.IntegerType(minimum=1) is not effective
# atypes.IntegerType(minimum=1) is not effective
if timeout is not None and timeout < 1:
raise exception.Invalid(
_("timeout has to be positive integer"))
@ -902,7 +902,7 @@ def _check_clean_steps(clean_steps):
class Traits(base.APIBase):
"""API representation of the traits for a node."""
traits = wtypes.ArrayType(str)
traits = atypes.ArrayType(str)
"""node traits"""
@classmethod
@ -956,7 +956,7 @@ class NodeTraitsController(rest.RestController):
return Traits(traits=traits.get_trait_names())
@METRICS.timer('NodeTraitsController.put')
@expose.expose(None, str, wtypes.ArrayType(str),
@expose.expose(None, str, atypes.ArrayType(str),
status_code=http_client.NO_CONTENT)
def put(self, trait=None, traits=None):
"""Add a trait to a node.
@ -1067,7 +1067,7 @@ class Node(base.APIBase):
return self._chassis_uuid
def _set_chassis_uuid(self, value):
if value in (wtypes.Unset, None):
if value in (atypes.Unset, None):
self._chassis_uuid = value
elif self._chassis_uuid != value:
try:
@ -1089,23 +1089,23 @@ class Node(base.APIBase):
instance_uuid = types.uuid
"""The UUID of the instance in nova-compute"""
name = wsme.wsattr(str)
name = atypes.wsattr(str)
"""The logical name for this node"""
power_state = wsme.wsattr(str, readonly=True)
power_state = atypes.wsattr(str, readonly=True)
"""Represent the current (not transition) power state of the node"""
target_power_state = wsme.wsattr(str, readonly=True)
target_power_state = atypes.wsattr(str, readonly=True)
"""The user modified desired power state of the node."""
last_error = wsme.wsattr(str, readonly=True)
last_error = atypes.wsattr(str, readonly=True)
"""Any error from the most recent (last) asynchronous transaction that
started but failed to finish."""
provision_state = wsme.wsattr(str, readonly=True)
provision_state = atypes.wsattr(str, readonly=True)
"""Represent the current (not transition) provision state of the node"""
reservation = wsme.wsattr(str, readonly=True)
reservation = atypes.wsattr(str, readonly=True)
"""The hostname of the conductor that holds an exclusive lock on
the node."""
@ -1122,13 +1122,13 @@ class Node(base.APIBase):
maintenance = types.boolean
"""Indicates whether the node is in maintenance mode."""
maintenance_reason = wsme.wsattr(str, readonly=True)
maintenance_reason = atypes.wsattr(str, readonly=True)
"""Indicates reason for putting a node in maintenance mode."""
fault = wsme.wsattr(str, readonly=True)
fault = atypes.wsattr(str, readonly=True)
"""Indicates the active fault of a node."""
target_provision_state = wsme.wsattr(str, readonly=True)
target_provision_state = atypes.wsattr(str, readonly=True)
"""The user modified desired provision state of the node."""
console_enabled = types.boolean
@ -1138,33 +1138,33 @@ class Node(base.APIBase):
instance_info = {str: types.jsontype}
"""This node's instance info."""
driver = wsme.wsattr(str, mandatory=True)
driver = atypes.wsattr(str, mandatory=True)
"""The driver responsible for controlling the node"""
driver_info = {str: types.jsontype}
"""This node's driver configuration"""
driver_internal_info = wsme.wsattr({str: types.jsontype},
readonly=True)
driver_internal_info = atypes.wsattr({str: types.jsontype},
readonly=True)
"""This driver's internal configuration"""
clean_step = wsme.wsattr({str: types.jsontype}, readonly=True)
clean_step = atypes.wsattr({str: types.jsontype}, readonly=True)
"""The current clean step"""
deploy_step = wsme.wsattr({str: types.jsontype}, readonly=True)
deploy_step = atypes.wsattr({str: types.jsontype}, readonly=True)
"""The current deploy step"""
raid_config = wsme.wsattr({str: types.jsontype}, readonly=True)
raid_config = atypes.wsattr({str: types.jsontype}, readonly=True)
"""Represents the current RAID configuration of the node """
target_raid_config = wsme.wsattr({str: types.jsontype},
readonly=True)
target_raid_config = atypes.wsattr({str: types.jsontype},
readonly=True)
"""The user modified RAID configuration of the node """
extra = {str: types.jsontype}
"""This node's meta data"""
resource_class = wsme.wsattr(wtypes.StringType(max_length=80))
resource_class = atypes.wsattr(atypes.StringType(max_length=80))
"""The resource class for the node, useful for classifying or grouping
nodes. Used, for example, to classify nodes in Nova's placement
engine."""
@ -1174,65 +1174,65 @@ class Node(base.APIBase):
properties = {str: types.jsontype}
"""The physical characteristics of this node"""
chassis_uuid = wsme.wsproperty(types.uuid, _get_chassis_uuid,
_set_chassis_uuid)
chassis_uuid = atypes.wsproperty(types.uuid, _get_chassis_uuid,
_set_chassis_uuid)
"""The UUID of the chassis this node belongs"""
links = wsme.wsattr([link.Link], readonly=True)
links = atypes.wsattr([link.Link], readonly=True)
"""A list containing a self link and associated node links"""
ports = wsme.wsattr([link.Link], readonly=True)
ports = atypes.wsattr([link.Link], readonly=True)
"""Links to the collection of ports on this node"""
portgroups = wsme.wsattr([link.Link], readonly=True)
portgroups = atypes.wsattr([link.Link], readonly=True)
"""Links to the collection of portgroups on this node"""
volume = wsme.wsattr([link.Link], readonly=True)
volume = atypes.wsattr([link.Link], readonly=True)
"""Links to endpoint for retrieving volume resources on this node"""
states = wsme.wsattr([link.Link], readonly=True)
states = atypes.wsattr([link.Link], readonly=True)
"""Links to endpoint for retrieving and setting node states"""
boot_interface = wsme.wsattr(str)
boot_interface = atypes.wsattr(str)
"""The boot interface to be used for this node"""
console_interface = wsme.wsattr(str)
console_interface = atypes.wsattr(str)
"""The console interface to be used for this node"""
deploy_interface = wsme.wsattr(str)
deploy_interface = atypes.wsattr(str)
"""The deploy interface to be used for this node"""
inspect_interface = wsme.wsattr(str)
inspect_interface = atypes.wsattr(str)
"""The inspect interface to be used for this node"""
management_interface = wsme.wsattr(str)
management_interface = atypes.wsattr(str)
"""The management interface to be used for this node"""
network_interface = wsme.wsattr(str)
network_interface = atypes.wsattr(str)
"""The network interface to be used for this node"""
power_interface = wsme.wsattr(str)
power_interface = atypes.wsattr(str)
"""The power interface to be used for this node"""
raid_interface = wsme.wsattr(str)
raid_interface = atypes.wsattr(str)
"""The raid interface to be used for this node"""
rescue_interface = wsme.wsattr(str)
rescue_interface = atypes.wsattr(str)
"""The rescue interface to be used for this node"""
storage_interface = wsme.wsattr(str)
storage_interface = atypes.wsattr(str)
"""The storage interface to be used for this node"""
vendor_interface = wsme.wsattr(str)
vendor_interface = atypes.wsattr(str)
"""The vendor interface to be used for this node"""
traits = wtypes.ArrayType(str)
traits = atypes.ArrayType(str)
"""The traits associated with this node"""
bios_interface = wsme.wsattr(str)
bios_interface = atypes.wsattr(str)
"""The bios interface to be used for this node"""
conductor_group = wsme.wsattr(str)
conductor_group = atypes.wsattr(str)
"""The conductor group to manage this node"""
automated_clean = types.boolean
@ -1241,28 +1241,28 @@ class Node(base.APIBase):
protected = types.boolean
"""Indicates whether the node is protected from undeploying/rebuilding."""
protected_reason = wsme.wsattr(str)
protected_reason = atypes.wsattr(str)
"""Indicates reason for protecting the node."""
conductor = wsme.wsattr(str, readonly=True)
conductor = atypes.wsattr(str, readonly=True)
"""Represent the conductor currently serving the node"""
owner = wsme.wsattr(str)
owner = atypes.wsattr(str)
"""Field for storage of physical node owner"""
lessee = wsme.wsattr(wtypes.text)
lessee = atypes.wsattr(str)
"""Field for storage of physical node lessee"""
description = wsme.wsattr(wtypes.text)
description = atypes.wsattr(str)
"""Field for node description"""
allocation_uuid = wsme.wsattr(types.uuid, readonly=True)
allocation_uuid = atypes.wsattr(types.uuid, readonly=True)
"""The UUID of the allocation this node belongs"""
retired = types.boolean
"""Indicates whether the node is marked for retirement."""
retired_reason = wsme.wsattr(str)
retired_reason = atypes.wsattr(str)
"""Indicates the reason for a node's retirement."""
# NOTE(tenbrae): "conductor_affinity" shouldn't be presented on the
@ -1286,10 +1286,10 @@ class Node(base.APIBase):
# NOTE(jroll) this is special-cased to "" and not Unset,
# because it is used in hash ring calculations
elif (k == 'conductor_group'
and (k not in kwargs or kwargs[k] is wtypes.Unset)):
and (k not in kwargs or kwargs[k] is atypes.Unset)):
value = ''
else:
value = kwargs.get(k, wtypes.Unset)
value = kwargs.get(k, atypes.Unset)
setattr(self, k, value)
# NOTE(lucasagomes): chassis_id is an attribute created on-the-fly
@ -1299,7 +1299,7 @@ class Node(base.APIBase):
self.fields.append('chassis_id')
if 'chassis_uuid' not in kwargs:
setattr(self, 'chassis_uuid', kwargs.get('chassis_id',
wtypes.Unset))
atypes.Unset))
@staticmethod
def _convert_with_links(node, url, fields=None, show_states_links=True,
@ -1407,7 +1407,7 @@ class Node(base.APIBase):
show_instance_secrets = policy.check("show_instance_secrets",
cdict, cdict)
if not show_driver_secrets and self.driver_info != wtypes.Unset:
if not show_driver_secrets and self.driver_info != atypes.Unset:
self.driver_info = strutils.mask_dict_password(
self.driver_info, "******")
@ -1418,7 +1418,7 @@ class Node(base.APIBase):
if self.driver_info.get('ssh_key_contents'):
self.driver_info['ssh_key_contents'] = "******"
if not show_instance_secrets and self.instance_info != wtypes.Unset:
if not show_instance_secrets and self.instance_info != atypes.Unset:
self.instance_info = strutils.mask_dict_password(
self.instance_info, "******")
# NOTE(tenbrae): agent driver may store a swift temp_url on the
@ -1440,7 +1440,7 @@ class Node(base.APIBase):
# NOTE(lucasagomes): The numeric ID should not be exposed to
# the user, it's internal only.
self.chassis_id = wtypes.Unset
self.chassis_id = atypes.Unset
show_states_links = (
api_utils.allow_links_node_states_and_driver_properties())
@ -1448,11 +1448,11 @@ class Node(base.APIBase):
show_volume = api_utils.allow_volume()
if not show_volume:
self.volume = wtypes.Unset
self.volume = atypes.Unset
if not show_portgroups:
self.portgroups = wtypes.Unset
self.portgroups = atypes.Unset
if not show_states_links:
self.states = wtypes.Unset
self.states = atypes.Unset
@classmethod
def sample(cls, expand=True):
@ -1944,7 +1944,7 @@ class NodesController(rest.RestController):
raise exception.NotAcceptable()
rpc_node[field] = None
continue
if patch_val == wtypes.Unset:
if patch_val == atypes.Unset:
patch_val = None
# conductor_group is case-insensitive, and we use it to calculate
# the conductor to send an update too. lowercase it here instead
@ -2204,30 +2204,30 @@ class NodesController(rest.RestController):
cdict = context.to_policy_values()
policy.authorize('baremetal:node:create', cdict, cdict)
if node.conductor is not wtypes.Unset:
if node.conductor is not atypes.Unset:
msg = _("Cannot specify conductor on node creation.")
raise exception.Invalid(msg)
reject_fields_in_newer_versions(node)
if node.traits is not wtypes.Unset:
if node.traits is not atypes.Unset:
msg = _("Cannot specify node traits on node creation. Traits must "
"be set via the node traits API.")
raise exception.Invalid(msg)
if (node.protected is not wtypes.Unset
or node.protected_reason is not wtypes.Unset):
if (node.protected is not atypes.Unset
or node.protected_reason is not atypes.Unset):
msg = _("Cannot specify protected or protected_reason on node "
"creation. These fields can only be set for active nodes")
raise exception.Invalid(msg)
if (node.description is not wtypes.Unset
if (node.description is not atypes.Unset
and len(node.description) > _NODE_DESCRIPTION_MAX_LENGTH):
msg = _("Cannot create node with description exceeding %s "
"characters") % _NODE_DESCRIPTION_MAX_LENGTH
raise exception.Invalid(msg)
if node.allocation_uuid is not wtypes.Unset:
if node.allocation_uuid is not atypes.Unset:
msg = _("Allocation UUID cannot be specified, use allocations API")
raise exception.Invalid(msg)
@ -2247,7 +2247,7 @@ class NodesController(rest.RestController):
e.code = http_client.BAD_REQUEST
raise
if node.name != wtypes.Unset and node.name is not None:
if node.name != atypes.Unset and node.name is not None:
error_msg = _("Cannot create node with invalid name '%(name)s'")
self._check_names_acceptable([node.name], error_msg)
node.provision_state = api_utils.initial_node_provision_state()

View File

@ -17,8 +17,8 @@ from oslo_log import log
from oslo_messaging import exceptions as oslo_msg_exc
from oslo_utils import excutils
from oslo_versionedobjects import exception as oslo_vo_exc
from wsme import types as wtypes
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.objects import allocation as allocation_objects
@ -71,8 +71,8 @@ def _emit_api_notification(context, obj, action, level, status, **kwargs):
:param kwargs: kwargs to use when creating the notification payload.
"""
resource = obj.__class__.__name__.lower()
# value wsme.Unset can be passed from API representation of resource
extra_args = {k: (v if v != wtypes.Unset else None)
# value atypes.Unset can be passed from API representation of resource
extra_args = {k: (v if v != atypes.Unset else None)
for k, v in kwargs.items()}
try:
try:

View File

@ -21,7 +21,6 @@ from oslo_log import log
from oslo_utils import uuidutils
from pecan import rest
import wsme
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
@ -31,6 +30,7 @@ from ironic.api.controllers.v1 import notification_utils as notify
from ironic.api.controllers.v1 import types
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import policy
@ -47,21 +47,21 @@ _DEFAULT_RETURN_FIELDS = ('uuid', 'address')
def hide_fields_in_newer_versions(obj):
# if requested version is < 1.18, hide internal_info field
if not api_utils.allow_port_internal_info():
obj.internal_info = wsme.Unset
obj.internal_info = atypes.Unset
# if requested version is < 1.19, hide local_link_connection and
# pxe_enabled fields
if not api_utils.allow_port_advanced_net_fields():
obj.pxe_enabled = wsme.Unset
obj.local_link_connection = wsme.Unset
obj.pxe_enabled = atypes.Unset
obj.local_link_connection = atypes.Unset
# if requested version is < 1.24, hide portgroup_uuid field
if not api_utils.allow_portgroups_subcontrollers():
obj.portgroup_uuid = wsme.Unset
obj.portgroup_uuid = atypes.Unset
# if requested version is < 1.34, hide physical_network field.
if not api_utils.allow_port_physical_network():
obj.physical_network = wsme.Unset
obj.physical_network = atypes.Unset
# if requested version is < 1.53, hide is_smartnic field.
if not api_utils.allow_port_is_smartnic():
obj.is_smartnic = wsme.Unset
obj.is_smartnic = atypes.Unset
class Port(base.APIBase):
@ -94,8 +94,8 @@ class Port(base.APIBase):
# response for a POST request to create a Port
e.code = http_client.BAD_REQUEST # BadRequest
raise
elif value == wtypes.Unset:
self._node_uuid = wtypes.Unset
elif value == atypes.Unset:
self._node_uuid = atypes.Unset
def _get_portgroup_uuid(self):
return self._portgroup_uuid
@ -103,7 +103,7 @@ class Port(base.APIBase):
def _set_portgroup_uuid(self, value):
if value and self._portgroup_uuid != value:
if not api_utils.allow_portgroups_subcontrollers():
self._portgroup_uuid = wtypes.Unset
self._portgroup_uuid = atypes.Unset
return
try:
portgroup = objects.Portgroup.get(api.request.context, value)
@ -121,8 +121,8 @@ class Port(base.APIBase):
# response for a POST request to create a Port
e.code = http_client.BAD_REQUEST # BadRequest
raise e
elif value == wtypes.Unset:
self._portgroup_uuid = wtypes.Unset
elif value == atypes.Unset:
self._portgroup_uuid = atypes.Unset
elif value is None and api_utils.allow_portgroups_subcontrollers():
# This is to output portgroup_uuid field if API version allows this
self._portgroup_uuid = None
@ -130,21 +130,21 @@ class Port(base.APIBase):
uuid = types.uuid
"""Unique UUID for this port"""
address = wsme.wsattr(types.macaddress, mandatory=True)
address = atypes.wsattr(types.macaddress, mandatory=True)
"""MAC Address for this port"""
extra = {str: types.jsontype}
"""This port's meta data"""
internal_info = wsme.wsattr({str: types.jsontype}, readonly=True)
internal_info = atypes.wsattr({str: types.jsontype}, readonly=True)
"""This port's internal information maintained by ironic"""
node_uuid = wsme.wsproperty(types.uuid, _get_node_uuid, _set_node_uuid,
mandatory=True)
node_uuid = atypes.wsproperty(types.uuid, _get_node_uuid, _set_node_uuid,
mandatory=True)
"""The UUID of the node this port belongs to"""
portgroup_uuid = wsme.wsproperty(types.uuid, _get_portgroup_uuid,
_set_portgroup_uuid, mandatory=False)
portgroup_uuid = atypes.wsproperty(types.uuid, _get_portgroup_uuid,
_set_portgroup_uuid, mandatory=False)
"""The UUID of the portgroup this port belongs to"""
pxe_enabled = types.boolean
@ -153,10 +153,10 @@ class Port(base.APIBase):
local_link_connection = types.locallinkconnectiontype
"""The port binding profile for the port"""
physical_network = wtypes.StringType(max_length=64)
physical_network = atypes.StringType(max_length=64)
"""The name of the physical network to which this port is connected."""
links = wsme.wsattr([link.Link], readonly=True)
links = atypes.wsattr([link.Link], readonly=True)
"""A list containing a self link and associated port links"""
is_smartnic = types.boolean
@ -175,14 +175,14 @@ class Port(base.APIBase):
# Add fields we expose.
if hasattr(self, field):
self.fields.append(field)
setattr(self, field, kwargs.get(field, wtypes.Unset))
setattr(self, field, kwargs.get(field, atypes.Unset))
# NOTE(lucasagomes): node_id is an attribute created on-the-fly
# by _set_node_uuid(), it needs to be present in the fields so
# that as_dict() will contain node_id field when converting it
# before saving it in the database.
self.fields.append('node_id')
setattr(self, 'node_uuid', kwargs.get('node_id', wtypes.Unset))
setattr(self, 'node_uuid', kwargs.get('node_id', atypes.Unset))
# NOTE: portgroup_id is an attribute created on-the-fly
# by _set_portgroup_uuid(), it needs to be present in the fields so
@ -190,7 +190,7 @@ class Port(base.APIBase):
# before saving it in the database.
self.fields.append('portgroup_id')
setattr(self, 'portgroup_uuid', kwargs.get('portgroup_id',
wtypes.Unset))
atypes.Unset))
@classmethod
def convert_with_links(cls, rpc_port, fields=None, sanitize=True):
@ -233,10 +233,10 @@ class Port(base.APIBase):
self.unset_fields_except(fields)
# never expose the node_id attribute
self.node_id = wtypes.Unset
self.node_id = atypes.Unset
# never expose the portgroup_id attribute
self.portgroup_id = wtypes.Unset
self.portgroup_id = atypes.Unset
@classmethod
def sample(cls, expand=True):
@ -711,7 +711,7 @@ class PortsController(rest.RestController):
except AttributeError:
# Ignore fields that aren't exposed in the API
continue
if patch_val == wtypes.Unset:
if patch_val == atypes.Unset:
patch_val = None
if rpc_port[field] != patch_val:
rpc_port[field] = patch_val

View File

@ -17,7 +17,6 @@ from ironic_lib import metrics_utils
from oslo_utils import uuidutils
import pecan
import wsme
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
@ -28,6 +27,7 @@ from ironic.api.controllers.v1 import port
from ironic.api.controllers.v1 import types
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import policy
@ -55,7 +55,7 @@ class Portgroup(base.APIBase):
def _set_node_uuid(self, value):
if value and self._node_uuid != value:
if not api_utils.allow_portgroups():
self._node_uuid = wtypes.Unset
self._node_uuid = atypes.Unset
return
try:
node = objects.Node.get(api.request.context, value)
@ -69,36 +69,36 @@ class Portgroup(base.APIBase):
# response for a POST request to create a Portgroup
e.code = http_client.BAD_REQUEST
raise e
elif value == wtypes.Unset:
self._node_uuid = wtypes.Unset
elif value == atypes.Unset:
self._node_uuid = atypes.Unset
uuid = types.uuid
"""Unique UUID for this portgroup"""
address = wsme.wsattr(types.macaddress)
address = atypes.wsattr(types.macaddress)
"""MAC Address for this portgroup"""
extra = {str: types.jsontype}
"""This portgroup's meta data"""
internal_info = wsme.wsattr({str: types.jsontype}, readonly=True)
internal_info = atypes.wsattr({str: types.jsontype}, readonly=True)
"""This portgroup's internal info"""
node_uuid = wsme.wsproperty(types.uuid, _get_node_uuid, _set_node_uuid,
mandatory=True)
node_uuid = atypes.wsproperty(types.uuid, _get_node_uuid, _set_node_uuid,
mandatory=True)
"""The UUID of the node this portgroup belongs to"""
name = wsme.wsattr(str)
name = atypes.wsattr(str)
"""The logical name for this portgroup"""
links = wsme.wsattr([link.Link], readonly=True)
links = atypes.wsattr([link.Link], readonly=True)
"""A list containing a self link and associated portgroup links"""
standalone_ports_supported = types.boolean
"""Indicates whether ports of this portgroup may be used as
single NIC ports"""
mode = wsme.wsattr(str)
mode = atypes.wsattr(str)
"""The mode for this portgroup. See linux bonding
documentation for details:
https://www.kernel.org/doc/Documentation/networking/bonding.txt"""
@ -106,7 +106,7 @@ class Portgroup(base.APIBase):
properties = {str: types.jsontype}
"""This portgroup's properties"""
ports = wsme.wsattr([link.Link], readonly=True)
ports = atypes.wsattr([link.Link], readonly=True)
"""Links to the collection of ports of this portgroup"""
def __init__(self, **kwargs):
@ -120,14 +120,14 @@ class Portgroup(base.APIBase):
if not hasattr(self, field):
continue
self.fields.append(field)
setattr(self, field, kwargs.get(field, wtypes.Unset))
setattr(self, field, kwargs.get(field, atypes.Unset))
# NOTE: node_id is an attribute created on-the-fly
# by _set_node_uuid(), it needs to be present in the fields so
# that as_dict() will contain node_id field when converting it
# before saving it in the database.
self.fields.append('node_id')
setattr(self, 'node_uuid', kwargs.get('node_id', wtypes.Unset))
setattr(self, 'node_uuid', kwargs.get('node_id', atypes.Unset))
@staticmethod
def _convert_with_links(portgroup, url, fields=None):
@ -141,7 +141,7 @@ class Portgroup(base.APIBase):
]
# never expose the node_id attribute
portgroup.node_id = wtypes.Unset
portgroup.node_id = atypes.Unset
portgroup.links = [link.Link.make_link('self', url,
'portgroups', portgroup.uuid),
@ -183,7 +183,7 @@ class Portgroup(base.APIBase):
self.unset_fields_except(fields)
# never expose the node_id attribute
self.node_id = wtypes.Unset
self.node_id = atypes.Unset
@classmethod
def sample(cls, expand=True):
@ -476,8 +476,8 @@ class PortgroupsController(pecan.rest.RestController):
raise exception.OperationNotPermitted()
if (not api_utils.allow_portgroup_mode_properties()
and (portgroup.mode is not wtypes.Unset
or portgroup.properties is not wtypes.Unset)):
and (portgroup.mode is not atypes.Unset
or portgroup.properties is not atypes.Unset)):
raise exception.NotAcceptable()
if (portgroup.name
@ -566,7 +566,7 @@ class PortgroupsController(pecan.rest.RestController):
except AttributeError:
# Ignore fields that aren't exposed in the API
continue
if patch_val == wtypes.Unset:
if patch_val == atypes.Unset:
patch_val = None
if rpc_portgroup[field] != patch_val:
rpc_portgroup[field] = patch_val

View File

@ -21,11 +21,10 @@ import json
from oslo_log import log
from oslo_utils import strutils
from oslo_utils import uuidutils
import wsme
from wsme import types as wtypes
from ironic.api.controllers import base
from ironic.api.controllers.v1 import utils as v1_utils
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import utils
@ -34,7 +33,7 @@ from ironic.common import utils
LOG = log.getLogger(__name__)
class MacAddressType(wtypes.UserType):
class MacAddressType(atypes.UserType):
"""A simple MAC address type."""
basetype = str
@ -51,7 +50,7 @@ class MacAddressType(wtypes.UserType):
return MacAddressType.validate(value)
class UuidOrNameType(wtypes.UserType):
class UuidOrNameType(atypes.UserType):
"""A simple UUID or logical name type."""
basetype = str
@ -71,7 +70,7 @@ class UuidOrNameType(wtypes.UserType):
return UuidOrNameType.validate(value)
class NameType(wtypes.UserType):
class NameType(atypes.UserType):
"""A simple logical name type."""
basetype = str
@ -90,7 +89,7 @@ class NameType(wtypes.UserType):
return NameType.validate(value)
class UuidType(wtypes.UserType):
class UuidType(atypes.UserType):
"""A simple UUID type."""
basetype = str
@ -109,7 +108,7 @@ class UuidType(wtypes.UserType):
return UuidType.validate(value)
class BooleanType(wtypes.UserType):
class BooleanType(atypes.UserType):
"""A simple boolean type."""
basetype = str
@ -130,7 +129,7 @@ class BooleanType(wtypes.UserType):
return BooleanType.validate(value)
class JsonType(wtypes.UserType):
class JsonType(atypes.UserType):
"""A simple JSON type."""
basetype = str
@ -155,7 +154,7 @@ class JsonType(wtypes.UserType):
return JsonType.validate(value)
class ListType(wtypes.UserType):
class ListType(atypes.UserType):
"""A simple list type."""
basetype = str
@ -196,11 +195,11 @@ jsontype = JsonType()
class JsonPatchType(base.Base):
"""A complex type that represents a single json-patch operation."""
path = wtypes.wsattr(wtypes.StringType(pattern='^(/[\\w-]+)+$'),
path = atypes.wsattr(atypes.StringType(pattern='^(/[\\w-]+)+$'),
mandatory=True)
op = wtypes.wsattr(wtypes.Enum(str, 'add', 'replace', 'remove'),
op = atypes.wsattr(atypes.Enum(str, 'add', 'replace', 'remove'),
mandatory=True)
value = wsme.wsattr(jsontype, default=wtypes.Unset)
value = atypes.wsattr(jsontype, default=atypes.Unset)
# The class of the objects being patched. Override this in subclasses.
# Should probably be a subclass of ironic.api.controllers.base.APIBase.
@ -254,20 +253,20 @@ class JsonPatchType(base.Base):
raise exception.ClientSideError(msg % patch.path)
if patch.op != 'remove':
if patch.value is wsme.Unset:
if patch.value is atypes.Unset:
msg = _("'add' and 'replace' operations need a value")
raise exception.ClientSideError(msg)
ret = {'path': patch.path, 'op': patch.op}
if patch.value is not wsme.Unset:
if patch.value is not atypes.Unset:
ret['value'] = patch.value
return ret
class LocalLinkConnectionType(wtypes.UserType):
class LocalLinkConnectionType(atypes.UserType):
"""A type describing local link connection."""
basetype = wtypes.DictType
basetype = atypes.DictType
name = 'locallinkconnection'
local_link_mandatory_fields = {'port_id', 'switch_id'}
@ -305,7 +304,7 @@ class LocalLinkConnectionType(wtypes.UserType):
:raises: Invalid if some of the keys in the dictionary being validated
are unknown, invalid, or some required ones are missing.
"""
wtypes.DictType(str, str).validate(value)
atypes.DictType(str, str).validate(value)
keys = set(value)
@ -385,7 +384,7 @@ class LocalLinkConnectionType(wtypes.UserType):
:return: True if both fields 'port_id' and 'hostname' are present
in 'value', False otherwise.
"""
wtypes.DictType(str, str).validate(value)
atypes.DictType(str, str).validate(value)
keys = set(value)
if LocalLinkConnectionType.smart_nic_mandatory_fields <= keys:
@ -426,10 +425,10 @@ class VifType(JsonType):
viftype = VifType()
class EventType(wtypes.UserType):
class EventType(atypes.UserType):
"""A simple Event type."""
basetype = wtypes.DictType
basetype = atypes.DictType
name = 'event'
def _validate_network_port_event(value):
@ -494,7 +493,7 @@ class EventType(wtypes.UserType):
:raises: Invalid if event not in proper format
"""
wtypes.DictType(str, str).validate(value)
atypes.DictType(str, str).validate(value)
keys = set(value)
# Check all mandatory fields are present

View File

@ -29,6 +29,7 @@ import wsme
from ironic import api
from ironic.api.controllers.v1 import versions
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common import faults
from ironic.common.i18n import _
@ -425,7 +426,7 @@ def vendor_passthru(ident, method, topic, data=None, driver_passthru=False):
if isinstance(return_value, str):
# If unicode, convert to bytes
return_value = return_value.encode('utf-8')
file_ = wsme.types.File(content=return_value)
file_ = atypes.File(content=return_value)
api.response.app_iter = static.FileIter(file_.file)
# Since we've attached the return value to the response
# object the response body should now be empty.

View File

@ -16,7 +16,6 @@ from http import client as http_client
import pecan
from pecan import rest
import wsme
from ironic import api
from ironic.api.controllers import base
@ -25,6 +24,7 @@ from ironic.api.controllers.v1 import utils as api_utils
from ironic.api.controllers.v1 import volume_connector
from ironic.api.controllers.v1 import volume_target
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common import policy
@ -36,13 +36,13 @@ class Volume(base.APIBase):
targets controllers.
"""
links = wsme.wsattr([link.Link], readonly=True)
links = atypes.wsattr([link.Link], readonly=True)
"""A list containing a self link and associated volume links"""
connectors = wsme.wsattr([link.Link], readonly=True)
connectors = atypes.wsattr([link.Link], readonly=True)
"""Links to the volume connectors resource"""
targets = wsme.wsattr([link.Link], readonly=True)
targets = atypes.wsattr([link.Link], readonly=True)
"""Links to the volume targets resource"""
@staticmethod

View File

@ -19,7 +19,6 @@ from ironic_lib import metrics_utils
from oslo_utils import uuidutils
from pecan import rest
import wsme
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
@ -29,6 +28,7 @@ from ironic.api.controllers.v1 import notification_utils as notify
from ironic.api.controllers.v1 import types
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import policy
@ -55,10 +55,10 @@ class VolumeConnector(base.APIBase):
def _set_node_identifiers(self, value):
"""Set both UUID and ID of a node for VolumeConnector object
:param value: UUID, ID of a node, or wtypes.Unset
:param value: UUID, ID of a node, or atypes.Unset
"""
if value == wtypes.Unset:
self._node_uuid = wtypes.Unset
if value == atypes.Unset:
self._node_uuid = atypes.Unset
elif value and self._node_uuid != value:
try:
node = objects.Node.get(api.request.context, value)
@ -75,20 +75,20 @@ class VolumeConnector(base.APIBase):
uuid = types.uuid
"""Unique UUID for this volume connector"""
type = wsme.wsattr(str, mandatory=True)
type = atypes.wsattr(str, mandatory=True)
"""The type of volume connector"""
connector_id = wsme.wsattr(str, mandatory=True)
connector_id = atypes.wsattr(str, mandatory=True)
"""The connector_id for this volume connector"""
extra = {str: types.jsontype}
"""The metadata for this volume connector"""
node_uuid = wsme.wsproperty(types.uuid, _get_node_uuid,
_set_node_identifiers, mandatory=True)
node_uuid = atypes.wsproperty(types.uuid, _get_node_uuid,
_set_node_identifiers, mandatory=True)
"""The UUID of the node this volume connector belongs to"""
links = wsme.wsattr([link.Link], readonly=True)
links = atypes.wsattr([link.Link], readonly=True)
"""A list containing a self link and associated volume connector links"""
def __init__(self, **kwargs):
@ -99,7 +99,7 @@ class VolumeConnector(base.APIBase):
if not hasattr(self, field):
continue
self.fields.append(field)
setattr(self, field, kwargs.get(field, wtypes.Unset))
setattr(self, field, kwargs.get(field, atypes.Unset))
# NOTE(smoriya): node_id is an attribute created on-the-fly
# by _set_node_uuid(), it needs to be present in the fields so
@ -113,7 +113,7 @@ class VolumeConnector(base.APIBase):
# secondary identifier in case RPC volume connector object dictionary
# was passed to the constructor.
self.node_uuid = kwargs.get('node_uuid') or kwargs.get('node_id',
wtypes.Unset)
atypes.Unset)
@staticmethod
def _convert_with_links(connector, url):
@ -159,7 +159,7 @@ class VolumeConnector(base.APIBase):
self.unset_fields_except(fields)
# never expose the node_id attribute
self.node_id = wtypes.Unset
self.node_id = atypes.Unset
@classmethod
def sample(cls, expand=True):
@ -437,7 +437,7 @@ class VolumeConnectorsController(rest.RestController):
except AttributeError:
# Ignore fields that aren't exposed in the API
continue
if patch_val == wtypes.Unset:
if patch_val == atypes.Unset:
patch_val = None
if rpc_connector[field] != patch_val:
rpc_connector[field] = patch_val

View File

@ -19,7 +19,6 @@ from ironic_lib import metrics_utils
from oslo_utils import uuidutils
from pecan import rest
import wsme
from wsme import types as wtypes
from ironic import api
from ironic.api.controllers import base
@ -29,6 +28,7 @@ from ironic.api.controllers.v1 import notification_utils as notify
from ironic.api.controllers.v1 import types
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import policy
@ -56,10 +56,10 @@ class VolumeTarget(base.APIBase):
def _set_node_identifiers(self, value):
"""Set both UUID and ID of a node for VolumeTarget object
:param value: UUID, ID of a node, or wtypes.Unset
:param value: UUID, ID of a node, or atypes.Unset
"""
if value == wtypes.Unset:
self._node_uuid = wtypes.Unset
if value == atypes.Unset:
self._node_uuid = atypes.Unset
elif value and self._node_uuid != value:
try:
node = objects.Node.get(api.request.context, value)
@ -76,26 +76,26 @@ class VolumeTarget(base.APIBase):
uuid = types.uuid
"""Unique UUID for this volume target"""
volume_type = wsme.wsattr(str, mandatory=True)
volume_type = atypes.wsattr(str, mandatory=True)
"""The volume_type of volume target"""
properties = {str: types.jsontype}
"""The properties for this volume target"""
boot_index = wsme.wsattr(int, mandatory=True)
boot_index = atypes.wsattr(int, mandatory=True)
"""The boot_index of volume target"""
volume_id = wsme.wsattr(str, mandatory=True)
volume_id = atypes.wsattr(str, mandatory=True)
"""The volume_id for this volume target"""
extra = {str: types.jsontype}
"""The metadata for this volume target"""
node_uuid = wsme.wsproperty(types.uuid, _get_node_uuid,
_set_node_identifiers, mandatory=True)
node_uuid = atypes.wsproperty(types.uuid, _get_node_uuid,
_set_node_identifiers, mandatory=True)
"""The UUID of the node this volume target belongs to"""
links = wsme.wsattr([link.Link], readonly=True)
links = atypes.wsattr([link.Link], readonly=True)
"""A list containing a self link and associated volume target links"""
def __init__(self, **kwargs):
@ -106,7 +106,7 @@ class VolumeTarget(base.APIBase):
if not hasattr(self, field):
continue
self.fields.append(field)
setattr(self, field, kwargs.get(field, wtypes.Unset))
setattr(self, field, kwargs.get(field, atypes.Unset))
# NOTE(smoriya): node_id is an attribute created on-the-fly
# by _set_node_uuid(), it needs to be present in the fields so
@ -120,7 +120,7 @@ class VolumeTarget(base.APIBase):
# secondary identifier in case RPC volume target object dictionary
# was passed to the constructor.
self.node_uuid = kwargs.get('node_uuid') or kwargs.get('node_id',
wtypes.Unset)
atypes.Unset)
@staticmethod
def _convert_with_links(target, url):
@ -165,7 +165,7 @@ class VolumeTarget(base.APIBase):
self.unset_fields_except(fields)
# never expose the node_id attribute
self.node_id = wtypes.Unset
self.node_id = atypes.Unset
@classmethod
def sample(cls, expand=True):
@ -448,7 +448,7 @@ class VolumeTargetsController(rest.RestController):
except AttributeError:
# Ignore fields that aren't exposed in the API
continue
if patch_val == wtypes.Unset:
if patch_val == atypes.Unset:
patch_val = None
if rpc_target[field] != patch_val:
rpc_target[field] = patch_val

29
ironic/api/types.py Normal file
View File

@ -0,0 +1,29 @@
# coding: utf-8
#
# Copyright 2020 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from wsme.types import ArrayType # noqa
from wsme.types import Base # noqa
from wsme.types import DictType # noqa
from wsme.types import Enum # noqa
from wsme.types import File # noqa
from wsme.types import IntegerType # noqa
from wsme.types import StringType # noqa
from wsme.types import text # noqa
from wsme.types import Unset # noqa
from wsme.types import UserType # noqa
from wsme.types import wsattr # noqa
from wsme.types import wsproperty # noqa

View File

@ -22,12 +22,12 @@ import mock
from oslo_config import cfg
from oslo_utils import timeutils
from oslo_utils import uuidutils
from wsme import types as wtypes
from ironic.api.controllers import base as api_base
from ironic.api.controllers import v1 as api_v1
from ironic.api.controllers.v1 import allocation as api_allocation
from ironic.api.controllers.v1 import notification_utils
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common import policy
from ironic.conductor import rpcapi
@ -45,7 +45,7 @@ class TestAllocationObject(base.TestCase):
allocation_dict = apiutils.allocation_post_data(node_id=None)
del allocation_dict['extra']
allocation = api_allocation.Allocation(**allocation_dict)
self.assertEqual(wtypes.Unset, allocation.extra)
self.assertEqual(atypes.Unset, allocation.extra)
class TestListAllocations(test_api_base.BaseApiTest):

View File

@ -23,12 +23,12 @@ import mock
from oslo_config import cfg
from oslo_utils import timeutils
from oslo_utils import uuidutils
from wsme import types as wtypes
from ironic.api.controllers import base as api_base
from ironic.api.controllers import v1 as api_v1
from ironic.api.controllers.v1 import chassis as api_chassis
from ironic.api.controllers.v1 import notification_utils
from ironic.api import types as atypes
from ironic import objects
from ironic.objects import fields as obj_fields
from ironic.tests import base
@ -43,7 +43,7 @@ class TestChassisObject(base.TestCase):
chassis_dict = apiutils.chassis_post_data()
del chassis_dict['description']
chassis = api_chassis.Chassis(**chassis_dict)
self.assertEqual(wtypes.Unset, chassis.description)
self.assertEqual(atypes.Unset, chassis.description)
def test_chassis_sample(self):
expected_description = 'Sample chassis'

View File

@ -24,7 +24,6 @@ from oslo_config import cfg
from oslo_utils import timeutils
from oslo_utils import uuidutils
from testtools import matchers
from wsme import types as wtypes
from ironic.api.controllers import base as api_base
from ironic.api.controllers import v1 as api_v1
@ -32,6 +31,7 @@ from ironic.api.controllers.v1 import node as api_node
from ironic.api.controllers.v1 import notification_utils
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api.controllers.v1 import versions
from ironic.api import types as atypes
from ironic.common import boot_devices
from ironic.common import components
from ironic.common import driver_factory
@ -54,7 +54,7 @@ class TestNodeObject(base.TestCase):
node_dict = test_api_utils.node_post_data()
del node_dict['instance_uuid']
node = api_node.Node(**node_dict)
self.assertEqual(wtypes.Unset, node.instance_uuid)
self.assertEqual(atypes.Unset, node.instance_uuid)
class TestListNodes(test_api_base.BaseApiTest):

View File

@ -14,9 +14,9 @@
import mock
from oslo_utils import uuidutils
from wsme import types as wtypes
from ironic.api.controllers.v1 import notification_utils as notif_utils
from ironic.api import types as atypes
from ironic.objects import fields
from ironic.objects import notification
from ironic.tests import base as tests_base
@ -102,7 +102,7 @@ class APINotifyTestCase(tests_base.TestCase):
test_status = fields.NotificationStatus.SUCCESS
notif_utils._emit_api_notification(self.context, node, 'create',
test_level, test_status,
chassis_uuid=wtypes.Unset)
chassis_uuid=atypes.Unset)
init_kwargs = self.node_notify_mock.call_args[1]
payload = init_kwargs['payload']
self.assertIsNone(payload.chassis_uuid)

View File

@ -23,7 +23,6 @@ from oslo_config import cfg
from oslo_utils import timeutils
from oslo_utils import uuidutils
from testtools import matchers
from wsme import types as wtypes
from ironic.api.controllers import base as api_base
from ironic.api.controllers import v1 as api_v1
@ -31,6 +30,7 @@ from ironic.api.controllers.v1 import notification_utils
from ironic.api.controllers.v1 import port as api_port
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api.controllers.v1 import versions
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common import policy
from ironic.common import states
@ -85,7 +85,7 @@ class TestPortObject(base.TestCase):
portgroup_uuid=None)
del port_dict['extra']
port = api_port.Port(**port_dict)
self.assertEqual(wtypes.Unset, port.extra)
self.assertEqual(atypes.Unset, port.extra)
@mock.patch.object(api_utils, 'allow_port_physical_network', autospec=True)
@ -1150,12 +1150,12 @@ class TestPatch(test_api_base.BaseApiTest):
obj_fields.NotificationLevel.INFO,
obj_fields.NotificationStatus.START,
node_uuid=self.node.uuid,
portgroup_uuid=wtypes.Unset),
portgroup_uuid=atypes.Unset),
mock.call(mock.ANY, mock.ANY, 'update',
obj_fields.NotificationLevel.INFO,
obj_fields.NotificationStatus.END,
node_uuid=self.node.uuid,
portgroup_uuid=wtypes.Unset)])
portgroup_uuid=atypes.Unset)])
def test_update_byaddress_not_allowed(self, mock_upd):
response = self.patch_json('/ports/%s' % self.port.address,
@ -1214,12 +1214,12 @@ class TestPatch(test_api_base.BaseApiTest):
obj_fields.NotificationLevel.INFO,
obj_fields.NotificationStatus.START,
node_uuid=self.node.uuid,
portgroup_uuid=wtypes.Unset),
portgroup_uuid=atypes.Unset),
mock.call(mock.ANY, mock.ANY, 'update',
obj_fields.NotificationLevel.ERROR,
obj_fields.NotificationStatus.ERROR,
node_uuid=self.node.uuid,
portgroup_uuid=wtypes.Unset)])
portgroup_uuid=atypes.Unset)])
def test_replace_node_uuid(self, mock_upd):
response = self.patch_json('/ports/%s' % self.port.uuid,

View File

@ -22,13 +22,13 @@ from oslo_config import cfg
from oslo_utils import timeutils
from oslo_utils import uuidutils
from testtools.matchers import HasLength
from wsme import types as wtypes
from ironic.api.controllers import base as api_base
from ironic.api.controllers import v1 as api_v1
from ironic.api.controllers.v1 import notification_utils
from ironic.api.controllers.v1 import portgroup as api_portgroup
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common import states
from ironic.common import utils as common_utils
@ -57,7 +57,7 @@ class TestPortgroupObject(base.TestCase):
portgroup_dict = apiutils.portgroup_post_data(node_id=None)
del portgroup_dict['extra']
portgroup = api_portgroup.Portgroup(**portgroup_dict)
self.assertEqual(wtypes.Unset, portgroup.extra)
self.assertEqual(atypes.Unset, portgroup.extra)
class TestListPortgroups(test_api_base.BaseApiTest):

View File

@ -23,6 +23,7 @@ import webtest
import wsme
from ironic.api.controllers.v1 import types
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common import utils
from ironic.tests import base
@ -88,7 +89,7 @@ class TestUuidOrNameType(base.TestCase):
class MyBaseType(object):
"""Helper class, patched by objects of type MyPatchType"""
mandatory = wsme.wsattr(str, mandatory=True)
mandatory = atypes.wsattr(str, mandatory=True)
class MyPatchType(types.JsonPatchType):

View File

@ -26,6 +26,7 @@ import wsme
from ironic import api
from ironic.api.controllers.v1 import node as api_node
from ironic.api.controllers.v1 import utils
from ironic.api import types as atypes
from ironic.common import exception
from ironic.common import policy
from ironic.common import states
@ -693,7 +694,7 @@ class TestVendorPassthru(base.TestCase):
'fake-data', 'fake-topic')
self.assertIsInstance(response, wsme.api.Response)
self.assertEqual('SpongeBob', response.obj)
self.assertEqual(response.return_type, wsme.types.Unset)
self.assertEqual(response.return_type, atypes.Unset)
sc = http_client.ACCEPTED if async_call else http_client.OK
self.assertEqual(sc, response.status_code)

View File

@ -23,13 +23,13 @@ import mock
from oslo_config import cfg
from oslo_utils import timeutils
from oslo_utils import uuidutils
from wsme import types as wtypes
from ironic.api.controllers import base as api_base
from ironic.api.controllers import v1 as api_v1
from ironic.api.controllers.v1 import notification_utils
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api.controllers.v1 import volume_connector as api_volume_connector
from ironic.api import types as atypes
from ironic.common import exception
from ironic.conductor import rpcapi
from ironic import objects
@ -54,7 +54,7 @@ class TestVolumeConnectorObject(base.TestCase):
connector_dict = apiutils.volume_connector_post_data(node_id=None)
del connector_dict['extra']
connector = api_volume_connector.VolumeConnector(**connector_dict)
self.assertEqual(wtypes.Unset, connector.extra)
self.assertEqual(atypes.Unset, connector.extra)
class TestListVolumeConnectors(test_api_base.BaseApiTest):

View File

@ -23,13 +23,13 @@ import mock
from oslo_config import cfg
from oslo_utils import timeutils
from oslo_utils import uuidutils
from wsme import types as wtypes
from ironic.api.controllers import base as api_base
from ironic.api.controllers import v1 as api_v1
from ironic.api.controllers.v1 import notification_utils
from ironic.api.controllers.v1 import utils as api_utils
from ironic.api.controllers.v1 import volume_target as api_volume_target
from ironic.api import types as atypes
from ironic.common import exception
from ironic.conductor import rpcapi
from ironic import objects
@ -54,7 +54,7 @@ class TestVolumeTargetObject(base.TestCase):
target_dict = apiutils.volume_target_post_data(node_id=None)
del target_dict['extra']
target = api_volume_target.VolumeTarget(**target_dict)
self.assertEqual(wtypes.Unset, target.extra)
self.assertEqual(atypes.Unset, target.extra)
class TestListVolumeTargets(test_api_base.BaseApiTest):