Add resources to put iDRAC in known good state

This change adds the iDRACCardService, JobCollection, JobService, and
LCService resources. Those offer actions to reset the iDRAC, get jobs,
delete jobs, and check if iDRAC is ready.

Change-Id: I29ce49c0865a610f2fb10f5072893bbf51b47303
Story: 2007617
Task: 40985
This commit is contained in:
DhuldevValekar3 2020-04-21 07:27:56 -05:00 committed by Richard G. Pioso
parent bec107ce58
commit 910d573c30
16 changed files with 701 additions and 0 deletions

View File

@ -28,3 +28,12 @@ EXPORT_NIC_CONFIG = 'NIC'
EXPORT_RAID_CONFIG = 'RAID' EXPORT_RAID_CONFIG = 'RAID'
"""Export RAID related configuration""" """Export RAID related configuration"""
# iDRAC Reset action constants
RESET_IDRAC_GRACEFUL_RESTART = 'graceful restart'
"""Perform a graceful shutdown followed by a restart of the system"""
RESET_IDRAC_FORCE_RESTART = 'force restart'
"""Perform an immediate (non-graceful) shutdown, followed by a restart"""

View File

@ -0,0 +1,85 @@
# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries.
#
# 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_oem_idrac.resources.manager import constants as mgr_cons
from sushy_oem_idrac.resources.manager import mappings as mgr_maps
LOG = logging.getLogger(__name__)
class ForceActionField(base.CompositeField):
target_uri = base.Field('target', required=True)
allowed_values = base.Field('Force@Redfish.AllowableValues',
adapter=list)
class ActionsField(base.CompositeField):
reset_idrac = ForceActionField('#DelliDRACCardService.iDRACReset')
class DelliDRACCardService(base.ResourceBase):
_actions = ActionsField('Actions')
identity = base.Field('Id', required=True)
def __init__(self, connector, identity, redfish_version=None,
registries=None):
"""A class representing a DelliDRACCardService.
:param connector: A Connector instance
:param identity: The identity of the DelliDRACCardService resource
:param redfish_version: The version of Redfish. Used to construct
the object according to schema of the given version.
:param registries: Dict of Redfish Message Registry objects to be
used in any resource that needs registries to parse messages.
"""
super(DelliDRACCardService, self).__init__(
connector, identity, redfish_version, registries)
def get_allowed_reset_idrac_values(self):
"""Get the allowed values for resetting the idrac.
:returns: A set of allowed values.
"""
reset_action = self._actions.reset_idrac
if not reset_action.allowed_values:
LOG.warning('Could not figure out the allowed values for the '
'reset idrac action for %s', self.identity)
return set(mgr_maps.RESET_IDRAC_VALUE_MAP_REV)
return set([mgr_maps.RESET_IDRAC_VALUE_MAP[value] for value in
set(mgr_maps.RESET_IDRAC_VALUE_MAP).
intersection(reset_action.allowed_values)])
def reset_idrac(self):
"""Reset the iDRAC.
"""
reset_type = mgr_cons.RESET_IDRAC_GRACEFUL_RESTART
valid_resets = self.get_allowed_reset_idrac_values()
if reset_type not in valid_resets:
raise exceptions.InvalidParameterValueError(
parameter='value', value=reset_type, valid_values=valid_resets)
reset_type = mgr_maps.RESET_IDRAC_VALUE_MAP_REV[reset_type]
target_uri = self._actions.reset_idrac.target_uri
payload = {"Force": reset_type}
LOG.debug('Resetting the iDRAC %s ...', self.identity)
self._conn.post(target_uri, data=payload)
LOG.info('The iDRAC %s is being reset', self.identity)

View File

