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:
Hugo Nicodemos 2017-06-29 16:53:47 -03:00 committed by Fellype Cavalcante
parent 08173a56af
commit 3a5288a9ad
7 changed files with 152 additions and 1 deletions

View File

@ -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

View File

@ -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.

View File

@ -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 = {}

View File

@ -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(

View File

@ -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',

View File

@ -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')

View File

@ -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.