Remove Link type

This type is only used for output response formatting, not for input
validation, so it can be replaced with a basic dict equivalent without
disruption.

This results in fields in WSME types which shouldn't be handled by
WSME because they are already in a dict format. This is handled by
relaxing the validation in the (ex-WSME) types so that a None type
means that WSME shouldn't serialize that attribute. This will allow
old style type serialization to be mixed with plain dicts during the
transition period.

Story: 1651346
Task: 10551

Change-Id: Ifae9bd005fb7cf951b069ade0c92b8d61e095e0f
This commit is contained in:
Steve Baker 2020-07-16 14:41:20 +12:00
parent 5e12d502fe
commit b1328fa996
18 changed files with 247 additions and 264 deletions

View File

@ -14,8 +14,6 @@
# under the License. # under the License.
from ironic import api 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): def build_url(resource, resource_args, bookmark=False, base_url=None):
@ -30,28 +28,15 @@ def build_url(resource, resource_args, bookmark=False, base_url=None):
return template % {'url': base_url, 'res': resource, 'args': resource_args} return template % {'url': base_url, 'res': resource, 'args': resource_args}
class Link(base.Base): def make_link(rel_name, url, resource, resource_args,
"""A link representation.""" bookmark=False, type=None):
"""Build a dict representing a link"""
href = str href = build_url(resource, resource_args,
"""The url of a link.""" bookmark=bookmark, base_url=url)
l = {
rel = str 'href': href,
"""The name of a link.""" 'rel': rel_name
}
type = str if type:
"""Indicates the type of document/link.""" l['type'] = type
return l
@staticmethod
def make_link(rel_name, url, resource, resource_args,
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)
@classmethod
def sample(cls):
sample = cls(href="http://localhost:6385/chassis/"
"eaaca217-e7d8-47b4-bb41-3f99f20eed89",
rel="bookmark")
return sample

View File