@ -0,0 +1,56 @@
# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries.
#
# 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.resources import base
LOG = logging.getLogger(__name__)
class DellJobCollection(base.ResourceBase):
identity = base.Field('Id', required=True)
_JOB_EXPAND = '?$expand=.($levels=1)'
def __init__(self, connector, identity, redfish_version=None,
registries=None):
"""A class representing a DellJobCollection.
:param connector: A Connector instance
:param identity: The identity of the DellJobCollection resource
:param redfish_version: The version of Redfish. Used to construct
the object according to schema of the given version.
:param registries: Dict of Redfish Message Registry objects to be
used in any resource that needs registries to parse messages
"""
super(DellJobCollection, self).__init__(
connector, identity, redfish_version, registries)
def get_unfinished_jobs(self):
"""Get the unfinished jobs.
:returns: A list of unfinished jobs.
"""
job_expand_uri = '%s%s' % (self._path, self._JOB_EXPAND)
unfinished_jobs = []
LOG.debug('Getting unfinished jobs...')
job_response = self._conn.get(job_expand_uri)
data = job_response.json()
for job in data[u'Members']:
if ((job[u'JobState'] == 'Scheduled') or (
job[u'JobState'] == 'Running')):
unfinished_jobs.append(job['Id'])
LOG.info('Got unfinished jobs')
return unfinished_jobs

View File

@ -0,0 +1,59 @@
# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries.
#
# 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.resources import base
from sushy.resources import common
LOG = logging.getLogger(__name__)
class ActionsField(base.CompositeField):
delete_job_queue = common.ActionField("#DellJobService.DeleteJobQueue")
class DellJobService(base.ResourceBase):
_actions = ActionsField('Actions')
identity = base.Field('Id', required=True)
def __init__(self, connector, identity, redfish_version=None,
registries=None):
"""A class representing a DellJobService.
:param connector: A Connector instance
:param identity: The identity of the DellJobService resource
:param redfish_version: The version of Redfish. Used to construct
the object according to schema of the given version.
:param registries: Dict of Redfish Message Registry objects to be
used in any resource that needs registries to parse messages.
"""
super(DellJobService, self).__init__(
connector, identity, redfish_version, registries)
def delete_jobs(self, job_ids=['JID_CLEARALL']):
"""Delete the given jobs, or all jobs.
:param job_ids: a list of job ids to delete. Clearing all the
jobs may be accomplished using the keyword JID_CLEARALL
as the job_id.
"""
target_uri = self._actions.delete_job_queue.target_uri
for job_id in job_ids:
LOG.debug('Deleting the job %s', job_id)
payload = {'JobID': job_id}
self._conn.post(target_uri,
data=payload)
LOG.info('Deleted the job %s', job_id)

View File

@ -0,0 +1,62 @@
# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries.
#
# 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.resources import base
from sushy.resources import common
LOG = logging.getLogger(__name__)
class ActionsField(base.CompositeField):
remote_service_api_status = common.ActionField(
"#DellLCService.GetRemoteServicesAPIStatus")
class DellLCService(base.ResourceBase):
_actions = ActionsField('Actions')
_IDRAC_READY_STATUS_CODE = 200
_IDRAC_READY_STATUS = 'Ready'
identity = base.Field('Id', required=True)
def __init__(self, connector, identity, redfish_version=None,
registries=None):
"""A class representing a DellLCService.
:param connector: A Connector instance
:param identity: The identity of the DellLCService resource
:param redfish_version: The version of Redfish. Used to construct
the object according to schema of the given version.
:param registries: Dict of Redfish Message Registry objects to be
used in any resource that needs registries to parse messages.
"""
super(DellLCService, self).__init__(
connector, identity, redfish_version, registries)
def is_idrac_ready(self):
"""Indicates if the iDRAC is ready to accept commands.
:returns: A boolean value True/False based on remote service api status
response.
"""
target_uri = self._actions.remote_service_api_status.target_uri
LOG.debug('Checking to see if the iDRAC is ready...')
idrac_ready_response = self._conn.post(target_uri, data={})
if idrac_ready_response.status_code != self._IDRAC_READY_STATUS_CODE:
return False
data = idrac_ready_response.json()
lc_status = data['LCStatus']
return lc_status == self._IDRAC_READY_STATUS

View File

