Merge "Add manager resource"

This commit is contained in:
Jenkins 2017-06-28 17:26:13 +00:00 committed by Gerrit Code Review
commit ad0d018fbd
15 changed files with 824 additions and 46 deletions

View File

@ -9,7 +9,7 @@ Welcome to Sushy's documentation!
Contents:
.. toctree::
:maxdepth: 1
:maxdepth: 2
About Sushy <readme>
installation

View File

@ -6,6 +6,10 @@ Usage
To use sushy in a project:
----------------------------------------
Creating and using a sushy system object
----------------------------------------
.. code-block:: python
import logging
@ -17,7 +21,8 @@ To use sushy in a project:
LOG.setLevel(logging.DEBUG)
LOG.addHandler(logging.StreamHandler())
s = sushy.Sushy('http://localhost:8000', username='foo', password='bar')
s = sushy.Sushy('http://localhost:8000/redfish/v1',
username='foo', password='bar')
# Get the Redfish version
print(s.redfish_version)
@ -79,6 +84,74 @@ To use sushy in a project:
print(sys_inst.processors.summary)
-----------------------------------------
Creating and using a sushy manager object
-----------------------------------------
.. code-block:: python
import logging
import sushy
# Enable logging at DEBUG level
LOG = logging.getLogger('sushy')
LOG.setLevel(logging.DEBUG)
LOG.addHandler(logging.StreamHandler())
s = sushy.Sushy('http://localhost:8000/redfish/v1',
username='foo', password='bar')
# Instantiate a manager object
mgr_inst = s.get_manager('BMC')
# Get the manager name & description
print(mgr_inst.name)
print(mgr_inst.description)
# Using manager collections
# Instantiate a ManagerCollection object
mgr_col = s.get_manager_collection()
# Print the ID of the managers available in the collection
print(mgr_col.members_identities)
# Get a list of manager objects available in the collection
mgr_insts = mgr_col.get_members()
# Instantiate a manager object, same as getting it directly
# from the s.get_manager()
mgr_inst = mgr_col.get_member(mgr_col.members_identities[0])
# Refresh the manager collection object
mgr_col.refresh()
# Using manager actions
# Get supported graphical console types
print(mgr_inst.get_supported_graphical_console_types())
# Get supported serial console types
print(mgr_inst.get_supported_serial_console_types())
# Get supported command shell types
print(mgr_inst.get_supported_command_shell_types())
# Get a list of allowed manager reset values
print(mgr_inst.get_allowed_reset_manager_values())
# Reset the manager
mgr_inst.reset_manager(sushy.RESET_MANAGER_FORCE_RESTART)
# Refresh the manager object
mgr_inst.refresh()
If you do not have any real baremetal machine that supports the Redfish
protocol you can look at the :ref:`contributing` page to learn how to
run a Redfish emulator.

View File