@ -77,158 +77,158 @@ class V1(base.Base):
media_types = [MediaType] media_types = [MediaType]
"""An array of supported media types for this version""" """An array of supported media types for this version"""
links = [link.Link] links = None
"""Links that point to a specific URL for this version and documentation""" """Links that point to a specific URL for this version and documentation"""
chassis = [link.Link] chassis = None
"""Links to the chassis resource""" """Links to the chassis resource"""
nodes = [link.Link] nodes = None
"""Links to the nodes resource""" """Links to the nodes resource"""
ports = [link.Link] ports = None
"""Links to the ports resource""" """Links to the ports resource"""
portgroups = [link.Link] portgroups = None
"""Links to the portgroups resource""" """Links to the portgroups resource"""
drivers = [link.Link] drivers = None
"""Links to the drivers resource""" """Links to the drivers resource"""
volume = [link.Link] volume = None
"""Links to the volume resource""" """Links to the volume resource"""
lookup = [link.Link] lookup = None
"""Links to the lookup resource""" """Links to the lookup resource"""
heartbeat = [link.Link] heartbeat = None
"""Links to the heartbeat resource""" """Links to the heartbeat resource"""
conductors = [link.Link] conductors = None
"""Links to the conductors resource""" """Links to the conductors resource"""
allocations = [link.Link] allocations = None
"""Links to the allocations resource""" """Links to the allocations resource"""
deploy_templates = [link.Link] deploy_templates = None
"""Links to the deploy_templates resource""" """Links to the deploy_templates resource"""
version = version.Version version = version.Version
"""Version discovery information.""" """Version discovery information."""
events = [link.Link] events = None
"""Links to the events resource""" """Links to the events resource"""
@staticmethod @staticmethod
def convert(): def convert():
v1 = V1() v1 = V1()
v1.id = "v1" v1.id = "v1"
v1.links = [link.Link.make_link('self', api.request.public_url, v1.links = [link.make_link('self', api.request.public_url,
'v1', '', bookmark=True), 'v1', '', bookmark=True),
link.Link.make_link('describedby', link.make_link('describedby',
'https://docs.openstack.org', 'https://docs.openstack.org',
'/ironic/latest/contributor/', '/ironic/latest/contributor/',
'webapi.html', 'webapi.html',
bookmark=True, type='text/html') bookmark=True, type='text/html')
] ]
v1.media_types = [MediaType('application/json', v1.media_types = [MediaType('application/json',
'application/vnd.openstack.ironic.v1+json')] 'application/vnd.openstack.ironic.v1+json')]
v1.chassis = [link.Link.make_link('self', api.request.public_url, v1.chassis = [link.make_link('self', api.request.public_url,
'chassis', ''), 'chassis', ''),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'chassis', '', 'chassis', '',
bookmark=True) bookmark=True)
] ]
v1.nodes = [link.Link.make_link('self', api.request.public_url, v1.nodes = [link.make_link('self', api.request.public_url,
'nodes', ''), 'nodes', ''),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'nodes', '', 'nodes', '',
bookmark=True) bookmark=True)
] ]
v1.ports = [link.Link.make_link('self', api.request.public_url, v1.ports = [link.make_link('self', api.request.public_url,
'ports', ''), 'ports', ''),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'ports', '', 'ports', '',
bookmark=True) bookmark=True)
] ]
if utils.allow_portgroups(): if utils.allow_portgroups():
v1.portgroups = [ v1.portgroups = [
link.Link.make_link('self', api.request.public_url, link.make_link('self', api.request.public_url,
'portgroups', ''), 'portgroups', ''),
link.Link.make_link('bookmark', api.request.public_url, link.make_link('bookmark', api.request.public_url,
'portgroups', '', bookmark=True) 'portgroups', '', bookmark=True)
] ]
v1.drivers = [link.Link.make_link('self', api.request.public_url, v1.drivers = [link.make_link('self', api.request.public_url,
'drivers', ''), 'drivers', ''),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'drivers', '', 'drivers', '',
bookmark=True) bookmark=True)
] ]
if utils.allow_volume(): if utils.allow_volume():
v1.volume = [ v1.volume = [
link.Link.make_link('self', link.make_link('self',
api.request.public_url, api.request.public_url,
'volume', ''), 'volume', ''),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'volume', '', 'volume', '',
bookmark=True) bookmark=True)
] ]
if utils.allow_ramdisk_endpoints(): if utils.allow_ramdisk_endpoints():
v1.lookup = [link.Link.make_link('self', api.request.public_url, v1.lookup = [link.make_link('self', api.request.public_url,
'lookup', ''), 'lookup', ''),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'lookup', '', 'lookup', '',
bookmark=True) bookmark=True)
] ]
v1.heartbeat = [link.Link.make_link('self', v1.heartbeat = [link.make_link('self',
api.request.public_url, api.request.public_url,
'heartbeat', ''), 'heartbeat', ''),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'heartbeat', '', 'heartbeat', '',
bookmark=True) bookmark=True)
] ]
if utils.allow_expose_conductors(): if utils.allow_expose_conductors():
v1.conductors = [link.Link.make_link('self', v1.conductors = [link.make_link('self',
api.request.public_url, api.request.public_url,
'conductors', ''), 'conductors', ''),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'conductors', '', 'conductors', '',
bookmark=True) bookmark=True)
] ]
if utils.allow_allocations(): if utils.allow_allocations():
v1.allocations = [link.Link.make_link('self', v1.allocations = [link.make_link('self',
api.request.public_url, api.request.public_url,
'allocations', ''), 'allocations', ''),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'allocations', '', 'allocations', '',
bookmark=True) bookmark=True)
] ]
if utils.allow_expose_events(): if utils.allow_expose_events():
v1.events = [link.Link.make_link('self', api.request.public_url, v1.events = [link.make_link('self', api.request.public_url,
'events', ''), 'events', ''),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'events', '', 'events', '',
bookmark=True) bookmark=True)
] ]
if utils.allow_deploy_templates(): if utils.allow_deploy_templates():
v1.deploy_templates = [ v1.deploy_templates = [
link.Link.make_link('self', link.make_link('self',
api.request.public_url, api.request.public_url,
'deploy_templates', ''), 'deploy_templates', ''),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'deploy_templates', '', 'deploy_templates', '',
bookmark=True) bookmark=True)
] ]
v1.version = version.default_version() v1.version = version.default_version()
return v1 return v1

View File