@ -19,11 +19,16 @@ import sushy
from sushy.resources import base from sushy.resources import base
from sushy.resources import common from sushy.resources import common
from sushy.resources.oem import base as oem_base from sushy.resources.oem import base as oem_base
from sushy import utils as sushy_utils
from sushy_oem_idrac import asynchronous from sushy_oem_idrac import asynchronous
from sushy_oem_idrac import constants from sushy_oem_idrac import constants
from sushy_oem_idrac.resources import common as res_common from sushy_oem_idrac.resources import common as res_common
from sushy_oem_idrac.resources.manager import constants as mgr_cons from sushy_oem_idrac.resources.manager import constants as mgr_cons
from sushy_oem_idrac.resources.manager import idrac_card_service
from sushy_oem_idrac.resources.manager import job_collection
from sushy_oem_idrac.resources.manager import job_service
from sushy_oem_idrac.resources.manager import lifecycle_service
from sushy_oem_idrac.resources.manager import mappings as mgr_maps from sushy_oem_idrac.resources.manager import mappings as mgr_maps
from sushy_oem_idrac import utils from sushy_oem_idrac import utils
@ -102,6 +107,57 @@ VFDD\
def export_system_configuration_uri(self): def export_system_configuration_uri(self):
return self._actions.export_system_configuration.target_uri return self._actions.export_system_configuration.target_uri
@property
@sushy_utils.cache_it
def idrac_card_service(self):
"""Property to reference `DelliDRACCardService` instance of this manager.
"""
path = sushy_utils.get_sub_resource_path_by(
self, ["Links", "Oem", "Dell", "DelliDRACCardService"],
is_collection=False)
return idrac_card_service.DelliDRACCardService(
self._conn, path, self.redfish_version, self.registries)
@property
@sushy_utils.cache_it
def lifecycle_service(self):
"""Property to reference `DellLCService` instance of this manager.
"""
path = sushy_utils.get_sub_resource_path_by(
self, ["Links", "Oem", "Dell", "DellLCService"],
is_collection=False)
return lifecycle_service.DellLCService(
self._conn, path, self.redfish_version, self.registries)
@property
@sushy_utils.cache_it
def job_service(self):
"""Property to reference `DellJobService` instance of this manager.
"""
path = sushy_utils.get_sub_resource_path_by(
self, ["Links", "Oem", "Dell", "DellJobService"],
is_collection=False)
return job_service.DellJobService(
self._conn, path, self.redfish_version, self.registries)
@property
@sushy_utils.cache_it
def job_collection(self):
"""Property to reference `DellJobService` instance of this manager.
"""
path = sushy_utils.get_sub_resource_path_by(
self, ["Links", "Oem", "Dell", "Jobs"], is_collection=False)
return job_collection.DellJobCollection(
self._conn, path, self.redfish_version, self.registries)
def set_virtual_boot_device(self, device, persistent=False, def set_virtual_boot_device(self, device, persistent=False,
manager=None, system=None): manager=None, system=None):
"""Set boot device for a node. """Set boot device for a node.

View File

@ -25,3 +25,10 @@ EXPORT_CONFIG_VALUE_MAP = {
} }
EXPORT_CONFIG_VALUE_MAP_REV = utils.revert_dictionary(EXPORT_CONFIG_VALUE_MAP) EXPORT_CONFIG_VALUE_MAP_REV = utils.revert_dictionary(EXPORT_CONFIG_VALUE_MAP)
RESET_IDRAC_VALUE_MAP = {
'Graceful': mgr_cons.RESET_IDRAC_GRACEFUL_RESTART,
'Force': mgr_cons.RESET_IDRAC_FORCE_RESTART,
}
RESET_IDRAC_VALUE_MAP_REV = utils.revert_dictionary(RESET_IDRAC_VALUE_MAP)

View File

@ -0,0 +1,17 @@
{
"@odata.context": "/redfish/v1/$metadata#DelliDRACCard.DelliDRACCardService",
"@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DelliDRACCardService",
"@odata.type": "#DelliDRACCardService.v1_1_0.DelliDRACCardService",
"Actions": {
"#DelliDRACCardService.iDRACReset": {
"Force@Redfish.AllowableValues": [
"Graceful",
"Force"
],
"target": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DelliDRACCardService/Actions/DelliDRACCardService.iDRACReset"
}
},
"Description": "The DelliDRACCardService resource provides some actions to support iDRAC configurations.",
"Id": "DelliDRACCardService",
"Name": "DelliDRACCardService"
}

