Merge "Add serial number to eseries ASUP payload"

This commit is contained in:
Jenkins
2015-12-21 20:17:55 +00:00
committed by Gerrit Code Review
5 changed files with 106 additions and 76 deletions

View File

@@ -595,6 +595,8 @@ VOLUME_MAPPING_TO_MULTIATTACH_GROUP.update(
)
STORAGE_SYSTEM = {
'chassisSerialNumber': 1,
'fwVersion': '08.10.15.00',
'freePoolSpace': 11142431623168,
'driveCount': 24,
'hostSparesUsed': 0, 'id':
@@ -667,7 +669,26 @@ SNAPSHOT_IMAGE = {
'pitSequenceNumber': '19'
}
HARDWARE_INVENTORY_SINGLE_CONTROLLER = {
'controllers': [
{
'modelName': '2752',
'serialNumber': '021436001321'
}
]
}
HARDWARE_INVENTORY = {
'controllers': [
{
'modelName': '2752',
'serialNumber': '021436000943'
},
{
'modelName': '2752',
'serialNumber': '021436001321'
}
],
'iscsiPorts': [
{
'controllerId':
@@ -806,7 +827,6 @@ FAKE_POOL_ACTION_PROGRESS = [
},
]
FAKE_RESOURCE_URL = '/devmgr/v2/devmgr/utils/about'
FAKE_APP_VERSION = '2015.2|2015.2.dev59|vendor|Linux-3.13.0-24-generic'
FAKE_BACKEND = 'eseriesiSCSI'
@@ -840,8 +860,17 @@ FAKE_ASUP_DATA = {
'model': FAKE_CONTROLLERS[0]['modelName'],
'controller2-serial': FAKE_CONTROLLERS[1]['serialNumber'],
'controller1-serial': FAKE_CONTROLLERS[0]['serialNumber'],
'chassis-serial-number': FAKE_SERIAL_NUMBER[0],
'operating-mode': 'proxy',
}
GET_ASUP_RETURN = {
'model': FAKE_CONTROLLERS[0]['modelName'],
'serial_numbers': FAKE_SERIAL_NUMBERS,
'firmware_version': FAKE_ASUP_DATA['system-version'],
'chassis_sn': FAKE_ASUP_DATA['chassis-serial-number'],
}
FAKE_POST_INVOKE_DATA = ('POST', '/key-values/%s' % FAKE_KEY,
json.dumps(FAKE_ASUP_DATA))

View File

@@ -27,7 +27,6 @@ from cinder.tests.unit.volume.drivers.netapp.eseries import fakes as \
eseries_fake
from cinder.volume.drivers.netapp.eseries import exception as es_exception
from cinder.volume.drivers.netapp.eseries import client
from cinder.volume.drivers.netapp import utils as na_utils
@@ -359,16 +358,8 @@ class NetAppEseriesClientDriverTestCase(test.TestCase):
eseries_fake.FAKE_ASUP_DATA['operating-mode'],
eseries_fake.FAKE_ABOUT_RESPONSE['version'])))
self.mock_object(
self.my_client, 'get_firmware_version',
mock.Mock(
return_value=eseries_fake.FAKE_ABOUT_RESPONSE['version']))
self.mock_object(
self.my_client, 'get_serial_numbers',
mock.Mock(return_value=eseries_fake.FAKE_SERIAL_NUMBERS))
self.mock_object(
self.my_client, 'get_model_name',
mock.Mock(
return_value=eseries_fake.FAKE_CONTROLLERS[0]['modelName']))
self.my_client, 'get_asup_info',
mock.Mock(return_value=eseries_fake.GET_ASUP_RETURN))
self.mock_object(
self.my_client, 'set_counter',
mock.Mock(return_value={'value': 1}))
@@ -385,38 +376,48 @@ class NetAppEseriesClientDriverTestCase(test.TestCase):
mock_invoke.assert_called_with(*eseries_fake.FAKE_POST_INVOKE_DATA)
@ddt.data((eseries_fake.FAKE_SERIAL_NUMBERS,
eseries_fake.FAKE_CONTROLLERS),
(eseries_fake.FAKE_DEFAULT_SERIAL_NUMBER, []),
eseries_fake.HARDWARE_INVENTORY),
(eseries_fake.FAKE_DEFAULT_SERIAL_NUMBER, {}),
(eseries_fake.FAKE_SERIAL_NUMBER,
eseries_fake.FAKE_SINGLE_CONTROLLER))
eseries_fake.HARDWARE_INVENTORY_SINGLE_CONTROLLER))
@ddt.unpack
def test_get_serial_numbers(self, expected_serial_numbers, controllers):
def test_get_asup_info_serial_numbers(self, expected_serial_numbers,
controllers):
self.mock_object(
client.RestClient, '_get_controllers',
client.RestClient, 'list_hardware_inventory',
mock.Mock(return_value=controllers))
serial_numbers = client.RestClient.get_serial_numbers(self.my_client)
self.assertEqual(expected_serial_numbers, serial_numbers)
def test_get_model_name(self):
self.mock_object(
client.RestClient, '_get_controllers',
mock.Mock(return_value=eseries_fake.FAKE_CONTROLLERS))
client.RestClient, 'list_storage_system',
mock.Mock(return_value={}))
model = client.RestClient.get_model_name(self.my_client)
sn = client.RestClient.get_asup_info(self.my_client)['serial_numbers']
self.assertEqual(eseries_fake.FAKE_CONTROLLERS[0]['modelName'],
model)
self.assertEqual(expected_serial_numbers, sn)
def test_get_model_name_empty_controllers_list(self):
def test_get_asup_info_model_name(self):
self.mock_object(
client.RestClient, '_get_controllers',
mock.Mock(return_value=[]))
client.RestClient, 'list_hardware_inventory',
mock.Mock(return_value=eseries_fake.HARDWARE_INVENTORY))
self.mock_object(
client.RestClient, 'list_storage_system',
mock.Mock(return_value=eseries_fake.STORAGE_SYSTEM))
model = client.RestClient.get_model_name(self.my_client)
model_name = client.RestClient.get_asup_info(self.my_client)['model']
self.assertEqual(eseries_fake.FAKE_DEFAULT_MODEL, model)
self.assertEqual(eseries_fake.HARDWARE_INVENTORY['controllers'][0]
['modelName'], model_name)
def test_get_asup_info_model_name_empty_controllers_list(self):
self.mock_object(
client.RestClient, 'list_hardware_inventory',
mock.Mock(return_value={}))
self.mock_object(
client.RestClient, 'list_storage_system',
mock.Mock(return_value={}))
model_name = client.RestClient.get_asup_info(self.my_client)['model']
self.assertEqual(eseries_fake.FAKE_DEFAULT_MODEL, model_name)
def test_get_eseries_api_info(self):
fake_invoke_service = mock.Mock()
@@ -712,8 +713,7 @@ class NetAppEseriesClientDriverTestCase(test.TestCase):
self.my_client._invoke.assert_called_once_with('DELETE', url,
**{'object-id':
fake_volume['id']}
)
fake_volume['id']})
@ddt.data('00.00.00.00', '01.52.9000.2', '01.52.9001.2', '01.51.9000.3',
'01.51.9001.3', '01.51.9010.5', '0.53.9000.3', '0.53.9001.4')
@@ -782,7 +782,6 @@ class NetAppEseriesClientDriverTestCase(test.TestCase):
@ddt.ddt
class TestWebserviceClientTestCase(test.TestCase):
def setUp(self):
"""sets up the mock tests"""
super(TestWebserviceClientTestCase, self).setUp()