@ -18,6 +18,7 @@ import pbr.version
from sushy.main import Sushy
from sushy.resources.system.constants import * # noqa
from sushy.resources.manager.constants import * # noqa
__all__ = ('Sushy',)
__version__ = pbr.version.VersionInfo(

View File

@ -14,21 +14,27 @@
# under the License.
from sushy import connector
from sushy import exceptions
from sushy.resources import base
from sushy.resources.manager import manager
from sushy.resources.system import system
class Sushy(base.ResourceBase):
identity = None
"""The Redfish system identity"""
identity = base.Field('Id', required=True)
"""The Redfish root service identity"""
name = None
"""The Redfish system name"""
name = base.Field('Name')
"""The Redfish root service name"""
uuid = None
"""The Redfish system UUID"""
uuid = base.Field('UUID')
"""The Redfish root service UUID"""
_systems_path = base.Field(['Systems', '@odata.id'], required=True)
"""SystemCollection path"""
_managers_path = base.Field(['Managers', '@odata.id'], required=True)
"""ManagerCollection path"""
def __init__(self, base_url, username=None, password=None,
root_prefix='/redfish/v1/', verify=True):
@ -55,18 +61,8 @@ class Sushy(base.ResourceBase):
path=self._root_prefix)
def _parse_attributes(self):
self.identity = self.json.get('Id')
self.name = self.json.get('Name')
super(Sushy, self)._parse_attributes()
self.redfish_version = self.json.get('RedfishVersion')
self.uuid = self.json.get('UUID')
def _get_system_collection_path(self):
"""Helper function to find the SystemCollection path"""
systems_col = self.json.get('Systems')
if not systems_col:
raise exceptions.MissingAttributeError(attribute='Systems',
resource=self._path)
return systems_col.get('@odata.id')
def get_system_collection(self):
"""Get the SystemCollection object
@ -75,9 +71,8 @@ class Sushy(base.ResourceBase):
not found
:returns: a SystemCollection object
"""
return system.SystemCollection(
self._conn, self._get_system_collection_path(),
redfish_version=self.redfish_version)
return system.SystemCollection(self._conn, self._systems_path,
redfish_version=self.redfish_version)
def get_system(self, identity):
"""Given the identity return a System object
@ -87,3 +82,22 @@ class Sushy(base.ResourceBase):
"""
return system.System(self._conn, identity,
redfish_version=self.redfish_version)
def get_manager_collection(self):
"""Get the ManagerCollection object
:raises: MissingAttributeError, if the collection attribute is
not found
:returns: a ManagerCollection object
"""
return manager.ManagerCollection(self._conn, self._managers_path,
redfish_version=self.redfish_version)
def get_manager(self, identity):
"""Given the identity return a Manager object
:param identity: The identity of the Manager resource
:returns: The Manager object
"""
return manager.Manager(self._conn, identity,
redfish_version=self.redfish_version)

20
sushy/resources/common.py Normal file
View File

@ -0,0 +1,20 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from sushy.resources import base
class ResetActionField(base.CompositeField):
allowed_values = base.Field('ResetType@Redfish.AllowableValues',
adapter=list)
target_uri = base.Field('target', required=True)

View File

View File

@ -0,0 +1,78 @@
# 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.
# Values comes from the Redfish System json-schema 1.0.0:
# http://redfish.dmtf.org/schemas/v1/Manager.v1_0_0.json#/definitions/Manager # noqa
# Manager Reset action constants
RESET_MANAGER_GRACEFUL_RESTART = 'graceful restart'
RESET_MANAGER_FORCE_RESTART = 'force restart'
# Manager Type constants
MANAGER_TYPE_MANAGEMENT_CONTROLLER = 'management controller'
"""A controller used primarily to monitor or manage the operation of
a device or system"""
MANAGER_TYPE_ENCLOSURE_MANAGER = 'enclosure manager'
"""A controller which provides management functions for a chassis
or group of devices or systems"""
MANAGER_TYPE_BMC = 'bmc'
"""A controller which provides management functions for a single
computer system"""
MANAGER_TYPE_RACK_MANAGER = 'rack manager'
"""A controller which provides management functions for a whole or part
of a rack"""
MANAGER_TYPE_AUXILIARY_CONTROLLER = 'auxiliary controller'
"""A controller which provides management functions for a particular
subsystem or group of devices"""
# Graphical Console constants
GRAPHICAL_CONSOLE_KVMIP = 'graphical console kvmip'
"""Graphical Console connection using a KVM-IP (redirection of Keyboard,
Video, Mouse over IP) protocol"""
GRAPHICAL_CONSOLE_OEM = 'graphical console oem'
"""Graphical Console connection using an OEM-specific protocol"""
# Serial Console constants
SERIAL_CONSOLE_SSH = 'serial console ssh'
"""Serial Console connection using the SSH protocol"""
SERIAL_CONSOLE_TELNET = 'serial console telnet'
"""Serial Console connection using the Telnet protocol"""
SERIAL_CONSOLE_IPMI = 'serial console ipmi'
"""Serial Console connection using the IPMI Serial-over-LAN (SOL) protocol"""
SERIAL_CONSOLE_OEM = 'serial console oem'
"""Serial Console connection using an OEM-specific protocol"""
# Command Shell constants
COMMAND_SHELL_SSH = 'command shell ssh'
"""Command Shell connection using the SSH protocol"""
COMMAND_SHELL_TELNET = 'command shell telnet'
"""Command Shell connection using the Telnet protocol"""
COMMAND_SHELL_IPMI = 'command shell ipmi'
"""Command Shell connection using the IPMI Serial-over-LAN (SOL) protocol"""
COMMAND_SHELL_OEM = 'command shell oem'
"""Command Shell connection using an OEM-specific protocol"""