View File

@ -0,0 +1,29 @@
{
"@odata.context": "/redfish/v1/$metadata#DellJobCollection.DellJobCollection",
"@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/Jobs",
"@odata.type": "#DellJobCollection.DellJobCollection",
"Description": "Collection of Job Instances",
"Id": "JobQueue",
"Members": [
{
"@odata.context": "/redfish/v1/$metadata#DellJob.DellJob",
"@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/Jobs/RID_878460711202",
"@odata.type": "#DellJob.v1_0_2.DellJob",
"CompletionTime": "2020-04-25T15:21:33",
"Description": "Job Instance",
"EndTime": "TIME_NA",
"Id": "RID_878460711202",
"JobState": "Running",
"JobType": "RebootForce",
"Message": "Reboot is complete.",
"MessageArgs": [ ],
"MessageArgs@odata.count": 0,
"MessageId": "RED030",
"Name": "Reboot3",
"PercentComplete": 100,
"StartTime": "TIME_NOW",
"TargetSettingsURI": null
}
],
"Name": "JobQueue"
}

View File

@ -0,0 +1,13 @@
{
"@odata.context": "/redfish/v1/$metadata#DellJobService.DellJobService",
"@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellJobService",
"@odata.type": "#DellJobService.v1_1_0.DellJobService",
"Actions": {
"#DellJobService.DeleteJobQueue": {
"target": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellJobService/Actions/DellJobService.DeleteJobQueue"
}
},
"Description": "The DellJobService resource provides some actions to support Job management functionality.",
"Id": "Job Service",
"Name": "DellJobService"
}

View File

@ -0,0 +1,13 @@
{
"@odata.context": "/redfish/v1/$metadata#DellLCService.DellLCService",
"@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService",
"@odata.type": "#DellLCService.v1_1_0.DellLCService",
"Actions": {
"#DellLCService.GetRemoteServicesAPIStatus": {
"target": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus"
}
},
"Description": "The DellLCService resource provides some actions to support Lifecycle Controller functionality.",
"Id": "DellLCService",
"Name": "DellLCService"
}

View File

@ -0,0 +1,65 @@
# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries.
#
# 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
from unittest import mock
from oslotest.base import BaseTestCase
from sushy_oem_idrac.resources.manager import constants as mgr_cons
from sushy_oem_idrac.resources.manager import idrac_card_service
class DelliDRACCardServiceTestCase(BaseTestCase):
def setUp(self):
super(DelliDRACCardServiceTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy_oem_idrac/tests/unit/json_samples/'
'idrac_card_service.json') as f:
mock_response = self.conn.get.return_value
mock_response.json.return_value = json.load(f)
mock_response.status_code = 200
mock_response = self.conn.post.return_value
mock_response.status_code = 202
mock_response.headers.get.return_value = '1'
self.idrac_card_service = idrac_card_service.DelliDRACCardService(
self.conn, '/redfish/v1/Dell/Managers/iDRAC.Embedded.1')
def test_reset_idrac(self):
self.idrac_card_service.reset_idrac()
target_uri = ('/redfish/v1/Dell/Managers/iDRAC.Embedded.1'
'/DelliDRACCardService'
'/Actions/DelliDRACCardService.iDRACReset')
self.conn.post.assert_called_once_with(target_uri,
data={'Force': 'Graceful'})
def test_get_allowed_reset_idrac_values(self):
expected_values = {mgr_cons.RESET_IDRAC_GRACEFUL_RESTART,
mgr_cons.RESET_IDRAC_FORCE_RESTART}
allowed_values = \
self.idrac_card_service.get_allowed_reset_idrac_values()
self.assertEqual(expected_values, allowed_values)
def test_get_allowed_reset_idrac_values_not_provided_by_idrac(self):
idrac_service_json = self.idrac_card_service.json
base_property = '#DelliDRACCardService.iDRACReset'
remove_property = 'Force@Redfish.AllowableValues'
idrac_service_json['Actions'][base_property].pop(remove_property)
expected_values = {mgr_cons.RESET_IDRAC_GRACEFUL_RESTART,
mgr_cons.RESET_IDRAC_FORCE_RESTART}
allowed_values = \
self.idrac_card_service.get_allowed_reset_idrac_values()
self.assertEqual(expected_values, allowed_values)