View File

@@ -950,16 +950,8 @@ class NetAppEseriesLibraryTestCase(test.TestCase):
eseries_fake.FAKE_ASUP_DATA['operating-mode'])
self.library._app_version = eseries_fake.FAKE_APP_VERSION
self.mock_object(
self.library._client, 'get_firmware_version',
mock.Mock(return_value=(
eseries_fake.FAKE_ASUP_DATA['system-version'])))
self.mock_object(
self.library._client, 'get_serial_numbers',
mock.Mock(return_value=eseries_fake.FAKE_SERIAL_NUMBERS))
self.mock_object(
self.library._client, 'get_model_name',
mock.Mock(
return_value=eseries_fake.FAKE_CONTROLLERS[0]['modelName']))
self.library._client, 'get_asup_info',
mock.Mock(return_value=eseries_fake.GET_ASUP_RETURN))
self.mock_object(
self.library._client, 'set_counter',
mock.Mock(return_value={'value': 1}))

View File

@@ -731,17 +731,44 @@ class RestClient(WebserviceClient):
path = ('/key-values/%s' % key)
self._invoke('POST', path, json.dumps(data))
def get_firmware_version(self):
"""Get firmware version information from the array."""
return self.list_storage_system()['fwVersion']
def set_counter(self, key, value):
path = ('/counters/%s/setCounter?value=%d' % (key, value))
self._invoke('POST', path)
def _get_controllers(self):
"""Get controller information from the array."""
return self.list_hardware_inventory()['controllers']
def get_asup_info(self):
"""Returns a dictionary of relevant autosupport information.
Currently returned fields are:
model -- E-series model name
serial_numbers -- Serial number for each controller
firmware_version -- Version of active firmware
chassis_sn -- Serial number for whole chassis
"""
asup_info = {}
controllers = self.list_hardware_inventory().get('controllers')
if controllers:
asup_info['model'] = controllers[0].get('modelName', 'unknown')
serial_numbers = [value['serialNumber'].rstrip()
for __, value in enumerate(controllers)]
serial_numbers.sort()
for index, value in enumerate(serial_numbers):
if not value:
serial_numbers[index] = 'unknown'
asup_info['serial_numbers'] = serial_numbers
else:
asup_info['model'] = 'unknown'
asup_info['serial_numbers'] = ['unknown', 'unknown']
system_info = self.list_storage_system()
if system_info:
asup_info['firmware_version'] = system_info['fwVersion']
asup_info['chassis_sn'] = system_info['chassisSerialNumber']
else:
asup_info['firmware_version'] = 'unknown'
asup_info['chassis_sn'] = 'unknown'
return asup_info
def get_eseries_api_info(self, verify=False):
"""Get E-Series API information from the array."""
@@ -759,23 +786,3 @@ class RestClient(WebserviceClient):
if mode_is_proxy:
api_operating_mode = 'proxy'
return api_operating_mode, about_response_dict['version']
def get_serial_numbers(self):
"""Get the list of Serial Numbers from the array."""
controllers = self._get_controllers()
if not controllers:
return ['unknown', 'unknown']
serial_numbers = [value['serialNumber'].rstrip()
for _, value in enumerate(controllers)]
serial_numbers.sort()
for index, value in enumerate(serial_numbers):
if not value:
serial_numbers[index] = 'unknown'
return serial_numbers
def get_model_name(self):
"""Get Model Name from the array."""
controllers = self._get_controllers()
if not controllers:
return 'unknown'
return controllers[0].get('modelName', 'unknown')

View File

@@ -1023,12 +1023,14 @@ class NetAppESeriesLibrary(object):
LOG.info(msg % self._client.api_version)
return
firmware_version = self._client.get_firmware_version()
event_source = ("Cinder driver %s" % self.DRIVER_NAME)
category = "provisioning"
event_description = "OpenStack Cinder connected to E-Series proxy"
model = self._client.get_model_name()
serial_numbers = self._client.get_serial_numbers()
asup_info = self._client.get_asup_info()
model = asup_info.get('model')
firmware_version = asup_info.get('firmware_version')
serial_numbers = asup_info.get('serial_numbers')
chassis_sn = asup_info.get('chassis_sn')
key = ("openstack-%s-%s-%s"
% (cinder_host, serial_numbers[0], serial_numbers[1]))
@@ -1046,6 +1048,7 @@ class NetAppESeriesLibrary(object):
'event-description': event_description,
'controller1-serial': serial_numbers[0],
'controller2-serial': serial_numbers[1],
'chassis-serial-number': chassis_sn,
'model': model,
'system-version': firmware_version,
'operating-mode': self._client.api_operating_mode