Add Support testing for HttpBootUri
Maps the HttpBootUri to the virtual media functionality, so we can leverage sushy-tools for testing HttpBootUri functionality. Change-Id: I51a7e684bafdb6b3aa9adda35ae438c747c9847a
This commit is contained in:
parent
0246649c06
commit
e14cfe361d
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds support to handle ``HttpBootUri`` being posted to the node, which
|
||||
maps to the virtual media functionality, because there is not a direct
|
||||
analog setting when interacting with libvirt.
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds basic functionality for ``HttpBootUri`` to be passed through to
|
||||
the libvirt driver, enabling boot operations utilizing supplied media.
|
||||
This does not influence the default URL to boot from due to a lack of
|
||||
capability in libvirt, but instead treats it similar to virtual media.
|
||||
In this case, an override boot target of ``UefiHttp`` is also re-mapped
|
||||
to ``Cd`` to facilitate testing.
|
@ -392,7 +392,8 @@ def system_resource(identity):
|
||||
managers=app.managers.get_managers_for_system(identity),
|
||||
chassis=app.chassis.chassis[:1],
|
||||
indicator_led=app.indicators.get_indicator_state(
|
||||
app.systems.uuid(identity))
|
||||
app.systems.uuid(identity)),
|
||||
http_boot_uri=try_get(app.systems.get_http_boot_uri)
|
||||
)
|
||||
|
||||
elif flask.request.method == 'PATCH':
|
||||
@ -405,6 +406,12 @@ def system_resource(identity):
|
||||
if boot:
|
||||
target = boot.get('BootSourceOverrideTarget')
|
||||
|
||||
if target == 'UefiHttp':
|
||||
# Reset to Cd, in our case, since we can't force override
|
||||
# the network boot to a specific URL. This is sort of a hack
|
||||
# but testing functionality overall is a bit more important.
|
||||
target = 'Cd'
|
||||
|
||||
if target:
|
||||
# NOTE(lucasagomes): In libvirt we always set the boot
|
||||
# device frequency to "continuous" so, we are ignoring the
|
||||
@ -423,9 +430,30 @@ def system_resource(identity):
|
||||
app.logger.info('Set boot mode to "%s" for system "%s"',
|
||||
mode, identity)
|
||||
|
||||
if not target and not mode:
|
||||
http_uri = boot.get('HttpBootUri')
|
||||
|
||||
if http_uri:
|
||||
|
||||
try:
|
||||
# Download the image
|
||||
image_path = flask.current_app.vmedia.insert_image(
|
||||
identity, 'Cd', http_uri)
|
||||
# Mount it as an ISO
|
||||
flask.current_app.systems.set_boot_image(
|
||||
'Cd', boot_image=image_path,
|
||||
write_protected=True)
|
||||
# Set it for our emulator's API surface to return it
|
||||
# if queried.
|
||||
flask.current_app.systems.set_http_boot_uri(http_uri)
|
||||
except Exception as e:
|
||||
app.logger.error('Unable to load HttpBootUri for boot '
|
||||
'operation. Error: %s', e)
|
||||
return '', 400
|
||||
|
||||
if not target and not mode and not http_uri:
|
||||
return ('Missing the BootSourceOverrideTarget and/or '
|
||||
'BootSourceOverrideMode element', 400)
|
||||
'BootSourceOverrideMode and/or HttpBootUri '
|
||||
'element', 400)
|
||||
|
||||
if indicator_led_state:
|
||||
app.indicators.set_indicator_state(
|
||||
|
@ -233,3 +233,21 @@ class AbstractSystemsDriver(metaclass=abc.ABCMeta):
|
||||
:returns: Id of the volume if successfully found/created else None
|
||||
"""
|
||||
raise error.NotSupportedError('Not implemented')
|
||||
|
||||
def get_http_boot_uri(self, identity):
|
||||
"""Return the URI stored for the HttpBootUri.
|
||||
|
||||
:param identity: The libvirt identity. Unused, exists for internal
|
||||
sushy-tools compatability.
|
||||
:returns: Stored URI value for HttpBootURI.
|
||||
"""
|
||||
raise error.NotSupportedError('Not implemented')
|
||||
|
||||
def set_http_boot_uri(self, uri):
|
||||
"""Stores the Uri for HttpBootURI.
|
||||
|
||||
:param uri: String to return
|
||||
|
||||
:returns: None
|
||||
"""
|
||||
raise error.NotSupportedError('Not implemented')
|
||||
|
@ -172,6 +172,7 @@ class LibvirtDriver(AbstractSystemsDriver):
|
||||
cls.SECURE_BOOT_DISABLED_NVRAM)
|
||||
cls.SUSHY_EMULATOR_IGNORE_BOOT_DEVICE = \
|
||||
cls._config.get('SUSHY_EMULATOR_IGNORE_BOOT_DEVICE', False)
|
||||
cls._http_boot_uri = None
|
||||
return cls
|
||||
|
||||
@memoize.memoize()
|
||||
@ -1353,3 +1354,21 @@ class LibvirtDriver(AbstractSystemsDriver):
|
||||
self._logger.debug(msg)
|
||||
return
|
||||
return data['Id']
|
||||
|
||||
def get_http_boot_uri(self, identity):
|
||||
"""Return the URI stored for the HttpBootUri.
|
||||
|
||||
:param identity: The libvirt identity. Unused, exists for internal
|
||||
sushy-tools compatability.
|
||||
:returns: Stored URI value for HttpBootURI.
|
||||
"""
|
||||
return self._http_boot_uri
|
||||
|
||||
def set_http_boot_uri(self, uri):
|
||||
"""Stores the Uri for HttpBootURI.
|
||||
|
||||
:param uri: String to return
|
||||
|
||||
:returns: None
|
||||
"""
|
||||
self._http_boot_uri = uri
|
||||
|
@ -19,16 +19,21 @@
|
||||
"BootSourceOverrideTarget@Redfish.AllowableValues": [
|
||||
"Pxe",
|
||||
"Cd",
|
||||
"Hdd"
|
||||
{%- if boot_source_mode %}
|
||||
],
|
||||
{%- if 'uefi' in boot_source_mode.lower() %}
|
||||
"Hdd",
|
||||
"UefiHttp"
|
||||
],
|
||||
"BootSourceOverrideMode": {{ boot_source_mode|string|tojson }},
|
||||
"UefiTargetBootSourceOverride": "/0x31/0x33/0x01/0x01"
|
||||
"UefiTargetBootSourceOverride": "/0x31/0x33/0x01/0x01",
|
||||
"HttpBootUri": {{ http_boot_uri|string|tojson }}
|
||||
{%- else %}
|
||||
"Hdd"
|
||||
],
|
||||
"BootSourceOverrideMode": {{ boot_source_mode|string|tojson }}
|
||||
{%- endif %}
|
||||
{%- else %}
|
||||
"Hdd"
|
||||
]
|
||||
{%- endif %}
|
||||
{%- else %}
|
||||
|
@ -1245,3 +1245,17 @@ class LibvirtDriverTestCase(base.BaseTestCase):
|
||||
|
||||
self.assertRaises(error.NotSupportedError,
|
||||
self.test_driver.set_secure_boot, self.uuid, True)
|
||||
|
||||
@mock.patch('libvirt.open', autospec=True)
|
||||
@mock.patch('libvirt.openReadOnly', autospec=True)
|
||||
def test_set_get_http_boot_uri(self, libvirt_mock, libvirt_rw_mock):
|
||||
with open('sushy_tools/tests/unit/emulator/domain-q35.xml', 'r') as f:
|
||||
data = f.read()
|
||||
|
||||
conn_mock = libvirt_mock.return_value
|
||||
domain_mock = conn_mock.lookupByUUID.return_value
|
||||
domain_mock.XMLDesc.return_value = data
|
||||
self.assertIsNone(self.test_driver.get_http_boot_uri(None))
|
||||
uri = 'http://host.path/meow'
|
||||
self.test_driver.set_http_boot_uri(uri)
|
||||
self.assertEqual(uri, self.test_driver.get_http_boot_uri(None))
|
||||
|
@ -287,3 +287,11 @@ class NovaDriverTestCase(base.BaseTestCase):
|
||||
self.assertRaises(
|
||||
error.NotSupportedError, self.test_driver.set_secure_boot,
|
||||
self.uuid, True)
|
||||
|
||||
def test_set_get_http_boot_uri(self):
|
||||
self.assertRaises(error.NotSupportedError,
|
||||
self.test_driver.get_http_boot_uri,
|
||||
None)
|
||||
self.assertRaises(error.NotSupportedError,
|
||||
self.test_driver.set_http_boot_uri,
|
||||
None)
|
||||
|
@ -273,6 +273,29 @@ class SystemsTestCase(EmulatorTestCase):
|
||||
set_boot_device = systems_mock.return_value.set_boot_device
|
||||
set_boot_device.assert_called_once_with('xxxx-yyyy-zzzz', 'Cd')
|
||||
|
||||
@patch_resource('vmedia')
|
||||
@patch_resource('systems')
|
||||
def test_system_boot_http_uri(self, systems_mock, vmedia_mock):
|
||||
data = {'Boot': {'BootSourceOverrideMode': 'UEFI',
|
||||
'BootSourceOverrideTarget': 'UefiHttp',
|
||||
'HttpBootUri': 'http://test.url/boot.iso'}}
|
||||
insert_image = vmedia_mock.return_value.insert_image
|
||||
insert_image.return_value = '/path/to/file.iso'
|
||||
response = self.app.patch('/redfish/v1/Systems/xxxx-yyyy-zzzz',
|
||||
json=data)
|
||||
self.assertEqual(204, response.status_code)
|
||||
insert_image.assert_called_once_with('xxxx-yyyy-zzzz', 'Cd',
|
||||
'http://test.url/boot.iso')
|
||||
set_boot_device = systems_mock.return_value.set_boot_device
|
||||
set_boot_image = systems_mock.return_value.set_boot_image
|
||||
set_boot_mode = systems_mock.return_value.set_boot_mode
|
||||
set_http_boot_uri = systems_mock.return_value.set_http_boot_uri
|
||||
set_boot_device.assert_called_once_with('xxxx-yyyy-zzzz', 'Cd')
|
||||
set_boot_image.assert_called_once_with(
|
||||
'Cd', boot_image='/path/to/file.iso', write_protected=True)
|
||||
set_boot_mode.assert_called_once_with('xxxx-yyyy-zzzz', 'UEFI')
|
||||
set_http_boot_uri.assert_called_once_with('http://test.url/boot.iso')
|
||||
|
||||
@patch_resource('systems')
|
||||
def test_system_reset_action(self, systems_mock):
|
||||
set_power_state = systems_mock.return_value.set_power_state
|
||||
|
Loading…
Reference in New Issue
Block a user