View File

@ -0,0 +1,46 @@
# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries.
#
# 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
from unittest import mock
from oslotest.base import BaseTestCase
from sushy_oem_idrac.resources.manager import job_collection
class DellJobCollectionTestCase(BaseTestCase):
def setUp(self):
super(DellJobCollectionTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy_oem_idrac/tests/unit/json_samples/'
'job_collection_expanded.json') as f:
mock_response = self.conn.get.return_value
mock_response.json.return_value = json.load(f)
mock_response.status_code = 200
mock_response = self.conn.post.return_value
mock_response.status_code = 202
mock_response.headers.get.return_value = '1'
self.job_collection = job_collection.DellJobCollection(
self.conn, '/redfish/v1/Managers/iDRAC.Embedded.1/Jobs')
def test_get_unfinished_jobs(self):
expected_unfinished_jobs = ['RID_878460711202']
actual_unfinished_jobs = self.job_collection.get_unfinished_jobs()
target_uri = ('/redfish/v1/Managers/iDRAC.Embedded.1'
'/Jobs?$expand=.($levels=1)')
self.conn.get.assert_called_with(target_uri)
self.assertEqual(expected_unfinished_jobs, actual_unfinished_jobs)

View File

@ -0,0 +1,50 @@
# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries.
#
# 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
from unittest import mock
from oslotest.base import BaseTestCase
from sushy_oem_idrac.resources.manager import job_service
class DellJobServiceTestCase(BaseTestCase):
def setUp(self):
super(DellJobServiceTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy_oem_idrac/tests/unit/json_samples/'
'job_service.json') as f:
mock_response = self.conn.get.return_value
mock_response.json.return_value = json.load(f)
mock_response.status_code = 200
mock_response = self.conn.post.return_value
mock_response.status_code = 202
mock_response.headers.get.return_value = '1'
self.job_service = job_service.DellJobService(
self.conn,
'/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellJobService')
def test_delete_jobs(self):
job_ids = ['JID_471269252011', 'JID_471269252012']
self.job_service.delete_jobs(job_ids=job_ids)
target_uri = ('/redfish/v1/Dell/Managers'
'/iDRAC.Embedded.1/DellJobService'
'/Actions/''DellJobService.DeleteJobQueue')
for job_id in job_ids:
self.conn.post.assert_any_call(target_uri,
data={'JobID': job_id})
self.assertEqual(2, self.conn.post.call_count)

View File