View File

@ -0,0 +1,197 @@
# 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 logging
from sushy import exceptions
from sushy.resources import base
from sushy.resources import common
from sushy.resources.manager import mappings as mgr_maps
LOG = logging.getLogger(__name__)
class ActionsField(base.CompositeField):
reset = common.ResetActionField('#Manager.Reset')
class RemoteAccessField(base.CompositeField):
service_enabled = base.Field('ServiceEnabled')
max_concurrent_sessions = base.Field('MaxConcurrentSessions')
connect_types_supported = base.Field('ConnectTypesSupported',
adapter=list)
class Manager(base.ResourceBase):
firmware_version = base.Field('FirmwareVersion')
"""The manager firmware version"""
graphical_console = RemoteAccessField('GraphicalConsole')
"""A dictionary containing the remote access support service via
graphical console (e.g. KVMIP) and max concurrent sessions
"""
serial_console = RemoteAccessField('SerialConsole')
"""A dictionary containing the remote access support service via
serial console (e.g. Telnet, SSH, IPMI) and max concurrent sessions
"""
command_shell = RemoteAccessField('CommandShell')
"""A dictionary containing the remote access support service via
command shell (e.g. Telnet, SSH) and max concurrent sessions
"""
description = base.Field('Description')
"""The manager description"""
identity = base.Field('Id', required=True)
"""The manager identity string"""
name = base.Field('Name')
"""The manager name"""
model = base.Field('Model')
"""The manager model"""
manager_type = base.MappedField('ManagerType',
mgr_maps.MANAGER_TYPE_VALUE_MAP)
"""The manager type"""
uuid = base.Field('UUID')
"""The manager UUID"""
_actions = ActionsField('Actions', required=True)
def __init__(self, connector, identity, redfish_version=None):
"""A class representing a Manager
:param connector: A Connector instance
:param identity: The identity of the Manager resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(Manager, self).__init__(connector, identity, redfish_version)
def get_supported_graphical_console_types(self):
"""Get the supported values for Graphical Console connection types.
:returns: A set of supported values.
"""
if (not self.graphical_console
or not self.graphical_console.connect_types_supported):
LOG.warning('Could not figure out the supported values for '
'remote access via graphical console for Manager %s',
self.identity)
return set(mgr_maps.GRAPHICAL_CONSOLE_VALUE_MAP_REV)
return set([mgr_maps.GRAPHICAL_CONSOLE_VALUE_MAP[v] for v in
set(mgr_maps.GRAPHICAL_CONSOLE_VALUE_MAP).
intersection(self.graphical_console.
connect_types_supported)])
def get_supported_serial_console_types(self):
"""Get the supported values for Serial Console connection types.
:returns: A set of supported values.
"""
if (not self.serial_console
or not self.serial_console.connect_types_supported):
LOG.warning('Could not figure out the supported values for '
'remote access via serial console for Manager %s',
self.identity)
return set(mgr_maps.SERIAL_CONSOLE_VALUE_MAP_REV)
return set([mgr_maps.SERIAL_CONSOLE_VALUE_MAP[v] for v in
set(mgr_maps.SERIAL_CONSOLE_VALUE_MAP).
intersection(self.serial_console.connect_types_supported)])
def get_supported_command_shell_types(self):
"""Get the supported values for Command Shell connection types.
:returns: A set of supported values.
"""
if (not self.command_shell
or not self.command_shell.connect_types_supported):
LOG.warning('Could not figure out the supported values for '
'remote access via command shell for Manager %s',
self.identity)
return set(mgr_maps.COMMAND_SHELL_VALUE_MAP_REV)
return set([mgr_maps.COMMAND_SHELL_VALUE_MAP[v] for v in
set(mgr_maps.COMMAND_SHELL_VALUE_MAP).
intersection(self.command_shell.connect_types_supported)])
def _get_reset_action_element(self):
reset_action = self._actions.reset
if not reset_action:
raise exceptions.MissingActionError(action='#Manager.Reset',
resource=self._path)
return reset_action
def get_allowed_reset_manager_values(self):
"""Get the allowed values for resetting the manager.
:returns: A set of allowed values.
:raises: MissingAttributeError, if Actions/#Manager.Reset attribute
not present.
"""
reset_action = self._get_reset_action_element()
if not reset_action.allowed_values:
LOG.warning('Could not figure out the allowed values for the '
'reset manager action for Manager %s', self.identity)
return set(mgr_maps.RESET_MANAGER_VALUE_MAP_REV)
return set([mgr_maps.RESET_MANAGER_VALUE_MAP[v] for v in
set(mgr_maps.RESET_MANAGER_VALUE_MAP).
intersection(reset_action.allowed_values)])
def reset_manager(self, value):
"""Reset the manager.
:param value: The target value.
:raises: InvalidParameterValueError, if the target value is not
allowed.
"""
valid_resets = self.get_allowed_reset_manager_values()
if value not in valid_resets:
raise exceptions.InvalidParameterValueError(
parameter='value', value=value, valid_values=valid_resets)
value = mgr_maps.RESET_MANAGER_VALUE_MAP_REV[value]
target_uri = self._get_reset_action_element().target_uri
LOG.debug('Resetting the Manager %s ...', self.identity)
self._conn.post(target_uri, data={'ResetType': value})
LOG.info('The Manager %s is being reset', self.identity)
class ManagerCollection(base.ResourceCollectionBase):
@property
def _resource_type(self):
return Manager
def __init__(self, connector, path, redfish_version=None):
"""A class representing a ManagerCollection
:param connector: A Connector instance
:param path: The canonical path to the Manager collection resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(ManagerCollection, self).__init__(connector, path,
redfish_version)

