Merge "Added support for IPv6 network"
This commit is contained in:
commit
8a79e04ace
|
@ -13,6 +13,7 @@
|
|||
# under the License.
|
||||
"""IloClient module"""
|
||||
|
||||
import netaddr
|
||||
from proliantutils import exception
|
||||
from proliantutils.ilo import ipmi
|
||||
from proliantutils.ilo import operations
|
||||
|
@ -125,9 +126,18 @@ class IloClient(operations.IloOperations):
|
|||
def __init__(self, host, login, password, timeout=60, port=443,
|
||||
bios_password=None, cacert=None, snmp_credentials=None,
|
||||
use_redfish_only=False):
|
||||
|
||||
# IPv6 Check
|
||||
# TODO(paresh) Need to test with Global IPv6 address
|
||||
# IPMI supports IPv6 without square brackets
|
||||
self.ipmi_host_info = {'address': host, 'username': login,
|
||||
'password': password}
|
||||
|
||||
if netaddr.valid_ipv6(host.split('%')[0]):
|
||||
host = '[' + host + ']'
|
||||
|
||||
self.ribcl = ribcl.RIBCLOperations(host, login, password, timeout,
|
||||
port, cacert=cacert)
|
||||
self.info = {'address': host, 'username': login, 'password': password}
|
||||
self.host = host
|
||||
self.use_redfish_only = use_redfish_only
|
||||
|
||||
|
@ -640,7 +650,8 @@ class IloClient(operations.IloOperations):
|
|||
# NOTE(vmud213): Even if it is None, pass it on to get_nic_capacity
|
||||
# as we still want to try getting nic capacity through ipmitool
|
||||
# irrespective of what firmware we are using.
|
||||
nic_capacity = ipmi.get_nic_capacity(self.info, major_minor)
|
||||
nic_capacity = ipmi.get_nic_capacity(self.ipmi_host_info,
|
||||
major_minor)
|
||||
if nic_capacity:
|
||||
capabilities.update({'nic_capacity': nic_capacity})
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class IloOperations(object):
|
|||
def _(self, msg):
|
||||
"""Prepends host information if available to msg and returns it."""
|
||||
try:
|
||||
return "[iLO %s] %s" % (self.host, msg)
|
||||
return "[iLO %s] %s" % (self.host.replace('%', '%%'), msg)
|
||||
except AttributeError:
|
||||
return "[iLO <unknown>] %s" % msg
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
__author__ = 'HPE'
|
||||
|
||||
import retrying
|
||||
from six.moves.urllib.parse import urlparse
|
||||
from sushy import connector
|
||||
from sushy import exceptions
|
||||
|
||||
|
@ -44,4 +45,11 @@ class HPEConnector(connector.Connector):
|
|||
:param headers: Optional dictionary of headers.
|
||||
:returns: The response from the connector.Connector's _op method.
|
||||
"""
|
||||
return super(HPEConnector, self)._op(method, path, data, headers)
|
||||
resp = super(HPEConnector, self)._op(method, path, data,
|
||||
headers, allow_redirects=False)
|
||||
# With IPv6, Gen10 server gives redirection response with new path with
|
||||
# a prefix of '/' so this check is required
|
||||
if resp.status_code == 308:
|
||||
path = urlparse(resp.headers['Location']).path
|
||||
resp = super(HPEConnector, self)._op(method, path, data, headers)
|
||||
return resp
|
||||
|
|
|
@ -47,7 +47,57 @@ class IloClientInitTestCase(testtools.TestCase):
|
|||
"1.2.3.4", "admin", "Admin", 120, 4430, cacert='/somewhere')
|
||||
self.assertEqual(
|
||||
{'address': "1.2.3.4", 'username': "admin", 'password': "Admin"},
|
||||
c.info)
|
||||
c.ipmi_host_info)
|
||||
self.assertEqual('product', c.model)
|
||||
|
||||
@mock.patch.object(ribcl, 'RIBCLOperations')
|
||||
@mock.patch.object(ris, 'RISOperations')
|
||||
def test_init_for_ipv6_link_address(self, ris_mock, ribcl_mock):
|
||||
ribcl_obj_mock = mock.MagicMock()
|
||||
ribcl_mock.return_value = ribcl_obj_mock
|
||||
ribcl_obj_mock.get_product_name.return_value = 'product'
|
||||
|
||||
c = client.IloClient("FE80::9AF2:B3FF:FEEE:F884%eth0", "admin",
|
||||
"Admin", timeout=120, port=4430,
|
||||
bios_password='foo',
|
||||
cacert='/somewhere')
|
||||
|
||||
ris_mock.assert_called_once_with(
|
||||
"[FE80::9AF2:B3FF:FEEE:F884%eth0]",
|
||||
"admin", "Admin", bios_password='foo',
|
||||
cacert='/somewhere')
|
||||
ribcl_mock.assert_called_once_with(
|
||||
"[FE80::9AF2:B3FF:FEEE:F884%eth0]",
|
||||
"admin", "Admin", 120, 4430, cacert='/somewhere')
|
||||
self.assertEqual(
|
||||
{'address': "FE80::9AF2:B3FF:FEEE:F884%eth0",
|
||||
'username': "admin", 'password': "Admin"},
|
||||
c.ipmi_host_info)
|
||||
self.assertEqual('product', c.model)
|
||||
|
||||
@mock.patch.object(ribcl, 'RIBCLOperations')
|
||||
@mock.patch.object(ris, 'RISOperations')
|
||||
def test_init_for_ipv6_global_address(self, ris_mock, ribcl_mock):
|
||||
ribcl_obj_mock = mock.MagicMock()
|
||||
ribcl_mock.return_value = ribcl_obj_mock
|
||||
ribcl_obj_mock.get_product_name.return_value = 'product'
|
||||
|
||||
c = client.IloClient("2001:0db8:85a3::8a2e:0370:7334", "admin",
|
||||
"Admin", timeout=120, port=4430,
|
||||
bios_password='foo',
|
||||
cacert='/somewhere')
|
||||
|
||||
ris_mock.assert_called_once_with(
|
||||
"[2001:0db8:85a3::8a2e:0370:7334]",
|
||||
"admin", "Admin", bios_password='foo',
|
||||
cacert='/somewhere')
|
||||
ribcl_mock.assert_called_once_with(
|
||||
"[2001:0db8:85a3::8a2e:0370:7334]",
|
||||
"admin", "Admin", 120, 4430, cacert='/somewhere')
|
||||
self.assertEqual(
|
||||
{'address': "2001:0db8:85a3::8a2e:0370:7334",
|
||||
'username': "admin", 'password': "Admin"},
|
||||
c.ipmi_host_info)
|
||||
self.assertEqual('product', c.model)
|
||||
|
||||
@mock.patch.object(ribcl, 'RIBCLOperations')
|
||||
|
@ -70,7 +120,7 @@ class IloClientInitTestCase(testtools.TestCase):
|
|||
cacert='/somewhere')
|
||||
self.assertEqual(
|
||||
{'address': "1.2.3.4", 'username': "admin", 'password': "Admin"},
|
||||
c.info)
|
||||
c.ipmi_host_info)
|
||||
self.assertEqual('ProLiant DL180 Gen10', c.model)
|
||||
self.assertIsNotNone(c.redfish)
|
||||
self.assertTrue(c.is_ribcl_enabled)
|
||||
|
@ -97,7 +147,7 @@ class IloClientInitTestCase(testtools.TestCase):
|
|||
cacert='/somewhere')
|
||||
self.assertEqual(
|
||||
{'address': "1.2.3.4", 'username': "admin", 'password': "Admin"},
|
||||
c.info)
|
||||
c.ipmi_host_info)
|
||||
self.assertIsNotNone(c.model)
|
||||
self.assertIsNotNone(c.redfish)
|
||||
self.assertFalse(c.is_ribcl_enabled)
|
||||
|
@ -119,7 +169,7 @@ class IloClientInitTestCase(testtools.TestCase):
|
|||
cacert='/somewhere')
|
||||
self.assertEqual(
|
||||
{'address': "1.2.3.4", 'username': "admin", 'password': "Admin"},
|
||||
c.info)
|
||||
c.ipmi_host_info)
|
||||
self.assertIsNotNone(c.model)
|
||||
self.assertIsNotNone(c.redfish)
|
||||
self.assertIsNone(c.is_ribcl_enabled)
|
||||
|
@ -152,7 +202,7 @@ class IloClientInitTestCase(testtools.TestCase):
|
|||
"1.2.3.4", "admin", "Admin", 120, 4430, cacert='/somewhere')
|
||||
self.assertEqual(
|
||||
{'address': "1.2.3.4", 'username': "admin", 'password': "Admin"},
|
||||
c.info)
|
||||
c.ipmi_host_info)
|
||||
self.assertEqual('product', c.model)
|
||||
self.assertTrue(snmp_mock.called)
|
||||
|
||||
|
@ -599,9 +649,9 @@ class IloClientTestCase(testtools.TestCase):
|
|||
'pci_gpu_devices': '2',
|
||||
'nic_capacity': '10Gb'}
|
||||
cap_mock.assert_called_once_with()
|
||||
nic_mock.assert_called_once_with(self.client.info, str_val)
|
||||
nic_mock.assert_called_once_with(self.client.ipmi_host_info, str_val)
|
||||
self.assertEqual(expected_capabilities, capabilities)
|
||||
self.assertEqual(info, self.client.info)
|
||||
self.assertEqual(info, self.client.ipmi_host_info)
|
||||
|
||||
@mock.patch.object(ipmi, 'get_nic_capacity')
|
||||
@mock.patch.object(ribcl.RIBCLOperations,
|
||||
|
@ -622,9 +672,9 @@ class IloClientTestCase(testtools.TestCase):
|
|||
'server_model': 'Gen8',
|
||||
'pci_gpu_devices': '2'}
|
||||
cap_mock.assert_called_once_with()
|
||||
nic_mock.assert_called_once_with(self.client.info, str_val)
|
||||
nic_mock.assert_called_once_with(self.client.ipmi_host_info, str_val)
|
||||
self.assertEqual(expected_capabilities, capabilities)
|
||||
self.assertEqual(info, self.client.info)
|
||||
self.assertEqual(info, self.client.ipmi_host_info)
|
||||
|
||||
@mock.patch.object(ipmi, 'get_nic_capacity')
|
||||
@mock.patch.object(ribcl.RIBCLOperations,
|
||||
|
@ -642,7 +692,7 @@ class IloClientTestCase(testtools.TestCase):
|
|||
'pci_gpu_devices': '2'}
|
||||
capabilities = self.client.get_server_capabilities()
|
||||
self.assertEqual(expected_capabilities, capabilities)
|
||||
nic_mock.assert_called_once_with(self.client.info, None)
|
||||
nic_mock.assert_called_once_with(self.client.ipmi_host_info, None)
|
||||
|
||||
@mock.patch.object(ipmi, 'get_nic_capacity')
|
||||
@mock.patch.object(ribcl.RIBCLOperations,
|
||||
|
@ -660,7 +710,7 @@ class IloClientTestCase(testtools.TestCase):
|
|||
'pci_gpu_devices': '2'}
|
||||
capabilities = self.client.get_server_capabilities()
|
||||
self.assertEqual(expected_capabilities, capabilities)
|
||||
nic_mock.assert_called_once_with(self.client.info, None)
|
||||
nic_mock.assert_called_once_with(self.client.ipmi_host_info, None)
|
||||
|
||||
@mock.patch.object(ris.RISOperations,
|
||||
'get_ilo_firmware_version_as_major_minor')
|
||||
|
@ -679,7 +729,7 @@ class IloClientTestCase(testtools.TestCase):
|
|||
'secure_boot': 'true'}
|
||||
capabilities = self.client.get_server_capabilities()
|
||||
cap_mock.assert_called_once_with()
|
||||
nic_mock.assert_called_once_with(self.client.info, str_val)
|
||||
nic_mock.assert_called_once_with(self.client.ipmi_host_info, str_val)
|
||||
expected_capabilities = {'ilo_firmware_version': '2.10',
|
||||
'rom_firmware_version': 'x',
|
||||
'server_model': 'Gen9',
|
||||
|
@ -702,7 +752,7 @@ class IloClientTestCase(testtools.TestCase):
|
|||
'secure_boot': 'true'}
|
||||
capabilities = self.client.get_server_capabilities()
|
||||
cap_mock.assert_called_once_with()
|
||||
nic_mock.assert_called_once_with(self.client.info, str_val)
|
||||
nic_mock.assert_called_once_with(self.client.ipmi_host_info, str_val)
|
||||
expected_capabilities = {'ilo_firmware_version': '2.10',
|
||||
'rom_firmware_version': 'x',
|
||||
'server_model': 'Gen9',
|
||||
|
@ -744,7 +794,7 @@ class IloClientTestCase(testtools.TestCase):
|
|||
'secure_boot': 'true'}
|
||||
capabilities = self.client.get_server_capabilities()
|
||||
cap_mock.assert_called_once_with()
|
||||
nic_mock.assert_called_once_with(self.client.info, str_val)
|
||||
nic_mock.assert_called_once_with(self.client.ipmi_host_info, str_val)
|
||||
expected_capabilities = {'ilo_firmware_version': '2.10',
|
||||
'rom_firmware_version': 'x',
|
||||
'server_model': 'Gen9',
|
||||
|
@ -1087,8 +1137,8 @@ class IloClientTestCase(testtools.TestCase):
|
|||
snmp_mock.return_value = 250
|
||||
self.client.get_essential_properties()
|
||||
call_mock.assert_called_once_with('get_essential_properties')
|
||||
snmp_mock.assert_called_once_with(self.client.info['address'],
|
||||
snmp_credentials)
|
||||
snmp_mock.assert_called_once_with(
|
||||
self.client.ipmi_host_info['address'], snmp_credentials)
|
||||
self.assertTrue(mac_mock.called)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, 'get_active_macs')
|
||||
|
@ -1112,8 +1162,8 @@ class IloClientTestCase(testtools.TestCase):
|
|||
snmp_mock.return_value = 0
|
||||
self.client.get_essential_properties()
|
||||
call_mock.assert_called_once_with('get_essential_properties')
|
||||
snmp_mock.assert_called_once_with(self.client.info['address'],
|
||||
snmp_credentials)
|
||||
snmp_mock.assert_called_once_with(
|
||||
self.client.ipmi_host_info['address'], snmp_credentials)
|
||||
self.assertTrue(mac_mock.called)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, 'get_active_macs')
|
||||
|
|
|
@ -33,3 +33,8 @@ class IloOperationsTestCase(unittest.TestCase):
|
|||
def test__no_host(self):
|
||||
self.assertEqual('[iLO <unknown>] foo',
|
||||
self.operations_object._('foo'))
|
||||
|
||||
def test__ipv6_host(self):
|
||||
self.operations_object.host = 'FE80::9EB6:54FF:FEB1:ACEE%ens37'
|
||||
self.assertEqual('[iLO FE80::9EB6:54FF:FEB1:ACEE%%ens37] foo',
|
||||
self.operations_object._('foo'))
|
||||
|
|
|
@ -28,29 +28,33 @@ class HPEConnectorTestCase(testtools.TestCase):
|
|||
|
||||
@mock.patch.object(connector.Connector, '_op', autospec=True)
|
||||
def test__op_no_exception(self, conn_mock):
|
||||
conn_mock.side_effect = ["Hello", exceptions.ConnectionError,
|
||||
"Hello", "World"]
|
||||
|
||||
response = mock.MagicMock()
|
||||
type(response).status_code = mock.PropertyMock(return_value=200)
|
||||
conn_mock.side_effect = [response, exceptions.ConnectionError,
|
||||
response, response]
|
||||
hpe_conn = hpe_connector.HPEConnector(
|
||||
'http://foo.bar:1234', verify=True)
|
||||
headers = {'X-Fake': 'header'}
|
||||
hpe_conn._op('GET', path='fake/path', data=None, headers=headers)
|
||||
conn_mock.assert_called_once_with(hpe_conn, 'GET', path='fake/path',
|
||||
data=None, headers=headers)
|
||||
data=None, headers=headers,
|
||||
allow_redirects=False)
|
||||
self.assertEqual(1, conn_mock.call_count)
|
||||
|
||||
@mock.patch.object(connector.Connector, '_op', autospec=True)
|
||||
def test__op_with_exception(self, conn_mock):
|
||||
response = mock.MagicMock()
|
||||
type(response).status_code = mock.PropertyMock(return_value=501)
|
||||
conn_mock.side_effect = [exceptions.ConnectionError,
|
||||
exceptions.ConnectionError, "Hello", "World"]
|
||||
|
||||
exceptions.ConnectionError,
|
||||
response, response]
|
||||
hpe_conn = hpe_connector.HPEConnector(
|
||||
'http://foo.bar:1234', verify=True)
|
||||
headers = {'X-Fake': 'header'}
|
||||
lval = hpe_conn._op('GET', path='fake/path', data=None,
|
||||
headers=headers)
|
||||
self.assertEqual(3, conn_mock.call_count)
|
||||
self.assertEqual(lval, "Hello")
|
||||
self.assertEqual(lval.status_code, 501)
|
||||
|
||||
@mock.patch.object(connector.Connector, '_op', autospec=True)
|
||||
def test__op_all_exception(self, conn_mock):
|
||||
|
@ -58,7 +62,6 @@ class HPEConnectorTestCase(testtools.TestCase):
|
|||
exceptions.ConnectionError] * (
|
||||
hpe_connector.HPEConnector.MAX_RETRY_ATTEMPTS) + (
|
||||
["Hello", "World"])
|
||||
|
||||
hpe_conn = hpe_connector.HPEConnector(
|
||||
'http://foo.bar:1234', verify=True)
|
||||
headers = {'X-Fake': 'header'}
|
||||
|
@ -67,3 +70,26 @@ class HPEConnectorTestCase(testtools.TestCase):
|
|||
'GET', path='fake/path', data=None, headers=headers)
|
||||
self.assertEqual(hpe_connector.HPEConnector.MAX_RETRY_ATTEMPTS,
|
||||
conn_mock.call_count)
|
||||
|
||||
@mock.patch.object(connector.Connector, '_op', autospec=True)
|
||||
def test__op_with_redirection_false_status_308(self, conn_mock):
|
||||
response = mock.MagicMock()
|
||||
type(response).status_code = mock.PropertyMock(return_value=308)
|
||||
headers = {'X-Fake': 'header',
|
||||
'Location': 'http://foo.bar:1234/new/path'}
|
||||
type(response).headers = headers
|
||||
response_redirect = mock.MagicMock()
|
||||
type(response_redirect).status_code = (
|
||||
mock.PropertyMock(return_value=200))
|
||||
conn_mock.side_effect = [response, response_redirect]
|
||||
hpe_conn = hpe_connector.HPEConnector(
|
||||
'http://foo.bar:1234', verify=True)
|
||||
headers = {'X-Fake': 'header'}
|
||||
res = hpe_conn._op('GET', path='fake/path',
|
||||
data=None, headers=headers)
|
||||
calls = [mock.call(hpe_conn, 'GET', path='fake/path', data=None,
|
||||
headers=headers, allow_redirects=False),
|
||||
mock.call(hpe_conn, 'GET', path='/new/path', data=None,
|
||||
headers=headers)]
|
||||
conn_mock.assert_has_calls(calls)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
|
|
Loading…
Reference in New Issue