@ -0,0 +1,71 @@
# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries.
#
# 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
from unittest import mock
from oslotest.base import BaseTestCase
from sushy_oem_idrac.resources.manager import lifecycle_service
class DellLCServiceTestCase(BaseTestCase):
def setUp(self):
super(DellLCServiceTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy_oem_idrac/tests/unit/json_samples/'
'lifecycle_service.json') as f:
mock_response = self.conn.get.return_value
mock_response.json.return_value = json.load(f)
mock_response.status_code = 200
mock_response = self.conn.post.return_value
mock_response.status_code = 202
mock_response.headers.get.return_value = '1'
self.lifecycle_service = lifecycle_service.DellLCService(
self.conn,
'/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService')
def test_is_idrac_ready_true(self):
mock_response = self.conn.post.return_value
mock_response.status_code = 200
mock_response.json.return_value = {
"LCStatus": "Ready",
"RTStatus": "Ready",
"ServerStatus": "OutOfPOST",
"Status": "Ready"
}
target_uri = ('/redfish/v1/Dell/Managers/iDRAC.Embedded.1'
'/DellLCService'
'/Actions/DellLCService.GetRemoteServicesAPIStatus')
idrac_ready_response = self.lifecycle_service.is_idrac_ready()
self.conn.post.assert_called_once_with(target_uri, data={})
self.assertTrue(idrac_ready_response)
def test_is_idrac_ready_false(self):
mock_response = self.conn.post.return_value
mock_response.status_code = 202
mock_response.json.return_value = {
"LCStatus": "NotReady",
"RTStatus": "NotReady",
"ServerStatus": "OutOfPOST",
"Status": "NotReady"
}
target_uri = ('/redfish/v1/Dell/Managers/iDRAC.Embedded.1'
'/DellLCService'
'/Actions/DellLCService.GetRemoteServicesAPIStatus')
idrac_ready_response = self.lifecycle_service.is_idrac_ready()
self.conn.post.assert_called_once_with(target_uri, data={})
self.assertFalse(idrac_ready_response)

View File

@ -22,6 +22,10 @@ import sushy
from sushy.resources.manager import manager from sushy.resources.manager import manager
from sushy_oem_idrac.resources.manager import constants as mgr_cons from sushy_oem_idrac.resources.manager import constants as mgr_cons
from sushy_oem_idrac.resources.manager import idrac_card_service as idrac_card
from sushy_oem_idrac.resources.manager import job_collection as jc
from sushy_oem_idrac.resources.manager import job_service as job
from sushy_oem_idrac.resources.manager import lifecycle_service as lifecycle
class ManagerTestCase(BaseTestCase): class ManagerTestCase(BaseTestCase):
@ -152,3 +156,62 @@ class ManagerTestCase(BaseTestCase):
self.assertRaises(sushy.exceptions.ExtensionError, self.assertRaises(sushy.exceptions.ExtensionError,
oem.get_pxe_port_macs_bios, ethernet_interfaces_mac) oem.get_pxe_port_macs_bios, ethernet_interfaces_mac)
def test_idrac_card_service(self):
oem = self.manager.get_oem_extension('Dell')
with open('sushy_oem_idrac/tests/unit/json_samples/'
'idrac_card_service.json') as f:
mock_response = self.conn.get.return_value
mock_response.json.return_value = json.load(f)
mock_response.status_code = 200
idrac_card_service = oem.idrac_card_service
self.assertEqual(
'/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DelliDRACCardService',
idrac_card_service.path)
self.assertIsInstance(idrac_card_service,
idrac_card.DelliDRACCardService)
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_lifecycle_service(self):
oem = self.manager.get_oem_extension('Dell')
with open('sushy_oem_idrac/tests/unit/json_samples/'
'lifecycle_service.json') as f:
mock_response = self.conn.get.return_value
mock_response.json.return_value = json.load(f)
mock_response.status_code = 200
lifecycle_service = oem.lifecycle_service
self.assertEqual(
'/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService',
lifecycle_service.path)
self.assertIsInstance(lifecycle_service,
lifecycle.DellLCService)
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_job_service(self):
oem = self.manager.get_oem_extension('Dell')
with open('sushy_oem_idrac/tests/unit/json_samples/'
'job_service.json') as f:
mock_response = self.conn.get.return_value
mock_response.json.return_value = json.load(f)
mock_response.status_code = 200
job_service = oem.job_service
self.assertEqual(
'/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellJobService',
job_service.path)
self.assertIsInstance(job_service,
job.DellJobService)
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_job_collection(self):
oem = self.manager.get_oem_extension('Dell')
with open('sushy_oem_idrac/tests/unit/json_samples/'
'job_collection_expanded.json') as f:
mock_response = self.conn.get.return_value
mock_response.json.return_value = json.load(f)
mock_response.status_code = 200
job_collection = oem.job_collection
self.assertEqual(
'/redfish/v1/Managers/iDRAC.Embedded.1/Jobs',
job_collection.path)
self.assertIsInstance(job_collection,
jc.DellJobCollection)