View File

@ -0,0 +1,61 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from sushy.resources.manager import constants as mgr_cons
from sushy import utils
RESET_MANAGER_VALUE_MAP = {
'GracefulRestart': mgr_cons.RESET_MANAGER_GRACEFUL_RESTART,
'ForceRestart': mgr_cons.RESET_MANAGER_FORCE_RESTART,
}
RESET_MANAGER_VALUE_MAP_REV = utils.revert_dictionary(RESET_MANAGER_VALUE_MAP)
MANAGER_TYPE_VALUE_MAP = {
'ManagementController': mgr_cons.MANAGER_TYPE_MANAGEMENT_CONTROLLER,
'EnclosureManager': mgr_cons.MANAGER_TYPE_ENCLOSURE_MANAGER,
'BMC': mgr_cons.MANAGER_TYPE_BMC,
'RackManager': mgr_cons.MANAGER_TYPE_RACK_MANAGER,
'AuxiliaryController': mgr_cons.MANAGER_TYPE_AUXILIARY_CONTROLLER
}
MANAGER_TYPE_VALUE_MAP_REV = (
utils.revert_dictionary(MANAGER_TYPE_VALUE_MAP))
GRAPHICAL_CONSOLE_VALUE_MAP = {
'KVMIP': mgr_cons.GRAPHICAL_CONSOLE_KVMIP,
'Oem': mgr_cons.GRAPHICAL_CONSOLE_OEM,
}
GRAPHICAL_CONSOLE_VALUE_MAP_REV = (
utils.revert_dictionary(GRAPHICAL_CONSOLE_VALUE_MAP))
SERIAL_CONSOLE_VALUE_MAP = {
'SSH': mgr_cons.SERIAL_CONSOLE_SSH,
'Telnet': mgr_cons.SERIAL_CONSOLE_TELNET,
'IPMI': mgr_cons.SERIAL_CONSOLE_IPMI,
'Oem': mgr_cons.SERIAL_CONSOLE_OEM,
}
SERIAL_CONSOLE_VALUE_MAP_REV = (
utils.revert_dictionary(SERIAL_CONSOLE_VALUE_MAP))
COMMAND_SHELL_VALUE_MAP = {
'SSH': mgr_cons.COMMAND_SHELL_SSH,
'Telnet': mgr_cons.COMMAND_SHELL_TELNET,
'IPMI': mgr_cons.COMMAND_SHELL_IPMI,
'Oem': mgr_cons.COMMAND_SHELL_OEM,
}
COMMAND_SHELL_VALUE_MAP_REV = (
utils.revert_dictionary(COMMAND_SHELL_VALUE_MAP))

