501 lines
18 KiB
Python
501 lines
18 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 copy
|
|
import json
|
|
import jsonschema
|
|
import mock
|
|
import testtools
|
|
|
|
from rsd_lib.resources.v2_3.fabric import endpoint
|
|
from rsd_lib.tests.unit.fakes import request_fakes
|
|
|
|
|
|
class EndpointTestCase(testtools.TestCase):
|
|
def setUp(self):
|
|
super(EndpointTestCase, self).setUp()
|
|
self.conn = mock.Mock()
|
|
with open(
|
|
"rsd_lib/tests/unit/json_samples/v2_3/endpoint_1.json", "r"
|
|
) as f:
|
|
self.conn.get.return_value.json.return_value = json.loads(f.read())
|
|
|
|
self.endpoint_inst = endpoint.Endpoint(
|
|
self.conn,
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints/1",
|
|
redfish_version="1.0.2",
|
|
)
|
|
|
|
def test__parse_attributes(self):
|
|
self.assertEqual("1.0.2", self.endpoint_inst.redfish_version)
|
|
self.assertEqual("Fabric Endpoint", self.endpoint_inst.description)
|
|
self.assertEqual("1", self.endpoint_inst.identity)
|
|
self.assertEqual("Fabric Endpoint", self.endpoint_inst.name)
|
|
self.assertEqual(
|
|
"Target", self.endpoint_inst.connected_entities[0].entity_role
|
|
)
|
|
self.assertEqual(
|
|
"/redfish/v1/StorageServices/1/Volumes/1",
|
|
self.endpoint_inst.connected_entities[0].entity_link,
|
|
)
|
|
self.assertEqual("Enabled", self.endpoint_inst.status.state)
|
|
self.assertEqual("OK", self.endpoint_inst.status.health)
|
|
self.assertEqual("OK", self.endpoint_inst.status.health_rollup)
|
|
self.assertEqual("NVMeOverFabrics", self.endpoint_inst.protocol)
|
|
self.assertEqual("NQN", self.endpoint_inst.identifiers[0].name_format)
|
|
self.assertEqual(
|
|
"nqn.2014-08.org.nvmexpress:NVMf:uuid:"
|
|
"397f9b78-7e94-11e7-9ea4-001e67dfa170",
|
|
self.endpoint_inst.identifiers[0].name,
|
|
)
|
|
self.assertEqual("UUID", self.endpoint_inst.identifiers[1].name_format)
|
|
self.assertEqual(
|
|
"397f9b78-7e94-11e7-9ea4-001e67dfa170",
|
|
self.endpoint_inst.identifiers[1].name,
|
|
)
|
|
self.assertEqual((), self.endpoint_inst.links.ports)
|
|
self.assertEqual((), self.endpoint_inst.links.endpoints)
|
|
self.assertEqual(
|
|
("/redfish/v1/Fabrics/NVMeoE/Zones/1",),
|
|
self.endpoint_inst.links.zones,
|
|
)
|
|
self.assertEqual(
|
|
"/redfish/v1/Systems/Target/EthernetInterfaces/1",
|
|
self.endpoint_inst.links.interface,
|
|
)
|
|
self.assertEqual(
|
|
"RoCEv2",
|
|
self.endpoint_inst.ip_transport_details[0].transport_protocol,
|
|
)
|
|
self.assertEqual(
|
|
"192.168.0.10",
|
|
self.endpoint_inst.ip_transport_details[0].ipv4_address,
|
|
)
|
|
self.assertEqual(
|
|
None, self.endpoint_inst.ip_transport_details[0].ipv6_address
|
|
)
|
|
self.assertEqual(1023, self.endpoint_inst.ip_transport_details[0].port)
|
|
self.assertEqual(None, self.endpoint_inst.oem.authentication)
|
|
|
|
with open(
|
|
"rsd_lib/tests/unit/json_samples/v2_3/endpoint_2.json", "r"
|
|
) as f:
|
|
self.conn.get.return_value.json.return_value = json.loads(f.read())
|
|
|
|
self.endpoint_inst.refresh()
|
|
self.assertEqual("1.0.2", self.endpoint_inst.redfish_version)
|
|
self.assertEqual(
|
|
"Fabric Initiator Endpoint", self.endpoint_inst.description
|
|
)
|
|
self.assertEqual("1", self.endpoint_inst.identity)
|
|
self.assertEqual("Fabric Endpoint", self.endpoint_inst.name)
|
|
self.assertEqual(
|
|
"Initiator", self.endpoint_inst.connected_entities[0].entity_role
|
|
)
|
|
self.assertEqual(
|
|
None, self.endpoint_inst.connected_entities[0].entity_link
|
|
)
|
|
self.assertEqual(None, self.endpoint_inst.status.state)
|
|
self.assertEqual(None, self.endpoint_inst.status.health)
|
|
self.assertEqual(None, self.endpoint_inst.status.health_rollup)
|
|
self.assertEqual("NVMeOverFabrics", self.endpoint_inst.protocol)
|
|
self.assertEqual("NQN", self.endpoint_inst.identifiers[0].name_format)
|
|
self.assertEqual(
|
|
"nqn.2014-08.org.nvmexpress:NVMf:uuid:"
|
|
"12345678-90ab-cdef-0000-000000000000",
|
|
self.endpoint_inst.identifiers[0].name,
|
|
)
|
|
self.assertEqual("UUID", self.endpoint_inst.identifiers[1].name_format)
|
|
self.assertEqual(
|
|
"12345678-90ab-cdef-0000-000000000000",
|
|
self.endpoint_inst.identifiers[1].name,
|
|
)
|
|
self.assertEqual((), self.endpoint_inst.links.ports)
|
|
self.assertEqual((), self.endpoint_inst.links.endpoints)
|
|
self.assertEqual(
|
|
("/redfish/v1/Fabrics/NVMeoE/Zones/1",),
|
|
self.endpoint_inst.links.zones,
|
|
)
|
|
self.assertEqual(None, self.endpoint_inst.links.interface)
|
|
self.assertEqual(
|
|
"RoCEv2",
|
|
self.endpoint_inst.ip_transport_details[0].transport_protocol,
|
|
)
|
|
self.assertEqual(
|
|
"192.168.0.10",
|
|
self.endpoint_inst.ip_transport_details[0].ipv4_address,
|
|
)
|
|
self.assertEqual(
|
|
None, self.endpoint_inst.ip_transport_details[0].ipv6_address
|
|
)
|
|
self.assertEqual(4791, self.endpoint_inst.ip_transport_details[0].port)
|
|
self.assertEqual(None, self.endpoint_inst.oem.authentication)
|
|
|
|
def test_update_authentication(self):
|
|
self.endpoint_inst.update_authentication(username="fake-username")
|
|
self.endpoint_inst._conn.patch.assert_called_once_with(
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints/1",
|
|
data={
|
|
"Oem": {
|
|
"Intel_RackScale": {
|
|
"@odata.type": "#Intel.Oem.Endpoint",
|
|
"Authentication": {"Username": "fake-username"},
|
|
}
|
|
}
|
|
},
|
|
)
|
|
|
|
self.endpoint_inst._conn.patch.reset_mock()
|
|
self.endpoint_inst.update_authentication(password="fake-password")
|
|
self.endpoint_inst._conn.patch.assert_called_once_with(
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints/1",
|
|
data={
|
|
"Oem": {
|
|
"Intel_RackScale": {
|
|
"@odata.type": "#Intel.Oem.Endpoint",
|
|
"Authentication": {"Password": "fake-password"},
|
|
}
|
|
}
|
|
},
|
|
)
|
|
|
|
self.endpoint_inst._conn.patch.reset_mock()
|
|
self.endpoint_inst.update_authentication(
|
|
username="fake-username", password="fake-password"
|
|
)
|
|
self.endpoint_inst._conn.patch.assert_called_once_with(
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints/1",
|
|
data={
|
|
"Oem": {
|
|
"Intel_RackScale": {
|
|
"@odata.type": "#Intel.Oem.Endpoint",
|
|
"Authentication": {
|
|
"Username": "fake-username",
|
|
"Password": "fake-password",
|
|
},
|
|
}
|
|
}
|
|
},
|
|
)
|
|
|
|
def test_update_authentication_with_invalid_parameter(self):
|
|
with self.assertRaisesRegex(
|
|
ValueError,
|
|
'At least "username" or "password" parameter has to be specified',
|
|
):
|
|
self.endpoint_inst.update_authentication()
|
|
|
|
def test_delete(self):
|
|
self.endpoint_inst.delete()
|
|
self.endpoint_inst._conn.delete.assert_called_once_with(
|
|
self.endpoint_inst.path
|
|
)
|
|
|
|
|
|
class EndpointCollectionTestCase(testtools.TestCase):
|
|
def setUp(self):
|
|
super(EndpointCollectionTestCase, self).setUp()
|
|
self.conn = mock.Mock()
|
|
with open(
|
|
"rsd_lib/tests/unit/json_samples/v2_3/endpoint_collection.json",
|
|
"r",
|
|
) as f:
|
|
self.conn.get.return_value.json.return_value = json.loads(f.read())
|
|
|
|
self.conn.post.return_value = request_fakes.fake_request_post(
|
|
None,
|
|
headers={
|
|
"Location": "https://localhost:8443/redfish/v1/"
|
|
"Fabrics/NVMeoE/Endpoints/3"
|
|
},
|
|
)
|
|
|
|
self.endpoint_col = endpoint.EndpointCollection(
|
|
self.conn,
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints",
|
|
redfish_version="1.0.2",
|
|
)
|
|
|
|
def test__parse_attributes(self):
|
|
self.assertEqual("1.0.2", self.endpoint_col.redfish_version)
|
|
self.assertEqual("Endpoint Collection", self.endpoint_col.name)
|
|
self.assertEqual(
|
|
(
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints/1",
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints/2",
|
|
),
|
|
self.endpoint_col.members_identities,
|
|
)
|
|
|
|
@mock.patch.object(endpoint, "Endpoint", autospec=True)
|
|
def test_get_member(self, mock_endpoint):
|
|
self.endpoint_col.get_member("/redfish/v1/Fabrics/NVMeoE/Endpoints/1")
|
|
mock_endpoint.assert_called_once_with(
|
|
self.endpoint_col._conn,
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints/1",
|
|
redfish_version=self.endpoint_col.redfish_version,
|
|
registries=None,
|
|
)
|
|
|
|
@mock.patch.object(endpoint, "Endpoint", autospec=True)
|
|
def test_get_members(self, mock_endpoint):
|
|
members = self.endpoint_col.get_members()
|
|
calls = [
|
|
mock.call(
|
|
self.endpoint_col._conn,
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints/1",
|
|
redfish_version=self.endpoint_col.redfish_version,
|
|
registries=None,
|
|
),
|
|
mock.call(
|
|
self.endpoint_col._conn,
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints/2",
|
|
redfish_version=self.endpoint_col.redfish_version,
|
|
registries=None,
|
|
),
|
|
]
|
|
mock_endpoint.assert_has_calls(calls)
|
|
self.assertIsInstance(members, list)
|
|
self.assertEqual(2, len(members))
|
|
|
|
def test_create_endpoint(self):
|
|
reqs = {
|
|
"EndpointProtocol": "NVMeOverFabrics",
|
|
"Identifiers": [
|
|
{
|
|
"DurableNameFormat": "NQN",
|
|
"DurableName": "nqn.2014-08.org.nvmexpress:NVMf:"
|
|
"uuid:397f9b78-7e94-11e7-9ea4-001e67dfa170",
|
|
}
|
|
],
|
|
"ConnectedEntities": [
|
|
{
|
|
"EntityLink": {
|
|
"@odata.id": "/redfish/v1/StorageServices/1/Volumes/1"
|
|
},
|
|
"EntityRole": "Target",
|
|
}
|
|
],
|
|
"Links": {
|
|
"Oem": {
|
|
"Intel_RackScale": {
|
|
"Interfaces": [
|
|
{
|
|
"@odata.id": "/redfish/v1/Systems/Target/"
|
|
"EthernetInterfaces/1"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
}
|
|
result = self.endpoint_col.create_endpoint(
|
|
identifiers=[
|
|
{
|
|
"DurableNameFormat": "NQN",
|
|
"DurableName": "nqn.2014-08.org.nvmexpress:NVMf:"
|
|
"uuid:397f9b78-7e94-11e7-9ea4-001e67dfa170",
|
|
}
|
|
],
|
|
connected_entities=[
|
|
{
|
|
"EntityLink": {
|
|
"@odata.id": "/redfish/v1/StorageServices/1/Volumes/1"
|
|
},
|
|
"EntityRole": "Target",
|
|
}
|
|
],
|
|
protocol="NVMeOverFabrics",
|
|
interface="/redfish/v1/Systems/Target/EthernetInterfaces/1",
|
|
)
|
|
self.endpoint_col._conn.post.assert_called_once_with(
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints", data=reqs
|
|
)
|
|
self.assertEqual(result, "/redfish/v1/Fabrics/NVMeoE/Endpoints/3")
|
|
|
|
self.endpoint_col._conn.post.reset_mock()
|
|
reqs = {
|
|
"EndpointProtocol": "iSCSI",
|
|
"Identifiers": [
|
|
{
|
|
"DurableNameFormat": "iQN",
|
|
"DurableName": "iqn.1986-03.com.intel:my_storage-uuid:"
|
|
"397f9b78-7e94-11e7-9ea4-001e67dfa170",
|
|
}
|
|
],
|
|
"ConnectedEntities": [
|
|
{
|
|
"EntityLink": {
|
|
"@odata.id": "/redfish/v1/StorageServices/1/Volumes/1"
|
|
},
|
|
"EntityRole": "Target",
|
|
"Identifiers": [
|
|
{"DurableNameFormat": "LUN", "DurableName": "1"}
|
|
],
|
|
}
|
|
],
|
|
"Oem": {
|
|
"Intel_RackScale": {
|
|
"Authentication": {
|
|
"Username": "userA",
|
|
"Password": "passB",
|
|
}
|
|
}
|
|
},
|
|
}
|
|
result = self.endpoint_col.create_endpoint(
|
|
identifiers=[
|
|
{
|
|
"DurableNameFormat": "iQN",
|
|
"DurableName": "iqn.1986-03.com.intel:my_storage-uuid:"
|
|
"397f9b78-7e94-11e7-9ea4-001e67dfa170",
|
|
}
|
|
],
|
|
connected_entities=[
|
|
{
|
|
"EntityLink": {
|
|
"@odata.id": "/redfish/v1/StorageServices/1/Volumes/1"
|
|
},
|
|
"EntityRole": "Target",
|
|
"Identifiers": [
|
|
{"DurableNameFormat": "LUN", "DurableName": "1"}
|
|
],
|
|
}
|
|
],
|
|
protocol="iSCSI",
|
|
authentication={"Username": "userA", "Password": "passB"},
|
|
)
|
|
self.endpoint_col._conn.post.assert_called_once_with(
|
|
"/redfish/v1/Fabrics/NVMeoE/Endpoints", data=reqs
|
|
)
|
|
self.assertEqual(result, "/redfish/v1/Fabrics/NVMeoE/Endpoints/3")
|
|
|
|
def test_create_endpoint_with_invalid_reqs(self):
|
|
identifiers = [
|
|
{
|
|
"DurableNameFormat": "iQN",
|
|
"DurableName": "iqn.1986-03.com.intel:my_storage-uuid:"
|
|
"397f9b78-7e94-11e7-9ea4-001e67dfa170",
|
|
}
|
|
]
|
|
connected_entities = [
|
|
{
|
|
"EntityLink": {
|
|
"@odata.id": "/redfish/v1/StorageServices/1/Volumes/1"
|
|
},
|
|
"EntityRole": "Target",
|
|
"Identifiers": [
|
|
{"DurableNameFormat": "LUN", "DurableName": "1"}
|
|
],
|
|
}
|
|
]
|
|
|
|
result = self.endpoint_col.create_endpoint(
|
|
identifiers=identifiers, connected_entities=connected_entities
|
|
)
|
|
self.assertEqual(result, "/redfish/v1/Fabrics/NVMeoE/Endpoints/3")
|
|
|
|
# Test invalid identifiers argument
|
|
invalid_identifiers = copy.deepcopy(identifiers)
|
|
invalid_identifiers[0]["DurableNameFormat"] = "fake-format"
|
|
self.assertRaises(
|
|
jsonschema.exceptions.ValidationError,
|
|
self.endpoint_col.create_endpoint,
|
|
identifiers=invalid_identifiers,
|
|
connected_entities=connected_entities,
|
|
)
|
|
|
|
invalid_identifiers = copy.deepcopy(identifiers)
|
|
invalid_identifiers[0].pop("DurableNameFormat")
|
|
self.assertRaises(
|
|
jsonschema.exceptions.ValidationError,
|
|
self.endpoint_col.create_endpoint,
|
|
identifiers=invalid_identifiers,
|
|
connected_entities=connected_entities,
|
|
)
|
|
|
|
invalid_identifiers = copy.deepcopy(identifiers)
|
|
invalid_identifiers[0].pop("DurableName")
|
|
self.assertRaises(
|
|
jsonschema.exceptions.ValidationError,
|
|
self.endpoint_col.create_endpoint,
|
|
identifiers=invalid_identifiers,
|
|
connected_entities=connected_entities,
|
|
)
|
|
|
|
# Test invalid connected_entities argument
|
|
invalid_connected_entities = copy.deepcopy(connected_entities)
|
|
invalid_connected_entities[0]["EntityRole"] = "fake-format"
|
|
self.assertRaises(
|
|
jsonschema.exceptions.ValidationError,
|
|
self.endpoint_col.create_endpoint,
|
|
identifiers=identifiers,
|
|
connected_entities=invalid_connected_entities,
|
|
)
|
|
|
|
invalid_connected_entities = copy.deepcopy(connected_entities)
|
|
invalid_connected_entities[0]["EntityLink"].pop("@odata.id")
|
|
self.assertRaises(
|
|
jsonschema.exceptions.ValidationError,
|
|
self.endpoint_col.create_endpoint,
|
|
identifiers=identifiers,
|
|
connected_entities=invalid_connected_entities,
|
|
)
|
|
|
|
invalid_connected_entities = copy.deepcopy(connected_entities)
|
|
invalid_connected_entities[0].pop("EntityLink")
|
|
self.assertRaises(
|
|
jsonschema.exceptions.ValidationError,
|
|
self.endpoint_col.create_endpoint,
|
|
identifiers=identifiers,
|
|
connected_entities=invalid_connected_entities,
|
|
)
|
|
|
|
invalid_connected_entities = copy.deepcopy(connected_entities)
|
|
invalid_connected_entities[0].pop("EntityRole")
|
|
self.assertRaises(
|
|
jsonschema.exceptions.ValidationError,
|
|
self.endpoint_col.create_endpoint,
|
|
identifiers=identifiers,
|
|
connected_entities=invalid_connected_entities,
|
|
)
|
|
|
|
# Test invalid protocol argument
|
|
self.assertRaises(
|
|
jsonschema.exceptions.ValidationError,
|
|
self.endpoint_col.create_endpoint,
|
|
identifiers=identifiers,
|
|
connected_entities=connected_entities,
|
|
protocol=1,
|
|
)
|
|
|
|
# Test invalid interface argument
|
|
self.assertRaises(
|
|
jsonschema.exceptions.ValidationError,
|
|
self.endpoint_col.create_endpoint,
|
|
identifiers=identifiers,
|
|
connected_entities=connected_entities,
|
|
interface=1,
|
|
)
|
|
|
|
# Test invalid authentication argument
|
|
self.assertRaises(
|
|
jsonschema.exceptions.ValidationError,
|
|
self.endpoint_col.create_endpoint,
|
|
identifiers=identifiers,
|
|
connected_entities=connected_entities,
|
|
authentication={"Username": 1},
|
|
)
|