@ -65,7 +65,7 @@ class Allocation(base.APIBase):
name = atypes.wsattr(str) name = atypes.wsattr(str)
"""The logical name for this allocation""" """The logical name for this allocation"""
links = atypes.wsattr([link.Link], readonly=True) links = None
"""A list containing a self link and associated allocation links""" """A list containing a self link and associated allocation links"""
state = atypes.wsattr(str, readonly=True) state = atypes.wsattr(str, readonly=True)
@ -107,9 +107,9 @@ class Allocation(base.APIBase):
# This field is only used in POST, never return it. # This field is only used in POST, never return it.
allocation.node = atypes.Unset allocation.node = atypes.Unset
allocation.links = [ allocation.links = [
link.Link.make_link('self', url, 'allocations', allocation.uuid), link.make_link('self', url, 'allocations', allocation.uuid),
link.Link.make_link('bookmark', url, 'allocations', link.make_link('bookmark', url, 'allocations',
allocation.uuid, bookmark=True) allocation.uuid, bookmark=True)
] ]
return allocation return allocation

View File

@ -37,7 +37,7 @@ class BIOSSetting(base.APIBase):
value = atypes.wsattr(str) value = atypes.wsattr(str)
links = atypes.wsattr([link.Link], readonly=True) links = None
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.fields = [] self.fields = []
@ -52,11 +52,11 @@ class BIOSSetting(base.APIBase):
def _convert_with_links(bios, node_uuid, url): def _convert_with_links(bios, node_uuid, url):
"""Add links to the bios setting.""" """Add links to the bios setting."""
name = bios.name name = bios.name
bios.links = [link.Link.make_link('self', url, 'nodes', bios.links = [link.make_link('self', url, 'nodes',
"%s/bios/%s" % (node_uuid, name)), "%s/bios/%s" % (node_uuid, name)),
link.Link.make_link('bookmark', url, 'nodes', link.make_link('bookmark', url, 'nodes',
"%s/bios/%s" % (node_uuid, name), "%s/bios/%s" % (node_uuid, name),
bookmark=True)] bookmark=True)]
return bios return bios
@classmethod @classmethod

View File

@ -58,10 +58,10 @@ class Chassis(base.APIBase):
extra = {str: types.jsontype} extra = {str: types.jsontype}
"""The metadata of the chassis""" """The metadata of the chassis"""
links = atypes.wsattr([link.Link], readonly=True) links = None
"""A list containing a self link and associated chassis links""" """A list containing a self link and associated chassis links"""
nodes = atypes.wsattr([link.Link], readonly=True) nodes = None
"""Links to the collection of nodes contained in this chassis""" """Links to the collection of nodes contained in this chassis"""
def __init__(self, **kwargs): def __init__(self, **kwargs):
@ -76,23 +76,23 @@ class Chassis(base.APIBase):
@staticmethod @staticmethod
def _convert_with_links(chassis, url, fields=None): def _convert_with_links(chassis, url, fields=None):
if fields is None: if fields is None:
chassis.nodes = [link.Link.make_link('self', chassis.nodes = [link.make_link('self',
url, url,
'chassis', 'chassis',
chassis.uuid + "/nodes"), chassis.uuid + "/nodes"),
link.Link.make_link('bookmark', link.make_link('bookmark',
url, url,
'chassis', 'chassis',
chassis.uuid + "/nodes", chassis.uuid + "/nodes",
bookmark=True) bookmark=True)
] ]
chassis.links = [link.Link.make_link('self', chassis.links = [link.make_link('self',
url, url,
'chassis', chassis.uuid), 'chassis', chassis.uuid),
link.Link.make_link('bookmark', link.make_link('bookmark',
url, url,
'chassis', chassis.uuid, 'chassis', chassis.uuid,
bookmark=True) bookmark=True)
] ]
return chassis return chassis

View File

@ -52,5 +52,5 @@ class Collection(base.Base):
'args': q_args, 'limit': limit, 'args': q_args, 'limit': limit,
'marker': getattr(self.collection[-1], self.get_key_field())} 'marker': getattr(self.collection[-1], self.get_key_field())}
return link.Link.make_link('next', api.request.public_url, return link.make_link('next', api.request.public_url,
resource_url, next_args).href resource_url, next_args)['href']

View File