View File

@ -17,6 +17,7 @@ import logging
from sushy import exceptions
from sushy.resources import base
from sushy.resources import common
from sushy.resources.system import constants as sys_cons
from sushy.resources.system import mappings as sys_maps
from sushy.resources.system import processor
@ -25,15 +26,8 @@ from sushy.resources.system import processor
LOG = logging.getLogger(__name__)
class ResetActionField(base.CompositeField):
allowed_values = base.Field('ResetType@Redfish.AllowableValues',
adapter=list)
target_uri = base.Field('target', required=True)
class ActionsField(base.CompositeField):
reset = ResetActionField('#ComputerSystem.Reset')
reset = common.ResetActionField('#ComputerSystem.Reset')
class BootField(base.CompositeField):

View File

@ -0,0 +1,86 @@
{
"@odata.type": "#Manager.v1_1_0.Manager",
"Id": "BMC",
"Name": "Manager",
"ManagerType": "BMC",
"Description": "Contoso BMC",
"ServiceEntryPointUUID": "92384634-2938-2342-8820-489239905423",
"UUID": "58893887-8974-2487-2389-841168418919",
"Model": "Joo Janta 200",
"DateTime": "2015-03-13T04:14:33+06:00",
"DateTimeLocalOffset": "+06:00",
"Status": {
"State": "Enabled",
"Health": "OK"
},
"GraphicalConsole": {
"ServiceEnabled": true,
"MaxConcurrentSessions": 2,
"ConnectTypesSupported": [
"KVMIP"
]
},
"SerialConsole": {
"ServiceEnabled": true,
"MaxConcurrentSessions": 1,
"ConnectTypesSupported": [
"Telnet",
"SSH",
"IPMI"
]
},
"CommandShell": {
"ServiceEnabled": true,
"MaxConcurrentSessions": 4,
"ConnectTypesSupported": [
"Telnet",
"SSH"
]
},
"FirmwareVersion": "1.00",
"NetworkProtocol": {
"@odata.id": "/redfish/v1/Managers/BMC/NetworkProtocol"
},
"EthernetInterfaces": {
"@odata.id": "/redfish/v1/Managers/BMC/NICs"
},
"SerialInterfaces": {
"@odata.id": "/redfish/v1/Managers/BMC/SerialInterfaces"
},
"LogServices": {
"@odata.id": "/redfish/v1/Managers/BMC/LogServices"
},
"VirtualMedia": {
"@odata.id": "/redfish/v1/Managers/BMC/VirtualMedia"
},
"Links": {
"ManagerForServers": [
{
"@odata.id": "/redfish/v1/Systems/437XR1138R2"
}
],
"ManagerForChassis": [
{
"@odata.id": "/redfish/v1/Chassis/1U"
}
],
"ManagerInChassis": {
"@odata.id": "/redfish/v1/Chassis/1U"
},
"Oem": {}
},
"Actions": {
"#Manager.Reset": {
"target": "/redfish/v1/Managers/BMC/Actions/Manager.Reset",
"ResetType@Redfish.AllowableValues": [
"ForceRestart",
"GracefulRestart"
]
},
"Oem": {}
},
"Oem": {},
"@odata.context": "/redfish/v1/$metadata#Manager.Manager",
"@odata.id": "/redfish/v1/Managers/BMC",
"@Redfish.Copyright": "Copyright 2014-2016 Distributed Management Task Force, Inc. (DMTF). For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright."
}

