Introduce hpOneView and ilorest to OneView
It introduces the hpOneView and ilorest library to the OneView Driver. This patch will be used as the standard patch to other patches related to the removal of the python-oneviewclient library dependency. Partial-Bug: #1693788 Change-Id: I77a220e8dc7099850aa5edb7a51e19ae486675a9
This commit is contained in:
parent
08173a56af
commit
3a5288a9ad
@ -9,6 +9,8 @@ pysnmp
|
||||
python-ironic-inspector-client>=1.5.0
|
||||
python-oneviewclient<3.0.0,>=2.5.2
|
||||
python-scciclient>=0.5.0
|
||||
python-ilorest-library>=1.9.2
|
||||
hpOneView<4.0.0,>=3.2.1
|
||||
UcsSdk==0.8.2.2
|
||||
python-dracclient>=1.3.0
|
||||
|
||||
|
@ -13,9 +13,9 @@
|
||||
# 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 oslo_log import log as logging
|
||||
from oslo_utils import importutils
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
@ -25,11 +25,18 @@ from ironic.drivers import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# NOTE(mrtenio): hpOneView will be the default library for OneView. It
|
||||
# is being introduced together with the python-oneviewclient to be used
|
||||
# generally by other patches. python-oneviewclient will be removed
|
||||
# subsequently.
|
||||
client = importutils.try_import('oneview_client.client')
|
||||
oneview_utils = importutils.try_import('oneview_client.utils')
|
||||
oneview_states = importutils.try_import('oneview_client.states')
|
||||
oneview_exceptions = importutils.try_import('oneview_client.exceptions')
|
||||
|
||||
hponeview_client = importutils.try_import('hpOneView.oneview_client')
|
||||
redfish = importutils.try_import('redfish')
|
||||
|
||||
REQUIRED_ON_DRIVER_INFO = {
|
||||
'server_hardware_uri': _("Server Hardware URI. Required in driver_info."),
|
||||
}
|
||||
@ -49,6 +56,8 @@ OPTIONAL_ON_PROPERTIES = {
|
||||
"Enclosure Group URI. Optional in properties/capabilities."),
|
||||
}
|
||||
|
||||
ILOREST_BASE_PORT = "443"
|
||||
|
||||
COMMON_PROPERTIES = {}
|
||||
COMMON_PROPERTIES.update(REQUIRED_ON_DRIVER_INFO)
|
||||
COMMON_PROPERTIES.update(REQUIRED_ON_PROPERTIES)
|
||||
@ -83,6 +92,74 @@ def get_oneview_client():
|
||||
return oneview_client
|
||||
|
||||
|
||||
def prepare_manager_url(manager_url):
|
||||
# NOTE(mrtenio) python-oneviewclient uses https or http in the manager_url
|
||||
# while python-hpOneView does not. This will not be necessary when
|
||||
# python-hpOneView client is the only OneView library.
|
||||
if manager_url:
|
||||
url_parse = parse.urlparse(manager_url)
|
||||
manager_url = url_parse.netloc
|
||||
return manager_url
|
||||
|
||||
|
||||
def get_hponeview_client():
|
||||
"""Generate an instance of the hpOneView client.
|
||||
|
||||
Generates an instance of the hpOneView client using the hpOneView library.
|
||||
|
||||
:returns: an instance of the OneViewClient
|
||||
:raises: InvalidParameterValue if mandatory information is missing on the
|
||||
node or on invalid input.
|
||||
"""
|
||||
manager_url = prepare_manager_url(CONF.oneview.manager_url)
|
||||
config = {
|
||||
"ip": manager_url,
|
||||
"credentials": {
|
||||
"userName": CONF.oneview.username,
|
||||
"password": CONF.oneview.password
|
||||
}
|
||||
}
|
||||
return hponeview_client.OneViewClient(config)
|
||||
|
||||
|
||||
def get_ilorest_client(oneview_client, server_hardware):
|
||||
"""Generate an instance of the iLORest library client.
|
||||
|
||||
:param oneview_client: an instance of a python-hpOneView
|
||||
:param: server_hardware: a server hardware uuid or uri
|
||||
:returns: an instance of the iLORest client
|
||||
:raises: InvalidParameterValue if mandatory information is missing on the
|
||||
node or on invalid input.
|
||||
"""
|
||||
remote_console = oneview_client.server_hardware.get_remote_console_url(
|
||||
server_hardware
|
||||
)
|
||||
host_ip, ilo_token = _get_ilo_access(remote_console)
|
||||
base_url = "https://%s:%s" % (host_ip, ILOREST_BASE_PORT)
|
||||
return redfish.rest_client(base_url=base_url, sessionkey=ilo_token)
|
||||
|
||||
|
||||
def _get_ilo_access(remote_console):
|
||||
"""Get the needed information to access ilo.
|
||||
|
||||
Get the host_ip and a token of an iLO remote console instance which can be
|
||||
used to perform operations on that controller.
|
||||
|
||||
The Remote Console url has the following format:
|
||||
hplocons://addr=1.2.3.4&sessionkey=a79659e3b3b7c8209c901ac3509a6719
|
||||
|
||||
:param: remote_console: OneView Remote Console object with a
|
||||
remoteConsoleUrl
|
||||
:returns: A tuple with the Host IP and Token to access ilo, for
|
||||
example: ('1.2.3.4', 'a79659e3b3b7c8209c901ac3509a6719')
|
||||
"""
|
||||
url = remote_console.get('remoteConsoleUrl')
|
||||
url_parse = parse.urlparse(url)
|
||||
host_ip = parse.parse_qs(url_parse.netloc).get('addr')[0]
|
||||
token = parse.parse_qs(url_parse.netloc).get('sessionkey')[0]
|
||||
return host_ip, token
|
||||
|
||||
|
||||
def verify_node_info(node):
|
||||
"""Verifies if fields and namespaces of a node are valid.
|
||||
|
||||
|
@ -25,6 +25,7 @@ from ironic.tests.unit.db import base as db_base
|
||||
from ironic.tests.unit.db import utils as db_utils
|
||||
from ironic.tests.unit.objects import utils as obj_utils
|
||||
|
||||
hponeview_client = importutils.try_import('oneview_client.client')
|
||||
oneview_states = importutils.try_import('oneview_client.states')
|
||||
|
||||
|
||||
@ -58,6 +59,34 @@ class OneViewCommonTestCase(db_base.DbTestCase):
|
||||
"server_hardware_type_uri"):
|
||||
common.verify_node_info(self.node)
|
||||
|
||||
def test_prepare_manager_url(self):
|
||||
self.assertEqual(
|
||||
common.prepare_manager_url("https://1.2.3.4/"), "1.2.3.4")
|
||||
self.assertEqual(
|
||||
common.prepare_manager_url("http://oneview"), "oneview")
|
||||
self.assertEqual(
|
||||
common.prepare_manager_url("http://oneview:8080"), "oneview:8080")
|
||||
self.assertEqual(
|
||||
common.prepare_manager_url("http://oneview/something"), "oneview")
|
||||
self.assertEqual(
|
||||
common.prepare_manager_url("oneview/something"), "")
|
||||
self.assertEqual(
|
||||
common.prepare_manager_url("oneview"), "")
|
||||
|
||||
@mock.patch.object(hponeview_client, 'OneViewClient', spec_set=True,
|
||||
autospec=True)
|
||||
def test_get_hponeview_client(self, mock_hponeview_client):
|
||||
common.get_hponeview_client()
|
||||
mock_hponeview_client.assert_called_once_with(self.config)
|
||||
|
||||
def test_get_ilo_access(self):
|
||||
url = ("hplocons://addr=1.2.3.4&sessionkey" +
|
||||
"=a79659e3b3b7c8209c901ac3509a6719")
|
||||
remote_console = {'remoteConsoleUrl': url}
|
||||
host_ip, token = common._get_ilo_access(remote_console)
|
||||
self.assertEqual(host_ip, "1.2.3.4")
|
||||
self.assertEqual(token, "a79659e3b3b7c8209c901ac3509a6719")
|
||||
|
||||
def test_verify_node_info_missing_node_driver_info(self):
|
||||
self.node.driver_info = {}
|
||||
|
||||
|
@ -31,6 +31,7 @@ class AgentPXEOneViewInspectTestCase(db_base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(AgentPXEOneViewInspectTestCase, self).setUp()
|
||||
self.config(manager_url='https://1.2.3.4', group='oneview')
|
||||
self.config(enabled=True, group='inspector')
|
||||
mgr_utils.mock_the_extension_manager(driver="agent_pxe_oneview")
|
||||
self.node = obj_utils.create_test_node(
|
||||
@ -69,6 +70,7 @@ class ISCSIPXEOneViewInspectTestCase(db_base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ISCSIPXEOneViewInspectTestCase, self).setUp()
|
||||
self.config(manager_url='https://1.2.3.4', group='oneview')
|
||||
self.config(enabled=True, group='inspector')
|
||||
mgr_utils.mock_the_extension_manager(driver="iscsi_pxe_oneview")
|
||||
self.node = obj_utils.create_test_node(
|
||||
|
@ -143,6 +143,24 @@ ONEVIEWCLIENT_STATES_SPEC = (
|
||||
'ONEVIEW_ERROR',
|
||||
)
|
||||
|
||||
HPONEVIEW_SPEC = (
|
||||
'oneview_client',
|
||||
'resources',
|
||||
'exceptions',
|
||||
)
|
||||
|
||||
HPONEVIEW_CLS_SPEC = (
|
||||
)
|
||||
|
||||
HPONEVIEW_STATES_SPEC = (
|
||||
'ONEVIEW_POWER_OFF',
|
||||
'ONEVIEW_POWERING_OFF',
|
||||
'ONEVIEW_POWER_ON',
|
||||
'ONEVIEW_POWERING_ON',
|
||||
'ONEVIEW_RESETTING',
|
||||
'ONEVIEW_ERROR',
|
||||
)
|
||||
|
||||
SUSHY_CONSTANTS_SPEC = (
|
||||
'BOOT_SOURCE_TARGET_PXE',
|
||||
'BOOT_SOURCE_TARGET_HDD',
|
||||
|
@ -26,6 +26,7 @@ Current list of mocked libraries:
|
||||
- pysnmp
|
||||
- scciclient
|
||||
- oneview_client
|
||||
- hpOneView
|
||||
- pywsman
|
||||
- python-dracclient
|
||||
"""
|
||||
@ -99,6 +100,22 @@ if 'ironic.drivers.oneview' in sys.modules:
|
||||
six.moves.reload_module(sys.modules['ironic.drivers.modules.oneview'])
|
||||
|
||||
|
||||
hpOneView = importutils.try_import('hpOneView')
|
||||
if not hpOneView:
|
||||
hpOneView = mock.MagicMock(spec_set=mock_specs.HPONEVIEW_SPEC)
|
||||
sys.modules['hpOneView'] = hpOneView
|
||||
sys.modules['hpOneView.oneview_client'] = hpOneView.oneview_client
|
||||
sys.modules['hpOneView.resources'] = hpOneView.resources
|
||||
sys.modules['hpOneView.exceptions'] = hpOneView.exceptions
|
||||
hpOneView.exceptions.HPOneViewException = type('HPOneViewException',
|
||||
(Exception,), {})
|
||||
sys.modules['hpOneView.oneview_client'].OneViewClient = mock.MagicMock(
|
||||
spec_set=mock_specs.HPONEVIEW_CLS_SPEC
|
||||
)
|
||||
if 'ironic.drivers.oneview' in sys.modules:
|
||||
six.moves.reload_module(sys.modules['ironic.drivers.modules.oneview'])
|
||||
|
||||
|
||||
# attempt to load the external 'python-dracclient' library, which is required
|
||||
# by the optional drivers.modules.drac module
|
||||
dracclient = importutils.try_import('dracclient')
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
Adds the ``hpOneView`` and ``ilorest`` library requirement
|
||||
to the OneView Driver, in order to prepare for the eventual
|
||||
removal of dependency on ``python-oneviewclient`` library.
|
Loading…
Reference in New Issue
Block a user