Redfish: Add support for Virtual Media Operations
This commit adds support to perform virtual media operations 'set_vm_status', 'eject_vmedia' and 'insert_vmedia'. Change-Id: Ia4d7d4984808c0b0be87262837174090066e0f2a Partial-Bug: 1691955
This commit is contained in:
parent
ca8033177c
commit
ead74eadad
|
@ -68,6 +68,9 @@ SUPPORTED_REDFISH_METHODS = [
|
|||
'get_pending_boot_mode',
|
||||
'get_current_boot_mode',
|
||||
'activate_license',
|
||||
'eject_virtual_media',
|
||||
'insert_virtual_media',
|
||||
'set_vm_status'
|
||||
]
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
|
|
|
@ -22,6 +22,7 @@ from proliantutils import exception
|
|||
from proliantutils.ilo import operations
|
||||
from proliantutils import log
|
||||
from proliantutils.redfish import main
|
||||
from proliantutils.redfish.resources.manager import constants as mgr_cons
|
||||
from proliantutils.redfish.resources.system import constants as sys_cons
|
||||
|
||||
"""
|
||||
|
@ -61,6 +62,13 @@ BOOT_MODE_MAP_REV = (
|
|||
PROLIANT_MANAGER_ID = '1'
|
||||
PROLIANT_SYSTEM_ID = '1'
|
||||
|
||||
BOOT_OPTION_MAP = {'BOOT_ONCE': True,
|
||||
'BOOT_ALWAYS': False,
|
||||
'NO_BOOT': False}
|
||||
|
||||
VIRTUAL_MEDIA_MAP = {'FLOPPY': mgr_cons.VIRTUAL_MEDIA_FLOPPY,
|
||||
'CDROM': mgr_cons.VIRTUAL_MEDIA_CD}
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
|
||||
|
||||
|
@ -306,3 +314,113 @@ class RedfishOperations(operations.IloOperations):
|
|||
{'error': str(e)})
|
||||
LOG.debug(msg)
|
||||
raise exception.IloError(msg)
|
||||
|
||||
def _validate_virtual_media(self, device):
|
||||
"""Check if the device is valid device.
|
||||
|
||||
:param device: virtual media device
|
||||
:raises: IloInvalidInputError, if the device is not valid.
|
||||
"""
|
||||
if device not in VIRTUAL_MEDIA_MAP:
|
||||
msg = (self._("Invalid device '%s'. Valid devices: FLOPPY or "
|
||||
"CDROM.")
|
||||
% device)
|
||||
LOG.debug(msg)
|
||||
raise exception.IloInvalidInputError(msg)
|
||||
|
||||
def eject_virtual_media(self, device):
|
||||
"""Ejects the Virtual Media image if one is inserted.
|
||||
|
||||
:param device: virual media device
|
||||
:raises: IloError, on an error from iLO.
|
||||
:raises: IloInvalidInputError, if the device is not valid.
|
||||
"""
|
||||
self._validate_virtual_media(device)
|
||||
manager = self._get_sushy_manager(PROLIANT_MANAGER_ID)
|
||||
try:
|
||||
vmedia_device = (
|
||||
manager.virtual_media.get_member_from_device(
|
||||
VIRTUAL_MEDIA_MAP[device]))
|
||||
if not vmedia_device.inserted:
|
||||
LOG.debug(self._("No media available in the device '%s' to "
|
||||
"perform eject operation.") % device)
|
||||
return
|
||||
|
||||
LOG.debug(self._("Ejecting the media image '%(url)s' from the "
|
||||
"device %(device)s.") %
|
||||
{'url': vmedia_device.image_url, 'device': device})
|
||||
vmedia_device.eject_vmedia()
|
||||
except sushy.exceptions.SushyError as e:
|
||||
msg = (self._("The Redfish controller failed to eject the virtual"
|
||||
" media device '%(device)s'. Error %(error)s.") %
|
||||
{'device': device, 'error': str(e)})
|
||||
LOG.debug(msg)
|
||||
raise exception.IloError(msg)
|
||||
|
||||
def insert_virtual_media(self, url, device):
|
||||
"""Inserts the Virtual Media image to the device.
|
||||
|
||||
:param url: URL to image
|
||||
:param device: virual media device
|
||||
:raises: IloError, on an error from iLO.
|
||||
:raises: IloInvalidInputError, if the device is not valid.
|
||||
"""
|
||||
self._validate_virtual_media(device)
|
||||
manager = self._get_sushy_manager(PROLIANT_MANAGER_ID)
|
||||
try:
|
||||
vmedia_device = (
|
||||
manager.virtual_media.get_member_from_device(
|
||||
VIRTUAL_MEDIA_MAP[device]))
|
||||
if vmedia_device.inserted:
|
||||
vmedia_device.eject_vmedia()
|
||||
|
||||
LOG.debug(self._("Inserting the image url '%(url)s' to the "
|
||||
"device %(device)s.") %
|
||||
{'url': url, 'device': device})
|
||||
vmedia_device.insert_vmedia(url)
|
||||
except sushy.exceptions.SushyError as e:
|
||||
msg = (self._("The Redfish controller failed to insert the media "
|
||||
"url %(url)s in the virtual media device "
|
||||
"'%(device)s'. Error %(error)s.") %
|
||||
{'url': url, 'device': device, 'error': str(e)})
|
||||
LOG.debug(msg)
|
||||
raise exception.IloError(msg)
|
||||
|
||||
def set_vm_status(self, device='FLOPPY',
|
||||
boot_option='BOOT_ONCE', write_protect='YES'):
|
||||
"""Sets the Virtual Media drive status
|
||||
|
||||
It sets the boot option for virtual media device.
|
||||
Note: boot option can be set only for CD device.
|
||||
|
||||
:param device: virual media device
|
||||
:param boot_option: boot option to set on the virtual media device
|
||||
:param write_protect: set the write protect flag on the vmedia device
|
||||
Note: It's ignored. In Redfish it is read-only.
|
||||
:raises: IloError, on an error from iLO.
|
||||
:raises: IloInvalidInputError, if the device is not valid.
|
||||
"""
|
||||
# CONNECT is a RIBCL call. There is no such property to set in Redfish.
|
||||
if boot_option == 'CONNECT':
|
||||
return
|
||||
|
||||
self._validate_virtual_media(device)
|
||||
|
||||
if boot_option not in BOOT_OPTION_MAP:
|
||||
msg = (self._("Virtual media boot option '%s' is invalid.")
|
||||
% boot_option)
|
||||
LOG.debug(msg)
|
||||
raise exception.IloInvalidInputError(msg)
|
||||
|
||||
manager = self._get_sushy_manager(PROLIANT_MANAGER_ID)
|
||||
try:
|
||||
vmedia_device = (
|
||||
manager.virtual_media.get_member_from_device(
|
||||
VIRTUAL_MEDIA_MAP[device]))
|
||||
vmedia_device.set_vm_status(BOOT_OPTION_MAP[boot_option])
|
||||
except sushy.exceptions.SushyError as e:
|
||||
msg = (self._("The Redfish controller failed to set the virtual "
|
||||
"media status for '%(device)s'. Error %(error)s") %
|
||||
{'device': device, 'error': str(e)})
|
||||
LOG.debug(msg)
|
||||
raise exception.IloError(msg)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# Copyright 2017 Hewlett Packard Enterprise Development LP
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Virtual Media types
|
||||
|
||||
VIRTUAL_MEDIA_CD = 'cd'
|
||||
|
||||
VIRTUAL_MEDIA_FLOPPY = 'floppy'
|
||||
|
||||
VIRTUAL_MEDIA_DVD = 'dvd'
|
||||
|
||||
VIRTUAL_MEDIA_USB_STICK = 'usb stick'
|
|
@ -16,6 +16,7 @@ __author__ = 'HPE'
|
|||
|
||||
from sushy.resources.manager import manager
|
||||
|
||||
from proliantutils.redfish.resources.manager import virtual_media
|
||||
from proliantutils.redfish import utils
|
||||
|
||||
|
||||
|
@ -26,6 +27,8 @@ class HPEManager(manager.Manager):
|
|||
from sushy
|
||||
"""
|
||||
|
||||
_virtual_media = None
|
||||
|
||||
def set_license(self, key):
|
||||
"""Set the license on a redfish system
|
||||
|
||||
|
@ -35,3 +38,18 @@ class HPEManager(manager.Manager):
|
|||
license_service_uri = (utils.get_subresource_path_by(self,
|
||||
['Oem', 'Hpe', 'Links', 'LicenseService']))
|
||||
self._conn.post(license_service_uri, data=data)
|
||||
|
||||
@property
|
||||
def virtual_media(self):
|
||||
"""Property to provide reference to `VirtualMediaCollection` instance.
|
||||
|
||||
It is calculated once when the first time it is queried. On refresh,
|
||||
this property gets reset.
|
||||
"""
|
||||
if self._virtual_media is None:
|
||||
self._virtual_media = virtual_media.VirtualMediaCollection(
|
||||
self._conn,
|
||||
utils.get_subresource_path_by(self, 'VirtualMedia'),
|
||||
redfish_version=self.redfish_version)
|
||||
|
||||
return self._virtual_media
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright 2017 Hewlett Packard Enterprise Development LP
|
||||
#
|
||||
# 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 import utils
|
||||
|
||||
from proliantutils.redfish.resources.manager import constants as cons
|
||||
|
||||
VIRTUAL_MEDIA_TYPES_MAP = {
|
||||
'CD': cons.VIRTUAL_MEDIA_CD,
|
||||
'DVD': cons.VIRTUAL_MEDIA_DVD,
|
||||
'Floppy': cons.VIRTUAL_MEDIA_FLOPPY,
|
||||
'USBStick': cons.VIRTUAL_MEDIA_USB_STICK
|
||||
}
|
||||
|
||||
VIRTUAL_MEDIA_TYPES_MAP_REV = utils.revert_dictionary(VIRTUAL_MEDIA_TYPES_MAP)
|
|
@ -0,0 +1,122 @@
|
|||
# Copyright 2017 Hewlett Packard Enterprise Development LP
|
||||
#
|
||||
# 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.
|
||||
|
||||
__author__ = 'HPE'
|
||||
|
||||
from sushy.resources import base
|
||||
from sushy.resources import common
|
||||
|
||||
from proliantutils import exception
|
||||
from proliantutils import log
|
||||
from proliantutils.redfish.resources.manager import mapping as maps
|
||||
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
|
||||
|
||||
def _get_media(media_types):
|
||||
"""Helper method to map the media types."""
|
||||
get_mapped_media = (lambda x: maps.VIRTUAL_MEDIA_TYPES_MAP[x]
|
||||
if x in maps.VIRTUAL_MEDIA_TYPES_MAP else None)
|
||||
return list(map(get_mapped_media, media_types))
|
||||
|
||||
|
||||
class ActionsField(base.CompositeField):
|
||||
insert_vmedia = common.ResetActionField(
|
||||
'#HpeiLOVirtualMedia.InsertVirtualMedia')
|
||||
|
||||
eject_vmedia = common.ResetActionField(
|
||||
'#HpeiLOVirtualMedia.EjectVirtualMedia')
|
||||
|
||||
|
||||
class VirtualMedia(base.ResourceBase):
|
||||
|
||||
media_types = base.Field('MediaTypes', adapter=_get_media,
|
||||
required=True)
|
||||
"""A list of allowed media types for the instance."""
|
||||
|
||||
inserted = base.Field('Inserted', required=True)
|
||||
"""A boolean value which represents vmedia is inserted or not."""
|
||||
|
||||
image_url = base.Field('Image')
|
||||
"""A string which represents the virtual media image url."""
|
||||
|
||||
_actions = ActionsField(['Oem', 'Hpe', 'Actions'], required=True)
|
||||
|
||||
def _get_action_element(self, action_type):
|
||||
"""Helper method to return the action object."""
|
||||
action = eval("self._actions." + action_type + "_vmedia")
|
||||
|
||||
if not action:
|
||||
if action_type == "insert":
|
||||
action_path = '#HpeiLOVirtualMedia.InsertVirtualMedia'
|
||||
else:
|
||||
action_path = '#HpeiLOVirtualMedia.EjectVirtualMedia'
|
||||
|
||||
raise exception.MissingAttributeError(
|
||||
attribute=action_path,
|
||||
resource=self._path)
|
||||
|
||||
return action
|
||||
|
||||
def insert_vmedia(self, url):
|
||||
"""Inserts Virtual Media to the device
|
||||
|
||||
:param url: URL to image.
|
||||
:raises: SushyError, on an error from iLO.
|
||||
"""
|
||||
target_uri = self._get_action_element('insert').target_uri
|
||||
data = {'Image': url}
|
||||
self._conn.post(target_uri, data=data)
|
||||
|
||||
def eject_vmedia(self):
|
||||
"""Ejects Virtual Media.
|
||||
|
||||
:raises: SushyError, on an error from iLO.
|
||||
"""
|
||||
target_uri = self._get_action_element('eject').target_uri
|
||||
data = {}
|
||||
self._conn.post(target_uri, data=data)
|
||||
|
||||
def set_vm_status(self, boot_on_next_reset):
|
||||
"""Set the Virtual Media drive status.
|
||||
|
||||
:param boot_on_next_reset: boolean value
|
||||
:raises: SushyError, on an error from iLO.
|
||||
"""
|
||||
data = {
|
||||
"Oem": {
|
||||
"Hpe": {
|
||||
"BootOnNextServerReset": boot_on_next_reset
|
||||
}
|
||||
}
|
||||
}
|
||||
self._conn.patch(self.path, data=data)
|
||||
|
||||
|
||||
class VirtualMediaCollection(base.ResourceCollectionBase):
|
||||
|
||||
@property
|
||||
def _resource_type(self):
|
||||
return VirtualMedia
|
||||
|
||||
def get_member_from_device(self, device):
|
||||
"""Returns the given virtual media device object.
|
||||
|
||||
:param device: virtual media device to be queried
|
||||
:returns virtual media device object.
|
||||
"""
|
||||
for vmedia_device in self.get_members():
|
||||
if device in vmedia_device.media_types:
|
||||
return vmedia_device
|
|
@ -0,0 +1,115 @@
|
|||
{
|
||||
"default": {
|
||||
"@odata.context": "/redfish/v1/$metadata#Managers/Members/1/VirtualMedia/Members/$entity",
|
||||
"@odata.etag": "W/\"FD62A3AF\"",
|
||||
"@odata.id": "/redfish/v1/Managers/1/VirtualMedia/2/",
|
||||
"@odata.type": "#VirtualMedia.v1_0_0.VirtualMedia",
|
||||
"ConnectedVia": "NotConnected",
|
||||
"Description": "Virtual Removable Media",
|
||||
"Id": "2",
|
||||
"Image": "",
|
||||
"Inserted": false,
|
||||
"MediaTypes":
|
||||
[
|
||||
"CD",
|
||||
"DVD"
|
||||
],
|
||||
"Name": "VirtualMedia",
|
||||
"Oem":
|
||||
{
|
||||
"Hpe":
|
||||
{
|
||||
"@odata.type": "#HpeiLOVirtualMedia.v2_0_0.HpeiLOVirtualMedia",
|
||||
"Actions":
|
||||
{
|
||||
"#HpeiLOVirtualMedia.EjectVirtualMedia":
|
||||
{
|
||||
"target": "/redfish/v1/Managers/1/VirtualMedia/2/Actions/Oem/Hpe/HpeiLOVirtualMedia.EjectVirtualMedia/"
|
||||
},
|
||||
"#HpeiLOVirtualMedia.InsertVirtualMedia":
|
||||
{
|
||||
"target": "/redfish/v1/Managers/1/VirtualMedia/2/Actions/Oem/Hpe/HpeiLOVirtualMedia.InsertVirtualMedia/"
|
||||
}
|
||||
},
|
||||
"BootOnNextServerReset": false
|
||||
}
|
||||
},
|
||||
"WriteProtected": true
|
||||
},
|
||||
"vmedia_inserted": {
|
||||
"@odata.context": "/redfish/v1/$metadata#Managers/Members/1/VirtualMedia/Members/$entity",
|
||||
"@odata.etag": "W/\"402B70A4\"",
|
||||
"@odata.id": "/redfish/v1/Managers/1/VirtualMedia/2/",
|
||||
"@odata.type": "#VirtualMedia.v1_0_0.VirtualMedia",
|
||||
"ConnectedVia": "URI",
|
||||
"Description": "Virtual Removable Media",
|
||||
"Id": "1",
|
||||
"Image": "http://172.17.1.121:8081/test",
|
||||
"ImageName": "test",
|
||||
"Inserted": true,
|
||||
"MediaTypes":
|
||||
[
|
||||
"CD",
|
||||
"DVD"
|
||||
],
|
||||
"Name": "VirtualMedia",
|
||||
"Oem":
|
||||
{
|
||||
"Hpe":
|
||||
{
|
||||
"@odata.type": "#HpeiLOVirtualMedia.v2_0_0.HpeiLOVirtualMedia",
|
||||
"Actions":
|
||||
{
|
||||
"#HpeiLOVirtualMedia.EjectVirtualMedia":
|
||||
{
|
||||
"target": "/redfish/v1/Managers/1/VirtualMedia/2/Actions/Oem/Hpe/HpeiLOVirtualMedia.EjectVirtualMedia/"
|
||||
},
|
||||
"#HpeiLOVirtualMedia.InsertVirtualMedia":
|
||||
{
|
||||
"target": "/redfish/v1/Managers/1/VirtualMedia/2/Actions/Oem/Hpe/HpeiLOVirtualMedia.InsertVirtualMedia/"
|
||||
},
|
||||
"BootOnNextServerReset": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"WriteProtected": true
|
||||
},
|
||||
"vmedia_floppy": {
|
||||
"@odata.context": "/redfish/v1/$metadata#Managers/Members/1/VirtualMedia/Members/$entity",
|
||||
"@odata.etag": "W/\"6C5A7D71\"",
|
||||
"@odata.id": "/redfish/v1/Managers/1/VirtualMedia/1/",
|
||||
"@odata.type": "#VirtualMedia.v1_0_0.VirtualMedia",
|
||||
"ConnectedVia": "NotConnected",
|
||||
"Description": "Virtual Removable Media",
|
||||
"Id": "1",
|
||||
"Image": "",
|
||||
"Inserted": false,
|
||||
"MediaTypes":
|
||||
[
|
||||
"Floppy",
|
||||
"USBStick"
|
||||
],
|
||||
"Name": "VirtualMedia",
|
||||
"Oem":
|
||||
{
|
||||
"Hpe":
|
||||
{
|
||||
"@odata.type": "#HpeiLOVirtualMedia.v2_0_0.HpeiLOVirtualMedia",
|
||||
"Actions":
|
||||
{
|
||||
"#HpeiLOVirtualMedia.EjectVirtualMedia":
|
||||
{
|
||||
"target": "/redfish/v1/Managers/1/VirtualMedia/1/Actions/Oem/Hpe/HpeiLOVirtualMedia.EjectVirtualMedia/"
|
||||
},
|
||||
"#HpeiLOVirtualMedia.InsertVirtualMedia":
|
||||
{
|
||||
"target": "/redfish/v1/Managers/1/VirtualMedia/1/Actions/Oem/Hpe/HpeiLOVirtualMedia.InsertVirtualMedia/"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"WriteProtected": false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#Managers/Members/1/VirtualMedia",
|
||||
"@odata.etag": "W/\"72D11D4D\"",
|
||||
"@odata.id": "/redfish/v1/Managers/1/VirtualMedia/",
|
||||
"@odata.type": "#VirtualMediaCollection.VirtualMediaCollection",
|
||||
"Description": "iLO Virtual Media Services Settings",
|
||||
"Members":
|
||||
[
|
||||
{
|
||||
"@odata.id": "/redfish/v1/Managers/1/VirtualMedia/2/"
|
||||
}
|
||||
],
|
||||
"Members@odata.count": 1,
|
||||
"Name": "Virtual Media Services"
|
||||
}
|
||||
|
||||
|
|
@ -18,6 +18,7 @@ import mock
|
|||
import testtools
|
||||
|
||||
from proliantutils.redfish.resources.manager import manager
|
||||
from proliantutils.redfish.resources.manager import virtual_media
|
||||
|
||||
|
||||
class HPEManagerTestCase(testtools.TestCase):
|
||||
|
@ -38,3 +39,24 @@ class HPEManagerTestCase(testtools.TestCase):
|
|||
self.mgr_inst._conn.post.assert_called_once_with(
|
||||
'/redfish/v1/Managers/1/LicenseService/',
|
||||
data={'LicenseKey': 'testkey'})
|
||||
|
||||
def test_virtual_media(self):
|
||||
self.assertIsNone(self.mgr_inst._virtual_media)
|
||||
|
||||
self.conn.get.return_value.json.reset_mock()
|
||||
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/vmedia_collection.json', 'r') as f:
|
||||
self.conn.get.return_value.json.return_value = json.loads(f.read())
|
||||
actual_vmedia = self.mgr_inst.virtual_media
|
||||
|
||||
self.assertIsInstance(actual_vmedia,
|
||||
virtual_media.VirtualMediaCollection)
|
||||
self.conn.get.return_value.json.assert_called_once_with()
|
||||
|
||||
# reset mock
|
||||
self.conn.get.return_value.json.reset_mock()
|
||||
|
||||
self.assertIs(actual_vmedia,
|
||||
self.mgr_inst.virtual_media)
|
||||
self.conn.get.return_value.json.assert_not_called()
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
# Copyright 2017 Hewlett Packard Enterprise Development LP
|
||||
#
|
||||
# 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.
|
||||
|
||||
__author__ = 'HPE'
|
||||
|
||||
import json
|
||||
|
||||
import mock
|
||||
from sushy import exceptions
|
||||
import testtools
|
||||
|
||||
from proliantutils import exception
|
||||
from proliantutils.redfish.resources.manager import constants
|
||||
from proliantutils.redfish.resources.manager import virtual_media
|
||||
|
||||
|
||||
class VirtualMediaCollectionTestCase(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(VirtualMediaCollectionTestCase, self).setUp()
|
||||
self.conn = mock.MagicMock()
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/vmedia_collection.json', 'r') as f:
|
||||
self.conn.get.return_value.json.return_value = (
|
||||
json.loads(f.read()))
|
||||
|
||||
self.vmedia_coll_inst = virtual_media.VirtualMediaCollection(
|
||||
self.conn, '/redfish/v1/Managers/1/VirtualMedia',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
def test_get_member_from_device(self):
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/vmedia.json', 'r') as f:
|
||||
self.conn.get.return_value.json.return_value = (
|
||||
json.loads(f.read())['default'])
|
||||
|
||||
obj = self.vmedia_coll_inst.get_member_from_device(
|
||||
constants.VIRTUAL_MEDIA_CD)
|
||||
|
||||
self.assertIsInstance(obj, virtual_media.VirtualMedia)
|
||||
|
||||
|
||||
class VirtualMediaTestCase(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(VirtualMediaTestCase, self).setUp()
|
||||
self.conn = mock.MagicMock()
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/vmedia.json', 'r') as f:
|
||||
vmedia_json = json.loads(f.read())
|
||||
|
||||
self.conn.get.return_value.json.return_value = vmedia_json[
|
||||
'default']
|
||||
|
||||
self.vmedia_inst = virtual_media.VirtualMedia(
|
||||
self.conn, '/redfish/v1/Managers/1/VirtualMedia/2',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
def test__parse_attributes(self):
|
||||
self.vmedia_inst._parse_attributes()
|
||||
self.assertEqual(['cd', 'dvd'], self.vmedia_inst.media_types)
|
||||
self.assertEqual(False, self.vmedia_inst.inserted)
|
||||
|
||||
def test__parse_attributes_missing_actions(self):
|
||||
self.vmedia_inst.json.pop('Oem')
|
||||
self.assertRaisesRegex(
|
||||
exceptions.MissingAttributeError, 'attribute Oem/Hpe/Actions',
|
||||
self.vmedia_inst._parse_attributes)
|
||||
|
||||
def test__get_action_element_insert(self):
|
||||
value = self.vmedia_inst._get_action_element('insert')
|
||||
self.assertEqual("/redfish/v1/Managers/1/VirtualMedia/2/Actions/Oem/"
|
||||
"Hpe/HpeiLOVirtualMedia.InsertVirtualMedia/",
|
||||
value.target_uri)
|
||||
|
||||
def test__get_action_element_missing_insert_action(self):
|
||||
self.vmedia_inst._actions.insert_vmedia = None
|
||||
self.assertRaisesRegex(
|
||||
exception.MissingAttributeError,
|
||||
'attribute #HpeiLOVirtualMedia.InsertVirtualMedia',
|
||||
self.vmedia_inst._get_action_element, 'insert')
|
||||
|
||||
def test__get_action_element_eject(self):
|
||||
value = self.vmedia_inst._get_action_element('eject')
|
||||
self.assertEqual("/redfish/v1/Managers/1/VirtualMedia/2/Actions/Oem/"
|
||||
"Hpe/HpeiLOVirtualMedia.EjectVirtualMedia/",
|
||||
value.target_uri)
|
||||
|
||||
def test__get__action_element_missing_eject_action(self):
|
||||
self.vmedia_inst._actions.eject_vmedia = None
|
||||
self.assertRaisesRegex(
|
||||
exception.MissingAttributeError,
|
||||
'attribute #HpeiLOVirtualMedia.EjectVirtualMedia',
|
||||
self.vmedia_inst._get_action_element, 'eject')
|
||||
|
||||
def test_insert_vmedia(self):
|
||||
url = "http://1.2.3.4:5678/xyz.iso"
|
||||
self.vmedia_inst.insert_vmedia(url)
|
||||
self.vmedia_inst._conn.post.assert_called_once_with(
|
||||
"/redfish/v1/Managers/1/VirtualMedia/2/Actions/Oem/Hpe/"
|
||||
"HpeiLOVirtualMedia.InsertVirtualMedia/",
|
||||
data={'Image': url})
|
||||
|
||||
def test_eject_vmedia(self):
|
||||
self.vmedia_inst.eject_vmedia()
|
||||
self.vmedia_inst._conn.post.assert_called_once_with(
|
||||
"/redfish/v1/Managers/1/VirtualMedia/2/Actions/Oem/Hpe/"
|
||||
"HpeiLOVirtualMedia.EjectVirtualMedia/",
|
||||
data={})
|
||||
|
||||
def test_set_vm_status(self):
|
||||
value = {'Oem': {'Hpe': {'BootOnNextServerReset': True}}}
|
||||
self.vmedia_inst.set_vm_status(True)
|
||||
self.vmedia_inst._conn.patch.assert_called_once_with(
|
||||
"/redfish/v1/Managers/1/VirtualMedia/2",
|
||||
data=value)
|
|
@ -22,6 +22,8 @@ import testtools
|
|||
from proliantutils import exception
|
||||
from proliantutils.redfish import main
|
||||
from proliantutils.redfish import redfish
|
||||
from proliantutils.redfish.resources.manager import manager
|
||||
from proliantutils.redfish.resources.manager import virtual_media
|
||||
from proliantutils.redfish.resources.system import constants as sys_cons
|
||||
from sushy.resources.system import system
|
||||
|
||||
|
@ -224,3 +226,195 @@ class RedfishOperationsTestCase(testtools.TestCase):
|
|||
exception.IloError,
|
||||
'The Redfish controller failed to update the license',
|
||||
self.rf_client.activate_license, 'key')
|
||||
|
||||
def _setup_virtual_media(self):
|
||||
self.conn = mock.Mock()
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/manager.json', 'r') as f:
|
||||
self.conn.get.return_value.json.return_value = json.loads(f.read())
|
||||
|
||||
manager_mock = manager.HPEManager(
|
||||
self.conn, '/redfish/v1/Managers/1',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/vmedia_collection.json', 'r') as f:
|
||||
vmedia_collection_json = json.loads(f.read())
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/vmedia.json', 'r') as f:
|
||||
vmedia_json = json.loads(f.read())
|
||||
return manager_mock, vmedia_collection_json, vmedia_json
|
||||
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'eject_vmedia')
|
||||
def test_eject_virtual_media(self, eject_mock, manager_mock):
|
||||
manager_mock.return_value, vmedia_collection_json, vmedia_json = (
|
||||
self._setup_virtual_media())
|
||||
self.conn.get.return_value.json.side_effect = [
|
||||
vmedia_collection_json, vmedia_json['vmedia_inserted']]
|
||||
|
||||
self.rf_client.eject_virtual_media('CDROM')
|
||||
|
||||
eject_mock.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'eject_vmedia')
|
||||
def test_eject_virtual_media_invalid_device(self, eject_mock,
|
||||
manager_mock):
|
||||
self.assertRaisesRegex(
|
||||
exception.IloError,
|
||||
"Invalid device 'XXXXX'. Valid devices: FLOPPY or CDROM.",
|
||||
self.rf_client.eject_virtual_media,
|
||||
'XXXXX')
|
||||
|
||||
self.assertFalse(eject_mock.called)
|
||||
self.assertFalse(manager_mock.called)
|
||||
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'eject_vmedia')
|
||||
def test_eject_virtual_media_not_inserted(self, eject_mock, manager_mock):
|
||||
manager_mock.return_value, vmedia_collection_json, vmedia_json = (
|
||||
self._setup_virtual_media())
|
||||
self.conn.get.return_value.json.side_effect = [
|
||||
vmedia_collection_json, vmedia_json['default']]
|
||||
|
||||
self.rf_client.eject_virtual_media('CDROM')
|
||||
|
||||
self.assertFalse(eject_mock.called)
|
||||
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'eject_vmedia')
|
||||
def test_eject_virtual_media_floppy(self, eject_mock, manager_mock):
|
||||
manager_mock.return_value, vmedia_collection_json, vmedia_json = (
|
||||
self._setup_virtual_media())
|
||||
self.conn.get.return_value.json.side_effect = [
|
||||
vmedia_collection_json, vmedia_json['vmedia_floppy']]
|
||||
|
||||
self.rf_client.eject_virtual_media('FLOPPY')
|
||||
|
||||
self.assertFalse(eject_mock.called)
|
||||
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'eject_vmedia')
|
||||
def test_eject_virtual_media_fail(self, eject_mock, manager_mock):
|
||||
manager_mock.return_value, vmedia_collection_json, vmedia_json = (
|
||||
self._setup_virtual_media())
|
||||
eject_mock.side_effect = sushy.exceptions.SushyError
|
||||
self.conn.get.return_value.json.side_effect = [
|
||||
vmedia_collection_json, vmedia_json['vmedia_inserted']]
|
||||
|
||||
msg = ("The Redfish controller failed to eject the virtual"
|
||||
" media device 'CDROM'.")
|
||||
self.assertRaisesRegex(exception.IloError, msg,
|
||||
self.rf_client.eject_virtual_media,
|
||||
'CDROM')
|
||||
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'eject_vmedia')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'insert_vmedia')
|
||||
def test_insert_virtual_media(self, insert_mock, eject_mock, manager_mock):
|
||||
manager_mock.return_value, vmedia_collection_json, vmedia_json = (
|
||||
self._setup_virtual_media())
|
||||
self.conn.get.return_value.json.side_effect = [
|
||||
vmedia_collection_json, vmedia_json['default']]
|
||||
url = 'http://1.2.3.4:5678/xyz.iso'
|
||||
|
||||
self.rf_client.insert_virtual_media(url, 'CDROM')
|
||||
|
||||
self.assertFalse(eject_mock.called)
|
||||
insert_mock.assert_called_once_with(url)
|
||||
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'eject_vmedia')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'insert_vmedia')
|
||||
def test_insert_virtual_media_floppy(self, insert_mock, eject_mock,
|
||||
manager_mock):
|
||||
manager_mock.return_value, vmedia_collection_json, vmedia_json = (
|
||||
self._setup_virtual_media())
|
||||
self.conn.get.return_value.json.side_effect = [
|
||||
vmedia_collection_json, vmedia_json['vmedia_floppy']]
|
||||
url = 'http://1.2.3.4:5678/xyz.iso'
|
||||
|
||||
self.rf_client.insert_virtual_media(url, 'FLOPPY')
|
||||
|
||||
self.assertFalse(eject_mock.called)
|
||||
insert_mock.assert_called_once_with(url)
|
||||
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'eject_vmedia')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'insert_vmedia')
|
||||
def test_insert_virtual_media_inserted(self, insert_mock, eject_mock,
|
||||
manager_mock):
|
||||
manager_mock.return_value, vmedia_collection_json, vmedia_json = (
|
||||
self._setup_virtual_media())
|
||||
self.conn.get.return_value.json.side_effect = [
|
||||
vmedia_collection_json, vmedia_json['vmedia_inserted']]
|
||||
url = 'http://1.2.3.4:5678/xyz.iso'
|
||||
|
||||
self.rf_client.insert_virtual_media(url, 'CDROM')
|
||||
|
||||
eject_mock.assert_called_once_with()
|
||||
insert_mock.assert_called_once_with(url)
|
||||
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'eject_vmedia')
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'insert_vmedia')
|
||||
def test_insert_virtual_media_fail(self, insert_mock, eject_mock,
|
||||
manager_mock):
|
||||
manager_mock.return_value, vmedia_collection_json, vmedia_json = (
|
||||
self._setup_virtual_media())
|
||||
insert_mock.side_effect = sushy.exceptions.SushyError
|
||||
self.conn.get.return_value.json.side_effect = [
|
||||
vmedia_collection_json, vmedia_json['vmedia_inserted']]
|
||||
url = 'http://1.2.3.4:5678/xyz.iso'
|
||||
msg = ("The Redfish controller failed to insert the media url "
|
||||
"%s in the virtual media device 'CDROM'.") % url
|
||||
|
||||
self.assertRaisesRegex(exception.IloError, msg,
|
||||
self.rf_client.insert_virtual_media,
|
||||
url, 'CDROM')
|
||||
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'set_vm_status')
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
def test_set_vm_status(self, manager_mock, set_mock):
|
||||
manager_mock.return_value, vmedia_collection_json, vmedia_json = (
|
||||
self._setup_virtual_media())
|
||||
self.conn.get.return_value.json.side_effect = [
|
||||
vmedia_collection_json, vmedia_json['default']]
|
||||
|
||||
self.rf_client.set_vm_status(device='CDROM')
|
||||
|
||||
set_mock.assert_called_once_with(True)
|
||||
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'set_vm_status')
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
def test_set_vm_status_fail(self, manager_mock, set_mock):
|
||||
manager_mock.return_value, vmedia_collection_json, vmedia_json = (
|
||||
self._setup_virtual_media())
|
||||
set_mock.side_effect = sushy.exceptions.SushyError
|
||||
self.conn.get.return_value.json.side_effect = [
|
||||
vmedia_collection_json, vmedia_json['default']]
|
||||
msg = ("The Redfish controller failed to set the virtual "
|
||||
"media status.")
|
||||
|
||||
self.assertRaisesRegex(exception.IloError, msg,
|
||||
self.rf_client.set_vm_status,
|
||||
'CDROM')
|
||||
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'set_vm_status')
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
def test_set_vm_status_not_supported_boot_option(self, manager_mock,
|
||||
set_mock):
|
||||
msg = ("Virtual media boot option 'XXXX' is invalid.")
|
||||
self.assertRaisesRegex(exception.IloInvalidInputError, msg,
|
||||
self.rf_client.set_vm_status,
|
||||
device='CDROM', boot_option='XXXX')
|
||||
self.assertFalse(manager_mock.called)
|
||||
self.assertFalse(set_mock.called)
|
||||
|
||||
@mock.patch.object(virtual_media.VirtualMedia, 'set_vm_status')
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
def test_set_vm_status_boot_option_connect(self, manager_mock, set_mock):
|
||||
self.rf_client.set_vm_status(device='CDROM', boot_option='CONNECT')
|
||||
self.assertFalse(manager_mock.called)
|
||||
self.assertFalse(set_mock.called)
|
||||
|
|
Loading…
Reference in New Issue