@ -53,7 +53,7 @@ class Conductor(base.APIBase):
drivers = atypes.wsattr([str]) drivers = atypes.wsattr([str])
"""The drivers enabled on this conductor""" """The drivers enabled on this conductor"""
links = atypes.wsattr([link.Link]) links = None
"""A list containing a self link and associated conductor links""" """A list containing a self link and associated conductor links"""
def __init__(self, **kwargs): def __init__(self, **kwargs):
@ -72,11 +72,11 @@ class Conductor(base.APIBase):
@staticmethod @staticmethod
def _convert_with_links(conductor, url, fields=None): def _convert_with_links(conductor, url, fields=None):
conductor.links = [link.Link.make_link('self', url, 'conductors', conductor.links = [link.make_link('self', url, 'conductors',
conductor.hostname), conductor.hostname),
link.Link.make_link('bookmark', url, 'conductors', link.make_link('bookmark', url, 'conductors',
conductor.hostname, conductor.hostname,
bookmark=True)] bookmark=True)]
return conductor return conductor
@classmethod @classmethod

View File

@ -82,7 +82,7 @@ class DeployTemplate(base.APIBase):
steps = atypes.wsattr([DeployStepType], mandatory=True) steps = atypes.wsattr([DeployStepType], mandatory=True)
"""The deploy steps of this deploy template.""" """The deploy steps of this deploy template."""
links = atypes.wsattr([link.Link]) links = None
"""A list containing a self link and associated deploy template links.""" """A list containing a self link and associated deploy template links."""
extra = {str: types.jsontype} extra = {str: types.jsontype}
@ -148,11 +148,11 @@ class DeployTemplate(base.APIBase):
@staticmethod @staticmethod
def _convert_with_links(template, url, fields=None): def _convert_with_links(template, url, fields=None):
template.links = [ template.links = [
link.Link.make_link('self', url, 'deploy_templates', link.make_link('self', url, 'deploy_templates',
template.uuid), template.uuid),
link.Link.make_link('bookmark', url, 'deploy_templates', link.make_link('bookmark', url, 'deploy_templates',
template.uuid, template.uuid,
bookmark=True) bookmark=True)
] ]
return template return template

View File

@ -96,10 +96,10 @@ class Driver(base.Base):
type = str type = str
"""Whether the driver is classic or dynamic (hardware type)""" """Whether the driver is classic or dynamic (hardware type)"""
links = atypes.wsattr([link.Link], readonly=True) links = None
"""A list containing self and bookmark links""" """A list containing self and bookmark links"""
properties = atypes.wsattr([link.Link], readonly=True) properties = None
"""A list containing links to driver properties""" """A list containing links to driver properties"""
"""Default interface for a hardware type""" """Default interface for a hardware type"""
@ -146,23 +146,23 @@ class Driver(base.Base):
driver.name = name driver.name = name
driver.hosts = hosts driver.hosts = hosts
driver.links = [ driver.links = [
link.Link.make_link('self', link.make_link('self',
api.request.public_url, api.request.public_url,
'drivers', name), 'drivers', name),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'drivers', name, 'drivers', name,
bookmark=True) bookmark=True)
] ]
if api_utils.allow_links_node_states_and_driver_properties(): if api_utils.allow_links_node_states_and_driver_properties():
driver.properties = [ driver.properties = [
link.Link.make_link('self', link.make_link('self',
api.request.public_url, api.request.public_url,
'drivers', name + "/properties"), 'drivers', name + "/properties"),
link.Link.make_link('bookmark', link.make_link('bookmark',
api.request.public_url, api.request.public_url,
'drivers', name + "/properties", 'drivers', name + "/properties",
bookmark=True) bookmark=True)
] ]
if api_utils.allow_dynamic_drivers(): if api_utils.allow_dynamic_drivers():

View File

