
Use num_or_none instead of int_or_none to support those resource property in float. Change-Id: I8830e7104ff69524379ccfbd90eda37133a8960a
234 lines
8.5 KiB
Python
234 lines
8.5 KiB
Python
# Copyright 2018 Intel, 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.
|
|
|
|
import jsonschema
|
|
import logging
|
|
|
|
from sushy.resources import base
|
|
from sushy import utils
|
|
|
|
from rsd_lib.resources.v2_3.fabric import endpoint_schemas
|
|
from rsd_lib import utils as rsd_lib_utils
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class IdentifiersField(base.ListField):
|
|
name_format = base.Field('DurableNameFormat')
|
|
name = base.Field('DurableName')
|
|
|
|
|
|
class ConnectedEntitiesField(base.ListField):
|
|
entity_type = base.Field('EntityType')
|
|
entity_role = base.Field('EntityRole')
|
|
entity_link = base.Field('EntityLink',
|
|
adapter=rsd_lib_utils.get_resource_identity)
|
|
|
|
|
|
class StatusField(base.CompositeField):
|
|
state = base.Field('State')
|
|
health = base.Field('Health')
|
|
health_rollup = base.Field('HealthRollup')
|
|
|
|
|
|
class LinksField(base.CompositeField):
|
|
ports = base.Field('Ports', adapter=utils.get_members_identities)
|
|
endpoints = base.Field('Endpoints', adapter=utils.get_members_identities)
|
|
zones = base.Field(['Oem', 'Intel_RackScale', 'Zones'],
|
|
adapter=utils.get_members_identities)
|
|
interface = base.Field(['Oem', 'Intel_RackScale', 'Interface'],
|
|
adapter=rsd_lib_utils.get_resource_identity)
|
|
|
|
|
|
class IPTransportDetailsField(base.ListField):
|
|
transport_protocol = base.Field('TransportProtocol')
|
|
ipv4_address = base.Field(['IPv4Address', 'Address'])
|
|
ipv6_address = base.Field(['IPv6Address', 'Address'])
|
|
port = base.Field('Port', adapter=rsd_lib_utils.num_or_none)
|
|
|
|
|
|
class AuthenticationField(base.CompositeField):
|
|
username = base.Field('Username')
|
|
password = base.Field('Password')
|
|
|
|
|
|
class OemField(base.CompositeField):
|
|
authentication = AuthenticationField(['Intel_RackScale', 'Authentication'])
|
|
|
|
|
|
class Endpoint(base.ResourceBase):
|
|
|
|
connected_entities = ConnectedEntitiesField('ConnectedEntities')
|
|
"""Entities connected to endpoint"""
|
|
|
|
description = base.Field('Description')
|
|
"""The endpoint description"""
|
|
|
|
protocol = base.Field('EndpointProtocol')
|
|
"""Protocol for endpoint (i.e. PCIe)"""
|
|
|
|
identifiers = IdentifiersField('Identifiers')
|
|
"""Identifiers for endpoint"""
|
|
|
|
identity = base.Field('Id', required=True)
|
|
"""The endpoint identity string"""
|
|
|
|
name = base.Field('Name')
|
|
"""The endpoint name"""
|
|
|
|
status = StatusField('Status')
|
|
"""The endpoint status"""
|
|
|
|
links = LinksField('Links')
|
|
"""These links to related components of this endpoint"""
|
|
|
|
ip_transport_details = IPTransportDetailsField('IPTransportDetails')
|
|
"""IP transport details info of this endpoint"""
|
|
|
|
oem = OemField('Oem')
|
|
"""The OEM additional info of this endpoint"""
|
|
|
|
def __init__(self, connector, identity, redfish_version=None):
|
|
"""A class representing an Endpoint
|
|
|
|
:param connector: A Connector instance
|
|
:param identity: The identity of the RemoteTarget resource
|
|
:param redfish_version: The version of RedFish. Used to construct
|
|
the object according to schema of the given version.
|
|
"""
|
|
super(Endpoint, self).__init__(connector, identity,
|
|
redfish_version)
|
|
|
|
def update_authentication(self, username=None, password=None):
|
|
"""Update endpoint authentication
|
|
|
|
:param username: an endpoint username used to authenticate it on the
|
|
other side of a communication channel
|
|
:param password: an endpoint password
|
|
:raises: BadRequestError if at least one param isn't specified
|
|
"""
|
|
if username is None and password is None:
|
|
raise ValueError('At least "username" or "password" parameter has '
|
|
'to be specified')
|
|
|
|
data = {
|
|
"Oem": {
|
|
"Intel_RackScale": {
|
|
"@odata.type": "#Intel.Oem.Endpoint",
|
|
"Authentication": {}
|
|
}
|
|
}
|
|
}
|
|
if username is not None:
|
|
data['Oem']['Intel_RackScale']['Authentication']['Username'] = \
|
|
username
|
|
if password is not None:
|
|
data['Oem']['Intel_RackScale']['Authentication']['Password'] = \
|
|
password
|
|
|
|
self._conn.patch(self.path, data=data)
|
|
|
|
|
|
class EndpointCollection(base.ResourceCollectionBase):
|
|
|
|
@property
|
|
def _resource_type(self):
|
|
return Endpoint
|
|
|
|
def __init__(self, connector, path, redfish_version=None):
|
|
"""A class representing an Endpoint
|
|
|
|
:param connector: A Connector instance
|
|
:param path: The canonical path to the Endpoint collection resource
|
|
:param redfish_version: The version of RedFish. Used to construct
|
|
the object according to schema of the given version.
|
|
"""
|
|
super(EndpointCollection, self).__init__(connector, path,
|
|
redfish_version)
|
|
|
|
def _create_endpoint_request(self, identifiers, connected_entities,
|
|
protocol=None, ip_transport_details=None,
|
|
interface=None, authentication=None):
|
|
|
|
request = {}
|
|
|
|
jsonschema.validate(identifiers,
|
|
endpoint_schemas.identifiers_req_schema)
|
|
request['Identifiers'] = identifiers
|
|
|
|
jsonschema.validate(connected_entities,
|
|
endpoint_schemas.connected_entities_req_schema)
|
|
request['ConnectedEntities'] = connected_entities
|
|
|
|
if protocol is not None:
|
|
jsonschema.validate(protocol, endpoint_schemas.protocol_req_schema)
|
|
request['EndpointProtocol'] = protocol
|
|
|
|
if ip_transport_details is not None:
|
|
jsonschema.validate(
|
|
ip_transport_details,
|
|
endpoint_schemas.ip_transport_details_req_schema)
|
|
request['IPTransportDetails'] = ip_transport_details
|
|
|
|
if interface is not None:
|
|
jsonschema.validate(interface,
|
|
endpoint_schemas.interface_req_schema)
|
|
request['Links'] = {
|
|
"Oem": {
|
|
"Intel_RackScale": {
|
|
"Interfaces": [
|
|
{
|
|
"@odata.id": interface
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
if authentication is not None:
|
|
jsonschema.validate(authentication,
|
|
endpoint_schemas.authentication_req_schema)
|
|
request['Oem'] = {"Intel_RackScale":
|
|
{"Authentication": authentication}}
|
|
|
|
return request
|
|
|
|
def create_endpoint(self, identifiers, connected_entities, protocol=None,
|
|
ip_transport_details=None, interface=None,
|
|
authentication=None):
|
|
"""Create a new endpoint
|
|
|
|
:param identifiers: provides iQN or NQN of created entity
|
|
:param connected_entities: provides information about entities
|
|
connected to the endpoint
|
|
:param protocol: the protocol used by the endpoint
|
|
:param ip_transport_details: the transport used for accessing the
|
|
endpoint
|
|
:param interface: the interface that should be used for the endpoint
|
|
connectivity
|
|
:param authentication: authentication data for target-initiator
|
|
authentication. Currently supported only for the
|
|
iSCSI protocol.
|
|
:returns: The uri of the new endpoint
|
|
"""
|
|
properties = self._create_endpoint_request(
|
|
identifiers, connected_entities, protocol, ip_transport_details,
|
|
interface, authentication)
|
|
resp = self._conn.post(self._path, data=properties)
|
|
LOG.info("Endpoint created at %s", resp.headers['Location'])
|
|
endpoint_url = resp.headers['Location']
|
|
return endpoint_url[endpoint_url.find(self._path):]
|