[PTP dual NIC config] 2nd review of PTP data model
In the original review of PTP data model: https://review.opendev.org/c/starlingx/config/+/819391 the relationships between ihost:PtpInstances and Interface:PtpInterfaces need to be many- to-many like between PtpParameters:PtpParameterOwners, in order to allow the same host run different PTP instances (services) as well for interfaces. Test Plan: PASS: Fresh install shows all new tables and relationships while system is responsive for other usual tasks (smoke test) Regression: PASS: All the previous test cases for PTP tables keep running with success. New test cases are planned to support the new relationships. Story: 2009248 Task: 44146 Signed-off-by: Douglas Henrique Koerich <douglashenrique.koerich@windriver.com> Change-Id: Id03881cf354e77862a770fc9b71b6bb0ab14aa19
This commit is contained in:
parent
a291b5a4cc
commit
37aec5c439
|
@ -70,7 +70,9 @@ from cgtsclient.v1 import pci_device
|
|||
from cgtsclient.v1 import port
|
||||
from cgtsclient.v1 import ptp
|
||||
from cgtsclient.v1 import ptp_instance
|
||||
from cgtsclient.v1 import ptp_instance_map
|
||||
from cgtsclient.v1 import ptp_interface
|
||||
from cgtsclient.v1 import ptp_interface_map
|
||||
from cgtsclient.v1 import ptp_parameter
|
||||
from cgtsclient.v1 import ptp_paramownership
|
||||
from cgtsclient.v1 import registry_image
|
||||
|
@ -123,7 +125,9 @@ class Client(http.HTTPClient):
|
|||
self.intp = intp.intpManager(self)
|
||||
self.ptp = ptp.ptpManager(self)
|
||||
self.ptp_instance = ptp_instance.PtpInstanceManager(self)
|
||||
self.ptp_instance_map = ptp_instance_map.PtpInstanceMapManager(self)
|
||||
self.ptp_interface = ptp_interface.PtpInterfaceManager(self)
|
||||
self.ptp_interface_map = ptp_interface_map.PtpInterfaceMapManager(self)
|
||||
self.ptp_parameter = ptp_parameter.PtpParameterManager(self)
|
||||
self.ptp_paramownership = \
|
||||
ptp_paramownership.PtpParameterOwnershipManager(self)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
########################################################################
|
||||
#
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
########################################################################
|
||||
|
||||
from cgtsclient.common import base
|
||||
from cgtsclient import exc
|
||||
|
||||
|
||||
CREATION_ATTRIBUTES = ['host_id', 'ptp_instance_id']
|
||||
|
||||
|
||||
class PtpInstanceMap(base.Resource):
|
||||
def __repr__(self):
|
||||
return "<PtpInstanceMap %s>" % self._info
|
||||
|
||||
|
||||
class PtpInstanceMapManager(base.Manager):
|
||||
resource_class = PtpInstanceMap
|
||||
|
||||
def _path(self, ptp_instance_map_id=None):
|
||||
return '/v1/ptp_instance_maps/%s' % ptp_instance_map_id \
|
||||
if ptp_instance_map_id else '/v1/ptp_instance_maps'
|
||||
|
||||
def get(self, ptp_instance_map_id):
|
||||
try:
|
||||
return self._list(self._path(ptp_instance_map_id))[0]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def create(self, **kwargs):
|
||||
data = {}
|
||||
for (key, value) in kwargs.items():
|
||||
if key in CREATION_ATTRIBUTES:
|
||||
data[key] = value
|
||||
else:
|
||||
raise exc.InvalidAttribute('%s' % key)
|
||||
return self._create(self._path(), data)
|
||||
|
||||
def delete(self, ptp_instance_map_id):
|
||||
return self._delete(self._path(ptp_instance_map_id))
|
|
@ -0,0 +1,44 @@
|
|||
########################################################################
|
||||
#
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
########################################################################
|
||||
|
||||
from cgtsclient.common import base
|
||||
from cgtsclient import exc
|
||||
|
||||
|
||||
CREATION_ATTRIBUTES = ['interface_id', 'ptp_interface_id']
|
||||
|
||||
|
||||
class PtpInterfaceMap(base.Resource):
|
||||
def __repr__(self):
|
||||
return "<PtpInterfaceMap %s>" % self._info
|
||||
|
||||
|
||||
class PtpInterfaceMapManager(base.Manager):
|
||||
resource_class = PtpInterfaceMap
|
||||
|
||||
def _path(self, ptp_interface_map_id=None):
|
||||
return '/v1/ptp_interface_maps/%s' % ptp_interface_map_id \
|
||||
if ptp_interface_map_id else '/v1/ptp_interface_maps'
|
||||
|
||||
def get(self, ptp_interface_map_id):
|
||||
try:
|
||||
return self._list(self._path(ptp_interface_map_id))[0]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def create(self, **kwargs):
|
||||
data = {}
|
||||
for (key, value) in kwargs.items():
|
||||
if key in CREATION_ATTRIBUTES:
|
||||
data[key] = value
|
||||
else:
|
||||
raise exc.InvalidAttribute('%s' % key)
|
||||
return self._create(self._path(), data)
|
||||
|
||||
def delete(self, ptp_interface_map_id):
|
||||
return self._delete(self._path(ptp_interface_map_id))
|
|
@ -66,7 +66,9 @@ from sysinv.api.controllers.v1 import pci_device
|
|||
from sysinv.api.controllers.v1 import port
|
||||
from sysinv.api.controllers.v1 import ptp
|
||||
from sysinv.api.controllers.v1 import ptp_instance
|
||||
from sysinv.api.controllers.v1 import ptp_instance_map
|
||||
from sysinv.api.controllers.v1 import ptp_interface
|
||||
from sysinv.api.controllers.v1 import ptp_interface_map
|
||||
from sysinv.api.controllers.v1 import ptp_parameter
|
||||
from sysinv.api.controllers.v1 import ptp_paramownership
|
||||
from sysinv.api.controllers.v1 import pv
|
||||
|
@ -153,9 +155,15 @@ class V1(base.APIBase):
|
|||
ptp_instances = [link.Link]
|
||||
"Links to the ptp_instances resource"
|
||||
|
||||
ptp_instance_maps = [link.Link]
|
||||
"Links to the ptp_instance_maps resource"
|
||||
|
||||
ptp_interfaces = [link.Link]
|
||||
"Links to the ptp_interfaces resource"
|
||||
|
||||
ptp_interface_maps = [link.Link]
|
||||
"Links to the ptp_interface_maps resource"
|
||||
|
||||
ptp_parameters = [link.Link]
|
||||
"Links to the ptp_parameters resource"
|
||||
|
||||
|
@ -469,6 +477,14 @@ class V1(base.APIBase):
|
|||
'ptp_instances', '',
|
||||
bookmark=True)]
|
||||
|
||||
v1.ptp_instance_maps = [link.Link.make_link('self',
|
||||
pecan.request.host_url,
|
||||
'ptp_instance_maps', ''),
|
||||
link.Link.make_link('bookmark',
|
||||
pecan.request.host_url,
|
||||
'ptp_instance_maps', '',
|
||||
bookmark=True)]
|
||||
|
||||
v1.ptp_interfaces = [link.Link.make_link('self', pecan.request.host_url,
|
||||
'ptp_interfaces', ''),
|
||||
link.Link.make_link('bookmark',
|
||||
|
@ -477,6 +493,14 @@ class V1(base.APIBase):
|
|||
bookmark=True)
|
||||
]
|
||||
|
||||
v1.ptp_interface_maps = [link.Link.make_link('self',
|
||||
pecan.request.host_url,
|
||||
'ptp_instance_maps', ''),
|
||||
link.Link.make_link('bookmark',
|
||||
pecan.request.host_url,
|
||||
'ptp_instance_maps', '',
|
||||
bookmark=True)]
|
||||
|
||||
v1.ptp_parameters = [link.Link.make_link('self', pecan.request.host_url,
|
||||
'ptp_parameters', ''),
|
||||
link.Link.make_link('bookmark',
|
||||
|
@ -935,7 +959,9 @@ class Controller(rest.RestController):
|
|||
intp = ntp.NTPController()
|
||||
ptp = ptp.PTPController()
|
||||
ptp_instances = ptp_instance.PtpInstanceController()
|
||||
ptp_instance_maps = ptp_instance_map.PtpInstanceMapController()
|
||||
ptp_interfaces = ptp_interface.PtpInterfaceController()
|
||||
ptp_interface_maps = ptp_interface_map.PtpInterfaceMapController()
|
||||
ptp_parameters = ptp_parameter.PtpParameterController()
|
||||
ptp_parameter_ownerships = \
|
||||
ptp_paramownership.PtpParameterOwnershipController()
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
#
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
import wsme
|
||||
from wsme import types as wtypes
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from oslo_log import log
|
||||
from sysinv._i18n import _
|
||||
from sysinv.api.controllers.v1 import base
|
||||
from sysinv.api.controllers.v1 import collection
|
||||
from sysinv.api.controllers.v1 import types
|
||||
from sysinv.common import exception
|
||||
from sysinv.common import utils as cutils
|
||||
from sysinv import objects
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class PtpInstanceMapPatchType(types.JsonPatchType):
|
||||
@staticmethod
|
||||
def mandatory_attrs():
|
||||
return []
|
||||
|
||||
|
||||
class PtpInstanceMap(base.APIBase):
|
||||
"""API representation of a PTP instance map to host.
|
||||
|
||||
This class enforces type checking and value constraints, and converts
|
||||
between the internal object model and the API representation of
|
||||
a PTP instance association to host.
|
||||
"""
|
||||
|
||||
created_at = wtypes.datetime.datetime
|
||||
"Timestamp of creation of this PTP instance mapping"
|
||||
|
||||
id = int
|
||||
"Unique ID for this PTP instance mapping"
|
||||
|
||||
uuid = types.uuid
|
||||
"Unique UUID for this PTP instance mapping"
|
||||
|
||||
host_id = int
|
||||
"ID of the associated host"
|
||||
|
||||
hostname = wtypes.text
|
||||
"Name of the associated host"
|
||||
|
||||
ptp_instance_id = int
|
||||
"ID of the associated PTP instance"
|
||||
|
||||
name = wtypes.text
|
||||
"Name of the associated PTP instance"
|
||||
|
||||
service = wtypes.text
|
||||
"Service type of the associated PTP instance"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.fields = list(objects.ptp_instance_map.fields.keys())
|
||||
for k in self.fields:
|
||||
if not hasattr(self, k):
|
||||
continue
|
||||
setattr(self, k, kwargs.get(k))
|
||||
|
||||
@classmethod
|
||||
def convert_with_links(cls, rpc_ptp_instance_map, expand=True):
|
||||
ptp_instance_map = PtpInstanceMap(**rpc_ptp_instance_map.as_dict())
|
||||
if not expand:
|
||||
ptp_instance_map.unset_fields_except(
|
||||
['uuid', 'host_id', 'hostname', 'ptp_instance_id',
|
||||
'name', 'service', 'created_at'])
|
||||
|
||||
LOG.debug("PtpInstanceMap.convert_with_links: converted %s" %
|
||||
ptp_instance_map.as_dict())
|
||||
return ptp_instance_map
|
||||
|
||||
|
||||
class PtpInstanceMapCollection(collection.Collection):
|
||||
"""API representation of a collection of PTP instance maps."""
|
||||
|
||||
ptp_instance_maps = [PtpInstanceMap]
|
||||
"A list containing PTP instance mapping objects"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._type = 'ptp_instance_maps'
|
||||
|
||||
@classmethod
|
||||
def convert_with_links(cls, rpc_ptp_instance_maps, limit, url=None,
|
||||
expand=False, **kwargs):
|
||||
collection = PtpInstanceMapCollection()
|
||||
collection.ptp_instance_maps = \
|
||||
[PtpInstanceMap.convert_with_links(p, expand)
|
||||
for p in rpc_ptp_instance_maps]
|
||||
collection.next = collection.get_next(limit, url=url, **kwargs)
|
||||
return collection
|
||||
|
||||
|
||||
LOCK_NAME = 'PtpInstanceMapController'
|
||||
|
||||
|
||||
class PtpInstanceMapController(rest.RestController):
|
||||
"""REST controller for PTP instance map."""
|
||||
|
||||
@wsme_pecan.wsexpose(PtpInstanceMap, types.uuid)
|
||||
def get_one(self, ptp_instance_map_uuid):
|
||||
"""Retrieve a single PTP instance."""
|
||||
LOG.debug("PtpInstanceMapController.get_one: uuid=%s" %
|
||||
ptp_instance_map_uuid)
|
||||
try:
|
||||
ptp_instance_map = objects.ptp_instance_map.get_by_uuid(
|
||||
pecan.request.context,
|
||||
ptp_instance_map_uuid)
|
||||
except exception.InvalidParameterValue:
|
||||
raise wsme.exc.ClientSideError(
|
||||
_("No PTP instance mapping found for %s"
|
||||
% ptp_instance_map_uuid))
|
||||
|
||||
return PtpInstanceMap.convert_with_links(ptp_instance_map)
|
||||
|
||||
def _check_instance_exists(self, id):
|
||||
LOG.debug("PtpInstanceMapController._check_instance_exists: "
|
||||
"id %d" % id)
|
||||
try:
|
||||
pecan.request.dbapi.ptp_instance_get(id)
|
||||
except exception.PtpInstanceNotFound:
|
||||
raise wsme.exc.ClientSideError(
|
||||
_("No PTP parameter object found with id %d" % id))
|
||||
|
||||
def _check_host_exists(self, id):
|
||||
LOG.debug("PtpInstanceMapController._check_host_exists: "
|
||||
"id %d" % id)
|
||||
try:
|
||||
pecan.request.dbapi.ihost_get(id)
|
||||
except exception.ServerNotFound:
|
||||
raise wsme.exc.ClientSideError(
|
||||
_("No host found with id %d" % id))
|
||||
|
||||
@cutils.synchronized(LOCK_NAME)
|
||||
@wsme_pecan.wsexpose(PtpInstanceMap, body=PtpInstanceMap)
|
||||
def post(self, ptp_instance_map):
|
||||
"""Create a new PTP instance mapping."""
|
||||
ptp_instance_map_dict = ptp_instance_map.as_dict()
|
||||
LOG.debug("PtpInstanceMapController.post: %s"
|
||||
% ptp_instance_map_dict)
|
||||
|
||||
self._check_instance_exists(ptp_instance_map_dict['ptp_instance_id'])
|
||||
self._check_host_exists(ptp_instance_map_dict['host_id'])
|
||||
|
||||
result = pecan.request.dbapi.ptp_instance_set_host(
|
||||
ptp_instance_map_dict)
|
||||
return PtpInstanceMap.convert_with_links(result)
|
||||
|
||||
@cutils.synchronized(LOCK_NAME)
|
||||
@wsme_pecan.wsexpose(None, types.uuid, status_code=204)
|
||||
def delete(self, ptp_instance_map_uuid):
|
||||
"""Delete a PTP instance mapping."""
|
||||
LOG.debug("PtpInstanceMapController.delete: %s"
|
||||
% ptp_instance_map_uuid)
|
||||
ptp_instance_map = objects.ptp_instance_map.get_by_uuid(
|
||||
pecan.request.context, ptp_instance_map_uuid)
|
||||
pecan.request.dbapi.ptp_parameter_unset_host(
|
||||
ptp_instance_map.as_dict())
|
|
@ -0,0 +1,174 @@
|
|||
#
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
import wsme
|
||||
from wsme import types as wtypes
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from oslo_log import log
|
||||
from sysinv._i18n import _
|
||||
from sysinv.api.controllers.v1 import base
|
||||
from sysinv.api.controllers.v1 import collection
|
||||
from sysinv.api.controllers.v1 import types
|
||||
from sysinv.common import exception
|
||||
from sysinv.common import utils as cutils
|
||||
from sysinv import objects
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class PtpInterfaceMapPatchType(types.JsonPatchType):
|
||||
@staticmethod
|
||||
def mandatory_attrs():
|
||||
return []
|
||||
|
||||
|
||||
class PtpInterfaceMap(base.APIBase):
|
||||
"""API representation of a PTP interface map to interface.
|
||||
|
||||
This class enforces type checking and value constraints, and converts
|
||||
between the internal object model and the API representation of
|
||||
a PTP interface association to interface.
|
||||
"""
|
||||
|
||||
created_at = wtypes.datetime.datetime
|
||||
"Timestamp of creation of this PTP interface mapping"
|
||||
|
||||
id = int
|
||||
"Unique ID for this PTP interface mapping"
|
||||
|
||||
uuid = types.uuid
|
||||
"Unique UUID for this PTP interface mapping"
|
||||
|
||||
interface_id = int
|
||||
"ID of the associated interface"
|
||||
|
||||
ifname = wtypes.text
|
||||
"Name of the associated interface"
|
||||
|
||||
iftype = wtypes.text
|
||||
"Type of the associated interface"
|
||||
|
||||
hostname = wtypes.text
|
||||
"Name of the host for the associated interface"
|
||||
|
||||
ptp_interface_id = int
|
||||
"ID of the associated PTP interface"
|
||||
|
||||
name = wtypes.text
|
||||
"Name of the PTP instance for the associated PTP interface"
|
||||
|
||||
service = wtypes.text
|
||||
"Service type of the PTP instance for the associated PTP interface"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.fields = list(objects.ptp_interface_map.fields.keys())
|
||||
for k in self.fields:
|
||||
if not hasattr(self, k):
|
||||
continue
|
||||
setattr(self, k, kwargs.get(k))
|
||||
|
||||
@classmethod
|
||||
def convert_with_links(cls, rpc_ptp_interface_map, expand=True):
|
||||
ptp_interface_map = PtpInterfaceMap(**rpc_ptp_interface_map.as_dict())
|
||||
if not expand:
|
||||
ptp_interface_map.unset_fields_except(
|
||||
['uuid', 'interface_id', 'ifname', 'iftype', 'hostname',
|
||||
'ptp_interface_id', 'name', 'service', 'created_at'])
|
||||
|
||||
LOG.debug("PtpInterfaceMap.convert_with_links: converted %s" %
|
||||
ptp_interface_map.as_dict())
|
||||
return ptp_interface_map
|
||||
|
||||
|
||||
class PtpInterfaceMapCollection(collection.Collection):
|
||||
"""API representation of a collection of PTP interface maps."""
|
||||
|
||||
ptp_interface_maps = [PtpInterfaceMap]
|
||||
"A list containing PTP interface map objects"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._type = 'ptp_interface_maps'
|
||||
|
||||
@classmethod
|
||||
def convert_with_links(cls, rpc_ptp_interface_maps, limit, url=None,
|
||||
expand=False, **kwargs):
|
||||
collection = PtpInterfaceMapCollection()
|
||||
collection.ptp_interface_maps = \
|
||||
[PtpInterfaceMap.convert_with_links(p, expand)
|
||||
for p in rpc_ptp_interface_maps]
|
||||
collection.next = collection.get_next(limit, url=url, **kwargs)
|
||||
return collection
|
||||
|
||||
|
||||
LOCK_NAME = 'PtpInterfaceMapController'
|
||||
|
||||
|
||||
class PtpInterfaceMapController(rest.RestController):
|
||||
"""REST controller for PTP interface map."""
|
||||
|
||||
@wsme_pecan.wsexpose(PtpInterfaceMap, types.uuid)
|
||||
def get_one(self, ptp_interface_map_uuid):
|
||||
"""Retrieve a single PTP interface."""
|
||||
LOG.debug("PtpInterfaceMapController.get_one: uuid=%s" %
|
||||
ptp_interface_map_uuid)
|
||||
try:
|
||||
ptp_interface_map = objects.ptp_interface_map.get_by_uuid(
|
||||
pecan.request.context,
|
||||
ptp_interface_map_uuid)
|
||||
except exception.InvalidParameterValue:
|
||||
raise wsme.exc.ClientSideError(
|
||||
_("No PTP interface mapping found for %s"
|
||||
% ptp_interface_map_uuid))
|
||||
|
||||
return PtpInterfaceMap.convert_with_links(ptp_interface_map)
|
||||
|
||||
def _check_interface_exists(self, id):
|
||||
LOG.debug("PtpInterfaceMapController._check_interface_exists: "
|
||||
"id %d" % id)
|
||||
try:
|
||||
pecan.request.dbapi.iinterface_get(id)
|
||||
except exception.InvalidParameterValue:
|
||||
raise wsme.exc.ClientSideError(
|
||||
_("No interface found with id %d" % id))
|
||||
|
||||
def _check_ptp_interface_exists(self, id):
|
||||
LOG.debug("PtpInterfaceMapController._check_ptp_interface_exists: "
|
||||
"id %d" % id)
|
||||
try:
|
||||
pecan.request.dbapi.ptp_interface_get(id)
|
||||
except exception.PtpInterfaceNotFound:
|
||||
raise wsme.exc.ClientSideError(
|
||||
_("No PTP interface found with id %d" % id))
|
||||
|
||||
@cutils.synchronized(LOCK_NAME)
|
||||
@wsme_pecan.wsexpose(PtpInterfaceMap, body=PtpInterfaceMap)
|
||||
def post(self, ptp_interface_map):
|
||||
"""Create a new PTP interface mapping."""
|
||||
ptp_interface_map_dict = ptp_interface_map.as_dict()
|
||||
LOG.debug("PtpInterfaceMapController.post: %s"
|
||||
% ptp_interface_map_dict)
|
||||
|
||||
self._check_interface_exists(ptp_interface_map_dict['interface_id'])
|
||||
self._check_ptp_interface_exists(
|
||||
ptp_interface_map_dict['ptp_interface_id'])
|
||||
|
||||
result = pecan.request.dbapi.ptp_interface_set_interface(
|
||||
ptp_interface_map_dict)
|
||||
return PtpInterfaceMap.convert_with_links(result)
|
||||
|
||||
@cutils.synchronized(LOCK_NAME)
|
||||
@wsme_pecan.wsexpose(None, types.uuid, status_code=204)
|
||||
def delete(self, ptp_interface_map_uuid):
|
||||
"""Delete a PTP interface mapping."""
|
||||
LOG.debug("PtpInterfaceMapController.delete: %s"
|
||||
% ptp_interface_map_uuid)
|
||||
ptp_interface_map = objects.ptp_interface_map.get_by_uuid(
|
||||
pecan.request.context, ptp_interface_map_uuid)
|
||||
pecan.request.dbapi.ptp_parameter_unset_interface(
|
||||
ptp_interface_map.as_dict())
|
|
@ -46,7 +46,13 @@ class PtpParameterOwnership(base.APIBase):
|
|||
"Unique UUID for this PTP parameter ownership"
|
||||
|
||||
parameter_uuid = types.uuid
|
||||
"UUID of the PTP parameter (name/value)"
|
||||
"UUID of the PTP parameter"
|
||||
|
||||
parameter_name = wtypes.text
|
||||
"Name of the PTP parameter"
|
||||
|
||||
parameter_value = wtypes.text
|
||||
"Value of the PTP parameter"
|
||||
|
||||
owner_uuid = types.uuid
|
||||
"UUID of the entity associated to PTP parameter (instance or interface)"
|
||||
|
@ -64,7 +70,8 @@ class PtpParameterOwnership(base.APIBase):
|
|||
**rpc_ptp_paramownership.as_dict())
|
||||
if not expand:
|
||||
ptp_parameter_ownership.unset_fields_except(
|
||||
['uuid', 'parameter_uuid', 'owner_uuid', 'created_at'])
|
||||
['uuid', 'parameter_uuid', 'parameter_name', 'parameter_value',
|
||||
'owner_uuid', 'created_at'])
|
||||
|
||||
LOG.debug("PtpParameterOwnership.convert_with_links: converted %s" %
|
||||
ptp_parameter_ownership.as_dict())
|
||||
|
@ -139,6 +146,14 @@ class PtpParameterOwnershipController(rest.RestController):
|
|||
LOG.debug("PtpParameterOwnershipController.post: %s"
|
||||
% ptp_paramownership_dict)
|
||||
|
||||
# Get rid of parameter details to set the ownership
|
||||
try:
|
||||
ptp_paramownership_dict.pop('parameter_name')
|
||||
ptp_paramownership_dict.pop('parameter_value')
|
||||
except KeyError:
|
||||
LOG.debug("PtpParameterController.post: no parameter data in %s" %
|
||||
ptp_paramownership_dict)
|
||||
|
||||
self._check_parameter_exists(ptp_paramownership_dict['parameter_uuid'])
|
||||
self._check_owner_exists(ptp_paramownership_dict['owner_uuid'])
|
||||
|
||||
|
@ -150,7 +165,7 @@ class PtpParameterOwnershipController(rest.RestController):
|
|||
@wsme_pecan.wsexpose(None, types.uuid, status_code=204)
|
||||
def delete(self, ptp_paramownership_uuid):
|
||||
"""Delete a PTP parameter ownership."""
|
||||
LOG.debug("PtpParameterController.delete: %s"
|
||||
LOG.debug("PtpParameterOwnershipController.delete: %s"
|
||||
% ptp_paramownership_uuid)
|
||||
ptp_paramownership = objects.ptp_paramownership.get_by_uuid(
|
||||
pecan.request.context, ptp_paramownership_uuid)
|
||||
|
|
|
@ -469,6 +469,16 @@ class PtpParameterOwnershipAlreadyExists(Conflict):
|
|||
message = _("UUID %(param)s is already a PTP parameter of UUID %(owner)s.")
|
||||
|
||||
|
||||
class PtpInstanceMapAlreadyExists(Conflict):
|
||||
message = _("PTP instance %(ptp_instance)s is already associated to host "
|
||||
"%(host)s.")
|
||||
|
||||
|
||||
class PtpInterfaceMapAlreadyExists(Conflict):
|
||||
message = _("PTP interface %(ptp_interface)s is already associated to "
|
||||
"interface %(interface)s.")
|
||||
|
||||
|
||||
class PMAlreadyExists(Conflict):
|
||||
message = _("A PM with UUID %(uuid)s already exists.")
|
||||
|
||||
|
@ -617,6 +627,14 @@ class PtpParameterOwnershipNotFound(NotFound):
|
|||
message = _("No PTP parameter ownership with id %(uuid)s found.")
|
||||
|
||||
|
||||
class PtpInstanceMapNotFound(NotFound):
|
||||
message = _("No PTP instance mapping with id %(uuid)s found.")
|
||||
|
||||
|
||||
class PtpInterfaceMapNotFound(NotFound):
|
||||
message = _("No PTP interface mapping with id %(uuid)s found.")
|
||||
|
||||
|
||||
class DiskNotFound(NotFound):
|
||||
message = _("No disk with id %(disk_id)s")
|
||||
|
||||
|
|
|
@ -1938,11 +1938,11 @@ class Connection(object):
|
|||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_instances_get_list(self, host=None, limit=None, marker=None,
|
||||
def ptp_instances_get_list(self, host_uuid=None, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
"""Returns a list of PTP service instances.
|
||||
|
||||
:param host: id or uuid of host.
|
||||
:param host_uuid: id or uuid of host.
|
||||
:param limit: Maximum number of PTP instances to return.
|
||||
:param marker: The last item of the previous page; we return the next
|
||||
result set.
|
||||
|
@ -1952,6 +1952,46 @@ class Connection(object):
|
|||
:returns: A list of PTP instances.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_instance_set_host(self, values):
|
||||
"""Set the PTP instance to some host.
|
||||
|
||||
:param values: A dict containing the IDs used to associate
|
||||
the PTP instance to the host.
|
||||
{
|
||||
'host_id': 1,
|
||||
'ptp_instance_id': 3
|
||||
}
|
||||
:returns: A PTP instance mapping.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_instance_unset_host(self, values):
|
||||
"""Remove the association between a PTP instance and a host.
|
||||
|
||||
:param values: A dict containing the IDs used to associate
|
||||
the PTP instance to the host.
|
||||
{
|
||||
'host_id': 1,
|
||||
'ptp_instance_id': 3
|
||||
}
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_instance_get_hosts(self, ptp_instance_id, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
"""Returns a list of all hosts associated to the PTP instance.
|
||||
|
||||
:param ptp_instance_id: The id or uuid of a PTP instance.
|
||||
:param limit: Maximum number of hosts to return.
|
||||
:param marker: The last item of the previous page; we return the next
|
||||
result set.
|
||||
:param sort_key: Attribute by which results should be sorted
|
||||
:param sort_dir: direction in which results should be sorted
|
||||
(asc, desc)
|
||||
:returns: A list of hosts for the given PTP instance.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_instance_destroy(self, ptp_instance_id):
|
||||
"""Destroys a PTP service instance.
|
||||
|
@ -1966,6 +2006,14 @@ class Connection(object):
|
|||
:param name: The name given for a PTP instance.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_instance_map_get(self, ptp_instance_map_id):
|
||||
"""Returns a PTP instance mapping.
|
||||
|
||||
:param ptp_instance_map_id: The id or uuid of a PTP instance map.
|
||||
:returns: A PTP instance map.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_interface_create(self, values):
|
||||
"""Creates a new PTP association between an interface
|
||||
|
@ -2046,6 +2094,46 @@ class Connection(object):
|
|||
interface.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_interface_set_interface(self, values):
|
||||
"""Set the PTP interface to some interface.
|
||||
|
||||
:param values: A dict containing the IDs used to associate
|
||||
the PTP interface to the interface.
|
||||
{
|
||||
'interface_id': 1,
|
||||
'ptp_interface_id': 3
|
||||
}
|
||||
:returns: A PTP interface mapping.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_interface_unset_interface(self, values):
|
||||
"""Remove the association between a PTP interface and a interface.
|
||||
|
||||
:param values: A dict containing the IDs used to associate
|
||||
the PTP interface to the interface.
|
||||
{
|
||||
'interface_id': 1,
|
||||
'ptp_interface_id': 3
|
||||
}
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_interface_get_interfaces(self, ptp_interface_id, limit=None,
|
||||
marker=None, sort_key=None, sort_dir=None):
|
||||
"""Returns a list of all interfaces associated to the PTP interface.
|
||||
|
||||
:param ptp_interface_id: The id or uuid of a PTP interface.
|
||||
:param limit: Maximum number of interfaces to return.
|
||||
:param marker: The last item of the previous page; we return the next
|
||||
result set.
|
||||
:param sort_key: Attribute by which results should be sorted
|
||||
:param sort_dir: direction in which results should be sorted
|
||||
(asc, desc)
|
||||
:returns: A list of interfaces for the given PTP interface.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_interface_destroy(self, ptp_interface_id):
|
||||
"""Destroys a PTP interface association.
|
||||
|
@ -2053,6 +2141,14 @@ class Connection(object):
|
|||
:param ptp_interface_id: The id or uuid of a PTP interface association.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_interface_map_get(self, ptp_interface_map_id):
|
||||
"""Returns a PTP interface mapping.
|
||||
|
||||
:param ptp_interface_map_id: The id or uuid of a PTP interface map.
|
||||
:returns: A PTP interface map.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ptp_parameter_create(self, values):
|
||||
"""Creates a new PTP parameter to be applied later either to some
|
||||
|
|
|
@ -3779,25 +3779,58 @@ class Connection(api.Connection):
|
|||
raise exception.NotFound()
|
||||
|
||||
@objects.objectify(objects.ptp_instance)
|
||||
def ptp_instances_get_list(self, host=None, limit=None, marker=None,
|
||||
def ptp_instances_get_list(self, host_uuid=None, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
query = model_query(models.PtpInstances)
|
||||
if host is not None:
|
||||
if utils.is_int_like(host):
|
||||
ihost = self.ihost_get(int(host))
|
||||
elif utils.is_uuid_like(host):
|
||||
ihost = self.ihost_get(host.strip())
|
||||
elif isinstance(host, models.ihost):
|
||||
ihost = host
|
||||
else:
|
||||
raise exception.NodeNotFound(node=host)
|
||||
ptp_instance_id = ihost['ptp_instance_id']
|
||||
if not ptp_instance_id:
|
||||
return []
|
||||
query = add_identity_filter(query, ptp_instance_id)
|
||||
if host_uuid is not None:
|
||||
host = self.ihost_get(host_uuid)
|
||||
query = query.join(models.PtpInstanceMaps,
|
||||
models.PtpInstanceMaps.host_id == host.id)
|
||||
return _paginate_query(models.PtpInstances, limit, marker,
|
||||
sort_key, sort_dir, query)
|
||||
|
||||
@objects.objectify(objects.ptp_instance_map)
|
||||
def ptp_instance_set_host(self, values):
|
||||
if not values.get('uuid'):
|
||||
values['uuid'] = uuidutils.generate_uuid()
|
||||
ptp_instance_map = models.PtpInstanceMaps(**values)
|
||||
with _session_for_write() as session:
|
||||
try:
|
||||
session.add(ptp_instance_map)
|
||||
session.flush()
|
||||
except db_exc.DBDuplicateEntry:
|
||||
raise exception.PtpInstanceMapAlreadyExists(
|
||||
ptp_instance=values['ptp_instance_id'],
|
||||
host=values['host_id'])
|
||||
|
||||
query = model_query(models.PtpInstanceMaps)
|
||||
query = add_identity_filter(query, values['uuid'])
|
||||
|
||||
try:
|
||||
return query.one()
|
||||
except NoResultFound:
|
||||
raise exception.PtpInstanceMapNotFound(uuid=values['uuid'])
|
||||
|
||||
def ptp_instance_unset_host(self, values):
|
||||
with _session_for_write() as session:
|
||||
query = model_query(models.PtpInstanceMaps, session=session)
|
||||
query = query.filter_by(ptp_instance_id=values['ptp_instance_id'],
|
||||
host_id=values['host_id'])
|
||||
try:
|
||||
query.one()
|
||||
except NoResultFound:
|
||||
return
|
||||
query.delete()
|
||||
|
||||
@objects.objectify(objects.ptp_instance)
|
||||
def ptp_instance_get_hosts(self, ptp_instance_id, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
query = model_query(models.PtpInstances)
|
||||
query = add_identity_filter(query, ptp_instance_id)
|
||||
query = query.join(models.PtpInstances.hosts)
|
||||
return _paginate_query(models.PtpInstances, limit, marker, sort_key,
|
||||
sort_dir, query)
|
||||
|
||||
def ptp_instance_destroy(self, ptp_instance_id):
|
||||
with _session_for_write() as session:
|
||||
# PTP instance will be deleted by cascade
|
||||
|
@ -3819,6 +3852,15 @@ class Connection(api.Connection):
|
|||
raise exception.NotFound()
|
||||
query.delete()
|
||||
|
||||
@objects.objectify(objects.ptp_instance_map)
|
||||
def ptp_instance_map_get(self, ptp_instance_map_id):
|
||||
query = model_query(models.PtpInstanceMaps)
|
||||
query = add_identity_filter(query, ptp_instance_map_id)
|
||||
try:
|
||||
return query.one()
|
||||
except NoResultFound:
|
||||
raise exception.PtpInstanceMapNotFound(uuid=ptp_instance_map_id)
|
||||
|
||||
def _ptp_interface_get(self, ptp_interface_id):
|
||||
query = model_query(models.PtpInterfaces)
|
||||
query = add_identity_filter(query, ptp_interface_id)
|
||||
|
@ -3910,6 +3952,50 @@ class Connection(api.Connection):
|
|||
return _paginate_query(models.PtpInterfaces, limit, marker,
|
||||
sort_key, sort_dir, query)
|
||||
|
||||
@objects.objectify(objects.ptp_interface_map)
|
||||
def ptp_interface_set_interface(self, values):
|
||||
if not values.get('uuid'):
|
||||
values['uuid'] = uuidutils.generate_uuid()
|
||||
ptp_interface_map = models.PtpInterfaceMaps(**values)
|
||||
with _session_for_write() as session:
|
||||
try:
|
||||
session.add(ptp_interface_map)
|
||||
session.flush()
|
||||
except db_exc.DBDuplicateEntry:
|
||||
raise exception.PtpInterfaceMapAlreadyExists(
|
||||
ptp_interface=values['ptp_interface_id'],
|
||||
interface=values['interface_id'])
|
||||
|
||||
query = model_query(models.PtpInterfaceMaps)
|
||||
query = add_identity_filter(query, values['uuid'])
|
||||
|
||||
try:
|
||||
return query.one()
|
||||
except NoResultFound:
|
||||
raise exception.PtpInterfaceMapNotFound(uuid=values['uuid'])
|
||||
|
||||
def ptp_interface_unset_interface(self, values):
|
||||
with _session_for_write() as session:
|
||||
query = model_query(models.PtpInterfaceMaps, session=session)
|
||||
query = query.filter_by(
|
||||
ptp_interface_id=values['ptp_interface_id'],
|
||||
interface_id=values['interface_id'])
|
||||
try:
|
||||
query.one()
|
||||
except NoResultFound:
|
||||
return
|
||||
query.delete()
|
||||
|
||||
@objects.objectify(objects.ptp_interface)
|
||||
def ptp_interface_get_interfaces(self, ptp_interface_id, limit=None,
|
||||
marker=None, sort_key=None,
|
||||
sort_dir=None):
|
||||
query = model_query(models.PtpInterfaces)
|
||||
query = add_identity_filter(query, ptp_interface_id)
|
||||
query = query.join(models.PtpInterfaces.interfaces)
|
||||
return _paginate_query(models.PtpInterfaces, limit, marker, sort_key,
|
||||
sort_dir, query)
|
||||
|
||||
def ptp_interface_destroy(self, ptp_interface_id):
|
||||
with _session_for_write() as session:
|
||||
# PTP instance will be deleted by cascade
|
||||
|
@ -3921,6 +4007,15 @@ class Connection(api.Connection):
|
|||
raise exception.PtpInterfaceNotFound(uuid=ptp_interface_id)
|
||||
query.delete()
|
||||
|
||||
@objects.objectify(objects.ptp_interface_map)
|
||||
def ptp_interface_map_get(self, ptp_interface_map_id):
|
||||
query = model_query(models.PtpInterfaceMaps)
|
||||
query = add_identity_filter(query, ptp_interface_map_id)
|
||||
try:
|
||||
return query.one()
|
||||
except NoResultFound:
|
||||
raise exception.PtpInterfaceMapNotFound(uuid=ptp_interface_map_id)
|
||||
|
||||
def _ptp_parameter_get(self, ptp_parameter_id):
|
||||
query = model_query(models.PtpParameters)
|
||||
query = add_identity_filter(query, ptp_parameter_id)
|
||||
|
|
|
@ -21,8 +21,7 @@ ENGINE = 'InnoDB'
|
|||
CHARSET = 'utf8'
|
||||
|
||||
|
||||
def _populate_ptp_tables(meta, ptp_instances, ptp_interfaces,
|
||||
ptp_parameters, ptp_parameter_ownerships):
|
||||
def _populate_ptp_tables(meta, tables):
|
||||
"""This function moves PTP configuration from other tables:
|
||||
- If advanced (specialized) ptp4l configuration is found in
|
||||
'service_parameter' table, it inserts a 'ptp4l' entry in
|
||||
|
@ -46,6 +45,8 @@ def upgrade(migrate_engine):
|
|||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
tables = {}
|
||||
|
||||
ptp_parameters = Table(
|
||||
'ptp_parameters',
|
||||
meta,
|
||||
|
@ -65,6 +66,7 @@ def upgrade(migrate_engine):
|
|||
mysql_charset=CHARSET,
|
||||
)
|
||||
ptp_parameters.create()
|
||||
tables.update({'ptp_parameters': ptp_parameters})
|
||||
|
||||
ptp_parameter_owners = Table(
|
||||
'ptp_parameter_owners',
|
||||
|
@ -84,6 +86,7 @@ def upgrade(migrate_engine):
|
|||
mysql_charset=CHARSET,
|
||||
)
|
||||
ptp_parameter_owners.create()
|
||||
tables.update({'ptp_parameter_owners': ptp_parameter_owners})
|
||||
|
||||
ptp_instances = Table(
|
||||
'ptp_instances',
|
||||
|
@ -103,10 +106,7 @@ def upgrade(migrate_engine):
|
|||
mysql_charset=CHARSET,
|
||||
)
|
||||
ptp_instances.create()
|
||||
|
||||
host = Table('i_host', meta, autoload=True)
|
||||
host.create_column(
|
||||
Column('ptp_instance_id', Integer, ForeignKey('ptp_instances.id')))
|
||||
tables.update({'ptp_instances': ptp_instances})
|
||||
|
||||
ptp_interfaces = Table(
|
||||
'ptp_interfaces',
|
||||
|
@ -127,10 +127,7 @@ def upgrade(migrate_engine):
|
|||
mysql_charset=CHARSET,
|
||||
)
|
||||
ptp_interfaces.create()
|
||||
|
||||
interface = Table('interfaces', meta, autoload=True)
|
||||
interface.create_column(
|
||||
Column('ptp_interface_id', Integer, ForeignKey('ptp_interfaces.id')))
|
||||
tables.update({'ptp_interfaces': ptp_interfaces})
|
||||
|
||||
ptp_parameter_ownerships = Table(
|
||||
'ptp_parameter_ownerships',
|
||||
|
@ -145,7 +142,9 @@ def upgrade(migrate_engine):
|
|||
Column('parameter_uuid', String(UUID_LENGTH),
|
||||
ForeignKey('ptp_parameters.uuid', ondelete='CASCADE'),
|
||||
nullable=False),
|
||||
Column('owner_uuid', String(UUID_LENGTH), nullable=False),
|
||||
Column('owner_uuid', String(UUID_LENGTH),
|
||||
ForeignKey('ptp_parameter_owners.uuid', ondelete='CASCADE'),
|
||||
nullable=False),
|
||||
|
||||
UniqueConstraint('parameter_uuid', 'owner_uuid', name='u_paramowner'),
|
||||
|
||||
|
@ -153,15 +152,78 @@ def upgrade(migrate_engine):
|
|||
mysql_charset=CHARSET,
|
||||
)
|
||||
ptp_parameter_ownerships.create()
|
||||
tables.update({'ptp_parameter_ownerships': ptp_parameter_ownerships})
|
||||
|
||||
_populate_ptp_tables(meta, ptp_instances, ptp_interfaces, ptp_parameters,
|
||||
ptp_parameter_ownerships)
|
||||
i_host = Table('i_host', meta, autoload=True)
|
||||
tables.update({'i_host': i_host})
|
||||
|
||||
ptp_instance_maps = Table(
|
||||
'ptp_instance_maps',
|
||||
meta,
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('deleted_at', DateTime),
|
||||
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('uuid', String(UUID_LENGTH), unique=True),
|
||||
|
||||
Column('host_id', Integer,
|
||||
ForeignKey('i_host.id', ondelete='CASCADE'),
|
||||
nullable=False),
|
||||
Column('ptp_instance_id', Integer,
|
||||
ForeignKey('ptp_instances.id', ondelete='CASCADE'),
|
||||
nullable=False),
|
||||
|
||||
UniqueConstraint('host_id', 'ptp_instance_id', name='u_hostinstance'),
|
||||
|
||||
mysql_engine=ENGINE,
|
||||
mysql_charset=CHARSET,
|
||||
)
|
||||
ptp_instance_maps.create()
|
||||
tables.update({'ptp_instance_maps': ptp_instance_maps})
|
||||
|
||||
interfaces = Table('interfaces', meta, autoload=True)
|
||||
tables.update({'interfaces': interfaces})
|
||||
|
||||
ptp_interface_maps = Table(
|
||||
'ptp_interface_maps',
|
||||
meta,
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('deleted_at', DateTime),
|
||||
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('uuid', String(UUID_LENGTH), unique=True),
|
||||
|
||||
Column('interface_id', Integer,
|
||||
ForeignKey('interfaces.id', ondelete='CASCADE'),
|
||||
nullable=False),
|
||||
Column('ptp_interface_id', Integer,
|
||||
ForeignKey('ptp_interfaces.id', ondelete='CASCADE'),
|
||||
nullable=False),
|
||||
|
||||
UniqueConstraint('interface_id', 'ptp_interface_id',
|
||||
name='u_ifaceptpiface'),
|
||||
|
||||
mysql_engine=ENGINE,
|
||||
mysql_charset=CHARSET,
|
||||
)
|
||||
ptp_interface_maps.create()
|
||||
tables.update({'ptp_interface_maps': ptp_interface_maps})
|
||||
|
||||
_populate_ptp_tables(meta, tables)
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
ptp_interface_maps = Table('ptp_interface_maps', meta, autoload=True)
|
||||
ptp_interface_maps.drop()
|
||||
|
||||
ptp_instance_maps = Table('ptp_instance_maps', meta, autoload=True)
|
||||
ptp_instance_maps.drop()
|
||||
|
||||
ptp_parameter_ownerships = Table('ptp_parameter_ownerships',
|
||||
meta,
|
||||
autoload=True)
|
||||
|
|
|
@ -245,14 +245,19 @@ class ihost(Base):
|
|||
peer_id = Column(Integer,
|
||||
ForeignKey('peers.id'))
|
||||
|
||||
ptp_instance_id = Column(Integer, ForeignKey('ptp_instances.id'))
|
||||
ptp = relationship("PtpInstances", lazy="joined", join_depth=1)
|
||||
|
||||
system = relationship("isystem")
|
||||
|
||||
host_upgrade = relationship("HostUpgrade", uselist=False)
|
||||
kube_host_upgrade = relationship("KubeHostUpgrade", uselist=False)
|
||||
|
||||
ptp_instances = relationship(
|
||||
"PtpInstances",
|
||||
secondary="ptp_instance_maps",
|
||||
primaryjoin="ihost.id == foreign(PtpInstanceMaps.host_id)",
|
||||
secondaryjoin="PtpInstances.id == "
|
||||
"foreign(PtpInstanceMaps.ptp_instance_id)",
|
||||
back_populates="hosts", lazy="joined", join_depth=1)
|
||||
|
||||
|
||||
class inode(Base):
|
||||
__tablename__ = 'i_node'
|
||||
|
@ -361,9 +366,6 @@ class Interfaces(Base):
|
|||
sriov_vf_driver = Column(String(255))
|
||||
ptp_role = Column(String(255), default='none') # TODO: deprecate it
|
||||
|
||||
ptp_interface_id = Column(Integer, ForeignKey('ptp_interfaces.id'))
|
||||
ptp = relationship("PtpInterfaces", lazy="joined", join_depth=1)
|
||||
|
||||
used_by = relationship(
|
||||
"Interfaces",
|
||||
secondary=interfaces_to_interfaces,
|
||||
|
@ -389,6 +391,14 @@ class Interfaces(Base):
|
|||
backref=backref("interface", lazy="joined"),
|
||||
cascade="all")
|
||||
|
||||
ptp_interfaces = relationship(
|
||||
"PtpInterfaces",
|
||||
secondary="ptp_interface_maps",
|
||||
primaryjoin="Interfaces.id == foreign(PtpInterfaceMaps.interface_id)",
|
||||
secondaryjoin="PtpInterfaces.id == "
|
||||
"foreign(PtpInterfaceMaps.ptp_interface_id)",
|
||||
back_populates="interfaces", lazy="joined", join_depth=1)
|
||||
|
||||
UniqueConstraint('ifname', 'forihostid', name='u_interfacenameihost')
|
||||
|
||||
__mapper_args__ = {
|
||||
|
@ -846,6 +856,14 @@ class PtpInstances(PtpParameterOwners):
|
|||
name = Column(String(255), unique=True, nullable=False)
|
||||
service = Column(String(255))
|
||||
|
||||
hosts = relationship(
|
||||
"ihost",
|
||||
secondary="ptp_instance_maps",
|
||||
primaryjoin="PtpInstances.id == "
|
||||
"foreign(PtpInstanceMaps.ptp_instance_id)",
|
||||
secondaryjoin="ihost.id == foreign(PtpInstanceMaps.host_id)",
|
||||
back_populates="ptp_instances", lazy="joined", join_depth=1)
|
||||
|
||||
__mapper_args__ = {
|
||||
'polymorphic_identity': constants.PTP_PARAMETER_OWNER_INSTANCE
|
||||
}
|
||||
|
@ -868,6 +886,15 @@ class PtpInterfaces(PtpParameterOwners):
|
|||
PtpInstances.name,
|
||||
PtpInstances.uuid])
|
||||
|
||||
interfaces = relationship(
|
||||
"Interfaces",
|
||||
secondary="ptp_interface_maps",
|
||||
primaryjoin="PtpInterfaces.id == "
|
||||
"foreign(PtpInterfaceMaps.ptp_interface_id)",
|
||||
secondaryjoin="Interfaces.id == "
|
||||
"foreign(PtpInterfaceMaps.interface_id)",
|
||||
back_populates="ptp_interfaces", lazy="joined", join_depth=1)
|
||||
|
||||
__mapper_args__ = {
|
||||
'polymorphic_identity': constants.PTP_PARAMETER_OWNER_INTERFACE
|
||||
}
|
||||
|
@ -887,20 +914,64 @@ class PtpParameterOwnerships(Base):
|
|||
ForeignKey('ptp_parameters.uuid',
|
||||
ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
owner_uuid = Column(String(UUID_LENGTH), nullable=False)
|
||||
owner_uuid = Column(String(UUID_LENGTH),
|
||||
ForeignKey('ptp_parameter_owners.uuid',
|
||||
ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
|
||||
parameter = relationship("PtpParameters", lazy="joined", join_depth=1)
|
||||
|
||||
owner = relationship(
|
||||
"PtpParameterOwners",
|
||||
primaryjoin="PtpParameterOwnerships.owner_uuid == "
|
||||
"foreign(PtpParameterOwners.uuid)",
|
||||
lazy="joined",
|
||||
join_depth=1)
|
||||
owner = relationship("PtpParameterOwners", lazy="joined", join_depth=1)
|
||||
|
||||
UniqueConstraint('parameter_uuid', 'owner_uuid', name='u_paramowner')
|
||||
|
||||
|
||||
class PtpInstanceMaps(Base):
|
||||
"""
|
||||
This is a bridge table used to model the many-to-many relationship between
|
||||
PTP instances (the services) and the hosts they run.
|
||||
"""
|
||||
__tablename__ = "ptp_instance_maps"
|
||||
|
||||
id = Column(Integer, primary_key=True, nullable=False)
|
||||
uuid = Column(String(UUID_LENGTH), unique=True)
|
||||
|
||||
host_id = Column(Integer,
|
||||
ForeignKey('i_host.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
ptp_instance_id = Column(
|
||||
Integer, ForeignKey('ptp_instances.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
|
||||
host = relationship("ihost", lazy="joined", join_depth=1)
|
||||
instance = relationship("PtpInstances", lazy="joined", join_depth=1)
|
||||
|
||||
UniqueConstraint('host_id', 'ptp_instance_id', name='u_hostinstance')
|
||||
|
||||
|
||||
class PtpInterfaceMaps(Base):
|
||||
"""
|
||||
This is a bridge table used to model the many-to-many relationship between
|
||||
PTP interfaces (PTP services and parameters) and the interfaces they run.
|
||||
"""
|
||||
__tablename__ = "ptp_interface_maps"
|
||||
|
||||
id = Column(Integer, primary_key=True, nullable=False)
|
||||
uuid = Column(String(UUID_LENGTH), unique=True)
|
||||
|
||||
interface_id = Column(Integer,
|
||||
ForeignKey('interfaces.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
ptp_interface_id = Column(
|
||||
Integer, ForeignKey('ptp_interfaces.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
|
||||
interface = relationship("Interfaces", lazy="joined", join_depth=1)
|
||||
ptp_interface = relationship("PtpInterfaces", lazy="joined", join_depth=1)
|
||||
|
||||
UniqueConstraint('interface_id', 'ptp_interface_id',
|
||||
name='u_ifaceptpiface')
|
||||
|
||||
|
||||
class StorageTier(Base):
|
||||
__tablename__ = 'storage_tiers'
|
||||
|
||||
|
|
|
@ -71,7 +71,9 @@ from sysinv.objects import peer
|
|||
from sysinv.objects import port
|
||||
from sysinv.objects import ptp
|
||||
from sysinv.objects import ptp_instance
|
||||
from sysinv.objects import ptp_instance_map
|
||||
from sysinv.objects import ptp_interface
|
||||
from sysinv.objects import ptp_interface_map
|
||||
from sysinv.objects import ptp_parameter
|
||||
from sysinv.objects import ptp_paramowner
|
||||
from sysinv.objects import ptp_paramownership
|
||||
|
@ -160,7 +162,9 @@ dns = dns.DNS
|
|||
ntp = ntp.NTP
|
||||
ptp = ptp.PTP
|
||||
ptp_instance = ptp_instance.PtpInstance
|
||||
ptp_instance_map = ptp_instance_map.PtpInstanceMap
|
||||
ptp_interface = ptp_interface.PtpInterface
|
||||
ptp_interface_map = ptp_interface_map.PtpInterfaceMap
|
||||
ptp_parameter = ptp_parameter.PtpParameter
|
||||
ptp_paramowner = ptp_paramowner.PtpParameterOwner
|
||||
ptp_paramownership = ptp_paramownership.PtpParameterOwnership
|
||||
|
@ -244,7 +248,9 @@ __all__ = ("system",
|
|||
"ntp",
|
||||
"ptp",
|
||||
"ptp_instance",
|
||||
"ptp_instance_map",
|
||||
"ptp_interface",
|
||||
"ptp_interface_map",
|
||||
"ptp_parameter",
|
||||
"ptp_paramowner",
|
||||
"ptp_paramownership",
|
||||
|
|
|
@ -23,11 +23,6 @@ def _get_target_load(field, db_object):
|
|||
return db_object.host_upgrade.load_target.software_version
|
||||
|
||||
|
||||
def _get_ptp_configuration(field, db_object):
|
||||
# TODO
|
||||
return {}
|
||||
|
||||
|
||||
class Host(base.SysinvObject):
|
||||
|
||||
dbapi = db_api.get_instance()
|
||||
|
@ -37,7 +32,6 @@ class Host(base.SysinvObject):
|
|||
'forisystemid': utils.int_or_none,
|
||||
'isystem_uuid': utils.str_or_none,
|
||||
'peer_id': utils.int_or_none,
|
||||
'ptp_instance_id': utils.int_or_none,
|
||||
'recordtype': utils.str_or_none,
|
||||
|
||||
# 'created_at': utils.datetime_str_or_none,
|
||||
|
@ -82,7 +76,6 @@ class Host(base.SysinvObject):
|
|||
'config_target': utils.str_or_none,
|
||||
'capabilities': utils.dict_or_none,
|
||||
'clock_synchronization': utils.str_or_none,
|
||||
'ptp_config': utils.dict_or_none,
|
||||
|
||||
'boot_device': utils.str_or_none,
|
||||
'rootfs_device': utils.str_or_none,
|
||||
|
@ -103,8 +96,7 @@ class Host(base.SysinvObject):
|
|||
_foreign_fields = {
|
||||
'isystem_uuid': 'system:uuid',
|
||||
'software_load': _get_software_load,
|
||||
'target_load': _get_target_load,
|
||||
'ptp_config': _get_ptp_configuration
|
||||
'target_load': _get_target_load
|
||||
}
|
||||
|
||||
@base.remotable_classmethod
|
||||
|
|
|
@ -108,11 +108,6 @@ def get_datanetworks(field, db_object):
|
|||
return result
|
||||
|
||||
|
||||
def _get_ptp_configuration(field, db_object):
|
||||
# TODO
|
||||
return {}
|
||||
|
||||
|
||||
class Interface(base.SysinvObject):
|
||||
# VERSION 1.0: Initial version
|
||||
# VERSION 1.1: Added VLAN and uses/used_by interface support
|
||||
|
@ -125,7 +120,6 @@ class Interface(base.SysinvObject):
|
|||
'uuid': utils.str_or_none,
|
||||
'forihostid': utils.int_or_none,
|
||||
'ihost_uuid': utils.str_or_none,
|
||||
'ptp_interface_id': utils.int_or_none,
|
||||
|
||||
'ifname': utils.str_or_none,
|
||||
'iftype': utils.str_or_none,
|
||||
|
@ -154,7 +148,6 @@ class Interface(base.SysinvObject):
|
|||
'sriov_numvfs': utils.int_or_none,
|
||||
'sriov_vf_driver': utils.str_or_none,
|
||||
'ptp_role': utils.str_or_none,
|
||||
'ptp_config': utils.dict_or_none,
|
||||
'max_tx_rate': utils.int_or_none,
|
||||
}
|
||||
|
||||
|
@ -166,8 +159,7 @@ class Interface(base.SysinvObject):
|
|||
'ipv6_pool': get_ipv6_address_pool,
|
||||
'ihost_uuid': get_host_uuid,
|
||||
'networktypelist': get_networktypes,
|
||||
'datanetworks': get_datanetworks,
|
||||
'ptp_config': _get_ptp_configuration}
|
||||
'datanetworks': get_datanetworks}
|
||||
|
||||
_optional_fields = ['aemode', 'txhashpolicy', 'schedpolicy',
|
||||
'vlan_id', 'vlan_type', 'primary_reselect']
|
||||
|
|
|
@ -12,16 +12,30 @@ from sysinv.objects import utils
|
|||
from sysinv.objects import ptp_paramowner
|
||||
|
||||
|
||||
def get_hosts(field, db_object):
|
||||
hosts = db_object['hosts']
|
||||
if not hosts:
|
||||
return []
|
||||
|
||||
hostnames = []
|
||||
for h in hosts:
|
||||
hostnames.append(h.hostname)
|
||||
return hostnames
|
||||
|
||||
|
||||
class PtpInstance(ptp_paramowner.PtpParameterOwner):
|
||||
|
||||
dbapi = db_api.get_instance()
|
||||
|
||||
fields = dict({
|
||||
'name': utils.str_or_none,
|
||||
'service': utils.str_or_none
|
||||
'service': utils.str_or_none,
|
||||
'hosts': utils.list_of_strings_or_none
|
||||
}, **ptp_paramowner.PtpParameterOwner.fields)
|
||||
|
||||
_foreign_fields = {}
|
||||
_foreign_fields = {
|
||||
'hosts': get_hosts
|
||||
}
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_uuid(cls, context, uuid):
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
########################################################################
|
||||
#
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
########################################################################
|
||||
|
||||
from sysinv.db import api as db_api
|
||||
from sysinv.objects import base
|
||||
from sysinv.objects import utils
|
||||
|
||||
|
||||
class PtpInstanceMap(base.SysinvObject):
|
||||
|
||||
dbapi = db_api.get_instance()
|
||||
|
||||
fields = {
|
||||
'id': int,
|
||||
'uuid': utils.str_or_none,
|
||||
|
||||
'host_id': int,
|
||||
'hostname': utils.str_or_none,
|
||||
|
||||
'ptp_instance_id': int,
|
||||
'name': utils.str_or_none,
|
||||
'service': utils.str_or_none
|
||||
}
|
||||
|
||||
_foreign_fields = {
|
||||
'host_id': 'host:id',
|
||||
'hostname': 'host:hostname',
|
||||
'ptp_instance_id': 'ptp_instance:id',
|
||||
'name': 'ptp_instance:name',
|
||||
'service': 'ptp_instance:service'
|
||||
}
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_uuid(cls, context, uuid):
|
||||
return cls.dbapi.ptp_instance_map_get(uuid)
|
|
@ -12,6 +12,24 @@ from sysinv.objects import utils
|
|||
from sysinv.objects import ptp_paramowner
|
||||
|
||||
|
||||
def get_interfaces(field, db_object):
|
||||
interfaces = db_object['interfaces']
|
||||
if not interfaces:
|
||||
return []
|
||||
|
||||
interfaces = []
|
||||
for i in interfaces:
|
||||
details = {}
|
||||
details['name'] = i.ifname
|
||||
details['type'] = i.iftype
|
||||
host = getattr(i, 'host')
|
||||
if host:
|
||||
details['host'] = host.hostname
|
||||
interfaces.append(details)
|
||||
|
||||
return interfaces
|
||||
|
||||
|
||||
class PtpInterface(ptp_paramowner.PtpParameterOwner):
|
||||
|
||||
dbapi = db_api.get_instance()
|
||||
|
@ -19,12 +37,14 @@ class PtpInterface(ptp_paramowner.PtpParameterOwner):
|
|||
fields = dict({
|
||||
'ptp_instance_id': utils.int_or_none,
|
||||
'ptp_instance_uuid': utils.str_or_none,
|
||||
'ptp_instance_name': utils.str_or_none
|
||||
'ptp_instance_name': utils.str_or_none,
|
||||
'interfaces': list
|
||||
}, **ptp_paramowner.PtpParameterOwner.fields)
|
||||
|
||||
_foreign_fields = {
|
||||
'ptp_instance_uuid': 'ptp_instance:uuid',
|
||||
'ptp_instance_name': 'ptp_instance:name'
|
||||
'ptp_instance_name': 'ptp_instance:name',
|
||||
'interfaces': get_interfaces
|
||||
}
|
||||
|
||||
@base.remotable_classmethod
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
########################################################################
|
||||
#
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
########################################################################
|
||||
|
||||
from sysinv.db import api as db_api
|
||||
from sysinv.objects import base
|
||||
from sysinv.objects import utils
|
||||
|
||||
|
||||
def get_hostname(field, db_object):
|
||||
host = getattr(db_object['interface'], 'host')
|
||||
if not host:
|
||||
return None
|
||||
|
||||
return host.hostname
|
||||
|
||||
|
||||
def get_instance_name(field, db_object):
|
||||
instance = getattr(db_object['ptp_interface'], 'ptp_instance')
|
||||
if not instance:
|
||||
return None
|
||||
|
||||
return instance.name
|
||||
|
||||
|
||||
def get_instance_service(field, db_object):
|
||||
instance = getattr(db_object['ptp_interface'], 'ptp_instance')
|
||||
if not instance:
|
||||
return None
|
||||
|
||||
return instance.service
|
||||
|
||||
|
||||
class PtpInterfaceMap(base.SysinvObject):
|
||||
|
||||
dbapi = db_api.get_instance()
|
||||
|
||||
fields = {
|
||||
'id': int,
|
||||
'uuid': utils.str_or_none,
|
||||
|
||||
'interface_id': int,
|
||||
'ifname': utils.str_or_none,
|
||||
'iftype': utils.str_or_none,
|
||||
'hostname': utils.str_or_none,
|
||||
|
||||
'ptp_interface_id': int,
|
||||
'name': utils.str_or_none,
|
||||
'service': utils.str_or_none
|
||||
}
|
||||
|
||||
_foreign_fields = {
|
||||
'interface_id': 'interface:id',
|
||||
'ifname': 'interface:ifname',
|
||||
'iftype': 'interface:iftype',
|
||||
'hostname': get_hostname,
|
||||
'ptp_interface_id': 'ptp_interface:id',
|
||||
'name': get_instance_name,
|
||||
'service': get_instance_service
|
||||
}
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_uuid(cls, context, uuid):
|
||||
return cls.dbapi.ptp_interface_map_get(uuid)
|
|
@ -20,10 +20,18 @@ class PtpParameterOwnership(base.SysinvObject):
|
|||
'uuid': utils.str_or_none,
|
||||
|
||||
'parameter_uuid': utils.str_or_none,
|
||||
'parameter_name': utils.str_or_none,
|
||||
'parameter_value': utils.str_or_none,
|
||||
|
||||
'owner_uuid': utils.str_or_none,
|
||||
}
|
||||
|
||||
_foreign_fields = {}
|
||||
_foreign_fields = {
|
||||
'parameter_uuid': 'parameter:uuid',
|
||||
'parameter_name': 'parameter:name',
|
||||
'parameter_value': 'parameter:value',
|
||||
'owner_uuid': 'owner:uuid'
|
||||
}
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_uuid(cls, context, uuid):
|
||||
|
|
|
@ -2061,3 +2061,33 @@ class TestMigrations(BaseMigrationTestCase, WalkVersionsMixin):
|
|||
self.assertTrue(
|
||||
isinstance(ptp_parameter_ownerships.c[column].type,
|
||||
getattr(sqlalchemy.types, column_type)))
|
||||
|
||||
ptp_instance_maps = db_utils.get_table(engine, 'ptp_instance_maps')
|
||||
ptp_instance_map_columns = {
|
||||
'created_at': 'DateTime',
|
||||
'updated_at': 'DateTime',
|
||||
'deleted_at': 'DateTime',
|
||||
'id': 'Integer',
|
||||
'uuid': 'String',
|
||||
'host_id': 'Integer',
|
||||
'ptp_instance_id': 'Integer'
|
||||
}
|
||||
for column, column_type in ptp_instance_map_columns.items():
|
||||
self.assertTrue(
|
||||
isinstance(ptp_instance_maps.c[column].type,
|
||||
getattr(sqlalchemy.types, column_type)))
|
||||
|
||||
ptp_interface_maps = db_utils.get_table(engine, 'ptp_interface_maps')
|
||||
ptp_interface_map_columns = {
|
||||
'created_at': 'DateTime',
|
||||
'updated_at': 'DateTime',
|
||||
'deleted_at': 'DateTime',
|
||||
'id': 'Integer',
|
||||
'uuid': 'String',
|
||||
'interface_id': 'Integer',
|
||||
'ptp_interface_id': 'Integer'
|
||||
}
|
||||
for column, column_type in ptp_interface_map_columns.items():
|
||||
self.assertTrue(
|
||||
isinstance(ptp_interface_maps.c[column].type,
|
||||
getattr(sqlalchemy.types, column_type)))
|
||||
|
|
|
@ -597,6 +597,34 @@ def create_test_ptp_ownership(**kw):
|
|||
return dbapi.ptp_parameter_set_owner(ownership)
|
||||
|
||||
|
||||
def get_test_ptp_instance_map(**kw):
|
||||
map = {
|
||||
'host_id': kw.get('host_id', None),
|
||||
'ptp_instance_id': kw.get('ptp_instance_id', None)
|
||||
}
|
||||
return map
|
||||
|
||||
|
||||
def create_test_ptp_instance_map(**kw):
|
||||
map = get_test_ptp_instance_map(**kw)
|
||||
dbapi = db_api.get_instance()
|
||||
return dbapi.ptp_instance_set_host(map)
|
||||
|
||||
|
||||
def get_test_ptp_interface_map(**kw):
|
||||
map = {
|
||||
'interface_id': kw.get('interface_id', None),
|
||||
'ptp_interface_id': kw.get('ptp_interface_id', None)
|
||||
}
|
||||
return map
|
||||
|
||||
|
||||
def create_test_ptp_interface_map(**kw):
|
||||
map = get_test_ptp_interface_map(**kw)
|
||||
dbapi = db_api.get_instance()
|
||||
return dbapi.ptp_interface_set_interface(map)
|
||||
|
||||
|
||||
# Create test dns object
|
||||
def get_test_dns(**kw):
|
||||
dns = {
|
||||
|
|
Loading…
Reference in New Issue