@ -343,7 +343,7 @@ class Indicator(base.APIBase):
states = atypes.ArrayType(str) states = atypes.ArrayType(str)
links = atypes.wsattr([link.Link], readonly=True) links = None
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.name = kwargs.get('name') self.name = kwargs.get('name')
@ -355,11 +355,11 @@ class Indicator(base.APIBase):
def _convert_with_links(node_uuid, indicator, url): def _convert_with_links(node_uuid, indicator, url):
"""Add links to the indicator.""" """Add links to the indicator."""
indicator.links = [ indicator.links = [
link.Link.make_link( link.make_link(
'self', url, 'nodes', 'self', url, 'nodes',
'%s/management/indicators/%s' % ( '%s/management/indicators/%s' % (
node_uuid, indicator.name)), node_uuid, indicator.name)),
link.Link.make_link( link.make_link(
'bookmark', url, 'nodes', 'bookmark', url, 'nodes',
'%s/management/indicators/%s' % ( '%s/management/indicators/%s' % (
node_uuid, indicator.name), node_uuid, indicator.name),
@ -1206,19 +1206,19 @@ class Node(base.APIBase):
_set_chassis_uuid) _set_chassis_uuid)
"""The UUID of the chassis this node belongs""" """The UUID of the chassis this node belongs"""
links = atypes.wsattr([link.Link], readonly=True) links = None
"""A list containing a self link and associated node links""" """A list containing a self link and associated node links"""
ports = atypes.wsattr([link.Link], readonly=True) ports = None
"""Links to the collection of ports on this node""" """Links to the collection of ports on this node"""
portgroups = atypes.wsattr([link.Link], readonly=True) portgroups = None
"""Links to the collection of portgroups on this node""" """Links to the collection of portgroups on this node"""
volume = atypes.wsattr([link.Link], readonly=True) volume = None
"""Links to endpoint for retrieving volume resources on this node""" """Links to endpoint for retrieving volume resources on this node"""
states = atypes.wsattr([link.Link], readonly=True) states = None
"""Links to endpoint for retrieving and setting node states""" """Links to endpoint for retrieving and setting node states"""
boot_interface = atypes.wsattr(str) boot_interface = atypes.wsattr(str)
@ -1336,38 +1336,38 @@ class Node(base.APIBase):
def _convert_with_links(node, url, fields=None, show_states_links=True, def _convert_with_links(node, url, fields=None, show_states_links=True,
show_portgroups=True, show_volume=True): show_portgroups=True, show_volume=True):
if fields is None: if fields is None:
node.ports = [link.Link.make_link('self', url, 'nodes', node.ports = [link.make_link('self', url, 'nodes',
node.uuid + "/ports"), node.uuid + "/ports"),
link.Link.make_link('bookmark', url, 'nodes', link.make_link('bookmark', url, 'nodes',
node.uuid + "/ports", node.uuid + "/ports",
bookmark=True) bookmark=True)
] ]
if show_states_links: if show_states_links:
node.states = [link.Link.make_link('self', url, 'nodes', node.states = [link.make_link('self', url, 'nodes',
node.uuid + "/states"), node.uuid + "/states"),
link.Link.make_link('bookmark', url, 'nodes', link.make_link('bookmark', url, 'nodes',
node.uuid + "/states", node.uuid + "/states",
bookmark=True)] bookmark=True)]
if show_portgroups: if show_portgroups:
node.portgroups = [ node.portgroups = [
link.Link.make_link('self', url, 'nodes', link.make_link('self', url, 'nodes',
node.uuid + "/portgroups"), node.uuid + "/portgroups"),
link.Link.make_link('bookmark', url, 'nodes', link.make_link('bookmark', url, 'nodes',
node.uuid + "/portgroups", node.uuid + "/portgroups",
bookmark=True)] bookmark=True)]
if show_volume: if show_volume:
node.volume = [ node.volume = [
link.Link.make_link('self', url, 'nodes', link.make_link('self', url, 'nodes',
node.uuid + "/volume"), node.uuid + "/volume"),
link.Link.make_link('bookmark', url, 'nodes', link.make_link('bookmark', url, 'nodes',
node.uuid + "/volume", node.uuid + "/volume",
bookmark=True)] bookmark=True)]
node.links = [link.Link.make_link('self', url, 'nodes', node.links = [link.make_link('self', url, 'nodes',
node.uuid), node.uuid),
link.Link.make_link('bookmark', url, 'nodes', link.make_link('bookmark', url, 'nodes',
node.uuid, bookmark=True) node.uuid, bookmark=True)
] ]
return node return node

View File

@ -155,7 +155,7 @@ class Port(base.APIBase):
physical_network = atypes.StringType(max_length=64) physical_network = atypes.StringType(max_length=64)
"""The name of the physical network to which this port is connected.""" """The name of the physical network to which this port is connected."""
links = atypes.wsattr([link.Link], readonly=True) links = None
"""A list containing a self link and associated port links""" """A list containing a self link and associated port links"""
is_smartnic = types.boolean is_smartnic = types.boolean
@ -199,11 +199,11 @@ class Port(base.APIBase):
url = api.request.public_url url = api.request.public_url
port.links = [link.Link.make_link('self', url, port.links = [link.make_link('self', url,
'ports', port.uuid), 'ports', port.uuid),
link.Link.make_link('bookmark', url, link.make_link('bookmark', url,
'ports', port.uuid, 'ports', port.uuid,
bookmark=True) bookmark=True)
] ]
if not sanitize: if not sanitize:

View File

@ -90,7 +90,7 @@ class Portgroup(base.APIBase):
name = atypes.wsattr(str) name = atypes.wsattr(str)
"""The logical name for this portgroup""" """The logical name for this portgroup"""
links = atypes.wsattr([link.Link], readonly=True) links = None
"""A list containing a self link and associated portgroup links""" """A list containing a self link and associated portgroup links"""
standalone_ports_supported = types.boolean standalone_ports_supported = types.boolean
@ -105,7 +105,7 @@ class Portgroup(base.APIBase):
properties = {str: types.jsontype} properties = {str: types.jsontype}
"""This portgroup's properties""" """This portgroup's properties"""
ports = atypes.wsattr([link.Link], readonly=True) ports = None
"""Links to the collection of ports of this portgroup""" """Links to the collection of ports of this portgroup"""
def __init__(self, **kwargs): def __init__(self, **kwargs):
@ -133,20 +133,20 @@ class Portgroup(base.APIBase):
"""Add links to the portgroup.""" """Add links to the portgroup."""
if fields is None: if fields is None:
portgroup.ports = [ portgroup.ports = [
link.Link.make_link('self', url, 'portgroups', link.make_link('self', url, 'portgroups',
portgroup.uuid + "/ports"), portgroup.uuid + "/ports"),
link.Link.make_link('bookmark', url, 'portgroups', link.make_link('bookmark', url, 'portgroups',
portgroup.uuid + "/ports", bookmark=True) portgroup.uuid + "/ports", bookmark=True)
] ]
# never expose the node_id attribute # never expose the node_id attribute
portgroup.node_id = atypes.Unset portgroup.node_id = atypes.Unset
portgroup.links = [link.Link.make_link('self', url, portgroup.links = [link.make_link('self', url,
'portgroups', portgroup.uuid), 'portgroups', portgroup.uuid),
link.Link.make_link('bookmark', url, link.make_link('bookmark', url,
'portgroups', portgroup.uuid, 'portgroups', portgroup.uuid,
bookmark=True) bookmark=True)
] ]
return portgroup return portgroup

View File

@ -14,7 +14,6 @@
# under the License. # under the License.
from ironic.api.controllers import base from ironic.api.controllers import base
from ironic.api.controllers import link
class State(base.APIBase): class State(base.APIBase):
@ -28,5 +27,5 @@ class State(base.APIBase):
available = [str] available = [str]
"""A list of available states it is able to transition to""" """A list of available states it is able to transition to"""
links = [link.Link] links = None
"""A list containing a self link and associated state links""" """A list containing a self link and associated state links"""

View File

@ -24,7 +24,6 @@ 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_connector
from ironic.api.controllers.v1 import volume_target from ironic.api.controllers.v1 import volume_target
from ironic.api import expose from ironic.api import expose
from ironic.api import types as atypes
from ironic.common import exception from ironic.common import exception
from ironic.common import policy from ironic.common import policy
@ -36,13 +35,13 @@ class Volume(base.APIBase):
targets controllers. targets controllers.
""" """
links = atypes.wsattr([link.Link], readonly=True) links = None
"""A list containing a self link and associated volume links""" """A list containing a self link and associated volume links"""
connectors = atypes.wsattr([link.Link], readonly=True) connectors = None
"""Links to the volume connectors resource""" """Links to the volume connectors resource"""
targets = atypes.wsattr([link.Link], readonly=True) targets = None
"""Links to the volume targets resource""" """Links to the volume targets resource"""
@staticmethod @staticmethod
@ -57,19 +56,19 @@ class Volume(base.APIBase):
args = '' args = ''
volume.links = [ volume.links = [
link.Link.make_link('self', url, resource, args), link.make_link('self', url, resource, args),
link.Link.make_link('bookmark', url, resource, args, link.make_link('bookmark', url, resource, args,
bookmark=True)] bookmark=True)]
volume.connectors = [ volume.connectors = [
link.Link.make_link('self', url, resource, args + 'connectors'), link.make_link('self', url, resource, args + 'connectors'),
link.Link.make_link('bookmark', url, resource, args + 'connectors', link.make_link('bookmark', url, resource, args + 'connectors',
bookmark=True)] bookmark=True)]
volume.targets = [ volume.targets = [
link.Link.make_link('self', url, resource, args + 'targets'), link.make_link('self', url, resource, args + 'targets'),
link.Link.make_link('bookmark', url, resource, args + 'targets', link.make_link('bookmark', url, resource, args + 'targets',
bookmark=True)] bookmark=True)]
return volume return volume

View File

@ -87,7 +87,7 @@ class VolumeConnector(base.APIBase):
_set_node_identifiers, mandatory=True) _set_node_identifiers, mandatory=True)
"""The UUID of the node this volume connector belongs to""" """The UUID of the node this volume connector belongs to"""
links = atypes.wsattr([link.Link], readonly=True) links = None
"""A list containing a self link and associated volume connector links""" """A list containing a self link and associated volume connector links"""
def __init__(self, **kwargs): def __init__(self, **kwargs):
@ -117,13 +117,13 @@ class VolumeConnector(base.APIBase):
@staticmethod @staticmethod
def _convert_with_links(connector, url): def _convert_with_links(connector, url):
connector.links = [link.Link.make_link('self', url, connector.links = [link.make_link('self', url,
'volume/connectors', 'volume/connectors',
connector.uuid), connector.uuid),
link.Link.make_link('bookmark', url, link.make_link('bookmark', url,
'volume/connectors', 'volume/connectors',
connector.uuid, connector.uuid,
bookmark=True) bookmark=True)
] ]
return connector return connector