View File

@ -0,0 +1,14 @@
{
"@odata.type": "#ManagerCollection.ManagerCollection",
"Name": "Manager Collection",
"Members@odata.count": 1,
"Members": [
{
"@odata.id": "/redfish/v1/Managers/BMC"
}
],
"Oem": {},
"@odata.context": "/redfish/v1/$metadata#Managers",
"@odata.id": "/redfish/v1/Managers",
"@Redfish.Copyright": "Copyright 2014-2016 Distributed Management Task Force, Inc. (DMTF). For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright."
}

View File

@ -0,0 +1,235 @@
# 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 json
import mock
import sushy
from sushy import exceptions
from sushy.resources.manager import manager
from sushy.tests.unit import base
class ManagerTestCase(base.TestCase):
def setUp(self):
super(ManagerTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/manager.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.manager = manager.Manager(self.conn, '/redfish/v1/Managers/BMC',
redfish_version='1.0.2')
def test__parse_attributes(self):
# | WHEN |
self.manager._parse_attributes()
# | THEN |
self.assertEqual('1.0.2', self.manager.redfish_version)
self.assertEqual('1.00', self.manager.firmware_version)
self.assertEqual(True, self.manager.graphical_console.service_enabled)
self.assertEqual(
2, self.manager.graphical_console.max_concurrent_sessions)
self.assertEqual(True, self.manager.serial_console.service_enabled)
self.assertEqual(
1, self.manager.serial_console.max_concurrent_sessions)
self.assertEqual(True, self.manager.command_shell.service_enabled)
self.assertEqual(
4, self.manager.command_shell.max_concurrent_sessions)
self.assertEqual('Contoso BMC', self.manager.description)
self.assertEqual('BMC', self.manager.identity)
self.assertEqual('Manager', self.manager.name)
self.assertEqual('Joo Janta 200', self.manager.model)
self.assertEqual(sushy.MANAGER_TYPE_BMC, self.manager.manager_type)
self.assertEqual('58893887-8974-2487-2389-841168418919',
self.manager.uuid)
def test_get_supported_graphical_console_types(self):
# | GIVEN |
expected = set([sushy.GRAPHICAL_CONSOLE_KVMIP])
# | WHEN |
values = self.manager.get_supported_graphical_console_types()
# | THEN |
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
def test_get_supported_graphical_console_types_for_no_connect_types(self):
# | GIVEN |
graphical_console = self.manager.graphical_console
expected = set([sushy.GRAPHICAL_CONSOLE_KVMIP,
sushy.GRAPHICAL_CONSOLE_OEM])
for val in [None, []]:
graphical_console.connect_types_supported = val
# | WHEN |
values = self.manager.get_supported_graphical_console_types()
# | THEN |
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
def test_get_supported_graphical_console_types_missing_graphcon_attr(self):
# | GIVEN |
self.manager.graphical_console = None
expected = set([sushy.GRAPHICAL_CONSOLE_KVMIP,
sushy.GRAPHICAL_CONSOLE_OEM])
# | WHEN |
values = self.manager.get_supported_graphical_console_types()
# | THEN |
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
def test_get_supported_serial_console_types(self):
# | GIVEN |
expected = set([sushy.SERIAL_CONSOLE_SSH,
sushy.SERIAL_CONSOLE_TELNET,
sushy.SERIAL_CONSOLE_IPMI])
# | WHEN |
values = self.manager.get_supported_serial_console_types()
# | THEN |
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
def test_get_supported_serial_console_types_for_no_connect_types(self):
# | GIVEN |
serial_console = self.manager.serial_console
expected = set([sushy.SERIAL_CONSOLE_SSH,
sushy.SERIAL_CONSOLE_TELNET,
sushy.SERIAL_CONSOLE_IPMI,
sushy.SERIAL_CONSOLE_OEM])
for val in [None, []]:
serial_console.connect_types_supported = val
# | WHEN |
values = self.manager.get_supported_serial_console_types()
# | THEN |
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
def test_get_supported_serial_console_types_missing_serialcon_attr(self):
# | GIVEN |
self.manager.serial_console = None
expected = set([sushy.SERIAL_CONSOLE_SSH,
sushy.SERIAL_CONSOLE_TELNET,
sushy.SERIAL_CONSOLE_IPMI,
sushy.SERIAL_CONSOLE_OEM])
# | WHEN |
values = self.manager.get_supported_serial_console_types()
# | THEN |
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
def test_get_supported_command_shell_types(self):
# | GIVEN |
expected = set([sushy.COMMAND_SHELL_SSH,
sushy.COMMAND_SHELL_TELNET])
# | WHEN |
values = self.manager.get_supported_command_shell_types()
# | THEN |
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
def test_get_supported_command_shell_types_for_no_connect_types(self):
# | GIVEN |
command_shell = self.manager.command_shell
expected = set([sushy.COMMAND_SHELL_SSH,
sushy.COMMAND_SHELL_TELNET,
sushy.COMMAND_SHELL_IPMI,
sushy.COMMAND_SHELL_OEM])
for val in [None, []]:
command_shell.connect_types_supported = val
# | WHEN |
values = self.manager.get_supported_command_shell_types()
# | THEN |
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
def test_get_supported_command_shell_types_missing_cmdshell_attr(self):
# | GIVEN |
self.manager.command_shell = None
expected = set([sushy.COMMAND_SHELL_SSH,
sushy.COMMAND_SHELL_TELNET,
sushy.COMMAND_SHELL_IPMI,
sushy.COMMAND_SHELL_OEM])
# | WHEN |
values = self.manager.get_supported_command_shell_types()
# | THEN |
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
def test_get_allowed_reset_manager_values(self):
# | GIVEN |
expected = set([sushy.RESET_MANAGER_GRACEFUL_RESTART,
sushy.RESET_MANAGER_FORCE_RESTART])
# | WHEN |
values = self.manager.get_allowed_reset_manager_values()
# | THEN |
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
def test_get_allowed_reset_manager_values_for_no_values_set(self):
# | GIVEN |
self.manager._actions.reset.allowed_values = []
expected = set([sushy.RESET_MANAGER_GRACEFUL_RESTART,
sushy.RESET_MANAGER_FORCE_RESTART])
# | WHEN |
values = self.manager.get_allowed_reset_manager_values()
# | THEN |
self.assertEqual(expected, values)
self.assertIsInstance(values, set)
def test_get_allowed_reset_manager_values_missing_action_reset_attr(self):
# | GIVEN |
self.manager._actions.reset = None
# | WHEN & THEN |
self.assertRaisesRegex(
exceptions.MissingActionError, 'action #Manager.Reset',
self.manager.get_allowed_reset_manager_values)
def test_reset_manager(self):
self.manager.reset_manager(sushy.RESET_MANAGER_GRACEFUL_RESTART)
self.manager._conn.post.assert_called_once_with(
'/redfish/v1/Managers/BMC/Actions/Manager.Reset',
data={'ResetType': 'GracefulRestart'})
def test_reset_manager_with_invalid_value(self):
self.assertRaises(exceptions.InvalidParameterValueError,
self.manager.reset_manager, 'invalid-value')
class ManagerCollectionTestCase(base.TestCase):
def setUp(self):
super(ManagerCollectionTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'manager_collection.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.managers = manager.ManagerCollection(
self.conn, '/redfish/v1/Managers', redfish_version='1.0.2')
@mock.patch.object(manager, 'Manager', autospec=True)
def test_get_member(self, Manager_mock):
self.managers.get_member('/redfish/v1/Managers/BMC')
Manager_mock.assert_called_once_with(
self.managers._conn, '/redfish/v1/Managers/BMC',
redfish_version=self.managers.redfish_version)
@mock.patch.object(manager, 'Manager', autospec=True)
def test_get_members(self, Manager_mock):
members = self.managers.get_members()
Manager_mock.assert_called_once_with(
self.managers._conn, '/redfish/v1/Managers/BMC',
redfish_version=self.managers.redfish_version)
self.assertIsInstance(members, list)
self.assertEqual(1, len(members))

View File

@ -18,8 +18,8 @@ import json
import mock
from sushy import connector
from sushy import exceptions
from sushy import main
from sushy.resources.manager import manager
from sushy.resources.system import system
from sushy.tests.unit import base
@ -30,12 +30,12 @@ class MainTestCase(base.TestCase):
def setUp(self, mock_connector):
super(MainTestCase, self).setUp()
self.conn = mock.Mock()
mock_connector.return_code = self.conn
mock_connector.return_value = self.conn
with open('sushy/tests/unit/json_samples/root.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.root = main.Sushy(
'http://foo.bar:1234', username='foo', password='bar',
verify=True)
with open('sushy/tests/unit/json_samples/root.json', 'r') as f:
self.root._json = json.loads(f.read())
mock_connector.assert_called_once_with(
'http://foo.bar:1234', 'foo', 'bar', True)
@ -46,17 +46,8 @@ class MainTestCase(base.TestCase):
self.assertEqual('1.0.2', self.root.redfish_version)
self.assertEqual('92384634-2938-2342-8820-489239905423',
self.root.uuid)
def test__get_system_collection_path(self):
self.assertEqual(
'/redfish/v1/Systems', self.root._get_system_collection_path())
def test__get_system_collection_path_missing_systems_attr(self):
self.root._json.pop('Systems')
self.assertRaisesRegex(
exceptions.MissingAttributeError,
'The attribute Systems is missing',
self.root._get_system_collection_path)
self.assertEqual('/redfish/v1/Systems', self.root._systems_path)
self.assertEqual('/redfish/v1/Managers', self.root._managers_path)
@mock.patch.object(system, 'SystemCollection', autospec=True)
def test_get_system_collection(self, mock_system_collection):
@ -71,3 +62,17 @@ class MainTestCase(base.TestCase):
mock_system.assert_called_once_with(
self.root._conn, 'fake-system-id',
redfish_version=self.root.redfish_version)
@mock.patch.object(manager, 'ManagerCollection', autospec=True)
def test_get_manager_collection(self, ManagerCollection_mock):
self.root.get_manager_collection()
ManagerCollection_mock.assert_called_once_with(
self.root._conn, '/redfish/v1/Managers',
redfish_version=self.root.redfish_version)
@mock.patch.object(manager, 'Manager', autospec=True)
def test_get_manager(self, Manager_mock):
self.root.get_manager('fake-manager-id')
Manager_mock.assert_called_once_with(
self.root._conn, 'fake-manager-id',
redfish_version=self.root.redfish_version)