View File

@ -94,7 +94,7 @@ class VolumeTarget(base.APIBase):
_set_node_identifiers, mandatory=True) _set_node_identifiers, mandatory=True)
"""The UUID of the node this volume target belongs to""" """The UUID of the node this volume target belongs to"""
links = atypes.wsattr([link.Link], readonly=True) links = None
"""A list containing a self link and associated volume target links""" """A list containing a self link and associated volume target links"""
def __init__(self, **kwargs): def __init__(self, **kwargs):
@ -124,13 +124,13 @@ class VolumeTarget(base.APIBase):
@staticmethod @staticmethod
def _convert_with_links(target, url): def _convert_with_links(target, url):
target.links = [link.Link.make_link('self', url, target.links = [link.make_link('self', url,
'volume/targets', 'volume/targets',
target.uuid), target.uuid),
link.Link.make_link('bookmark', url, link.make_link('bookmark', url,
'volume/targets', 'volume/targets',
target.uuid, target.uuid,
bookmark=True) bookmark=True)
] ]
return target return target

View File

@ -27,7 +27,7 @@ class Version(base.Base):
id = str id = str
"""The ID of the (major) version, also acts as the release number""" """The ID of the (major) version, also acts as the release number"""
links = [link.Link] links = None
"""A Link that point to a specific version of the API""" """A Link that point to a specific version of the API"""
status = str status = str
@ -47,8 +47,8 @@ class Version(base.Base):
def __init__(self, id, min_version, version, status='CURRENT'): def __init__(self, id, min_version, version, status='CURRENT'):
self.id = id self.id = id
self.links = [link.Link.make_link('self', api.request.public_url, self.links = [link.make_link('self', api.request.public_url,
self.id, '', bookmark=True)] self.id, '', bookmark=True)]
self.status = status self.status = status
self.version = version self.version = version
self.min_version = min_version self.min_version = min_version

View File

@ -280,7 +280,7 @@ Unset = UnsetType()
def validate_value(datatype, value): def validate_value(datatype, value):
if value in (Unset, None): if value in (Unset, None) or datatype is None:
return value return value
# Try to promote the data type to one of our complex types. # Try to promote the data type to one of our complex types.