Single field added to AutoSupport data key-value pair.
AutoSupport is a mechanism that allows NetApp backends
to report customer usage metrics.
Change-Id: I4c1dae89505767acd579e874fbe541d4617915f2
)
STORAGE_SYSTEM = {
+ 'chassisSerialNumber': 1,
+ 'fwVersion': '08.10.15.00',
'freePoolSpace': 11142431623168,
'driveCount': 24,
'hostSparesUsed': 0, 'id':
'pitSequenceNumber': '19'
}
+HARDWARE_INVENTORY_SINGLE_CONTROLLER = {
+ 'controllers': [
+ {
+ 'modelName': '2752',
+ 'serialNumber': '021436001321'
+ }
+ ]
+}
+
HARDWARE_INVENTORY = {
+ 'controllers': [
+ {
+ 'modelName': '2752',
+ 'serialNumber': '021436000943'
+ },
+ {
+ 'modelName': '2752',
+ 'serialNumber': '021436001321'
+ }
+ ],
'iscsiPorts': [
{
'controllerId':
},
]
-
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'
'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))
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
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}))
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))
+ self.mock_object(
+ client.RestClient, 'list_storage_system',
+ mock.Mock(return_value={}))
- serial_numbers = client.RestClient.get_serial_numbers(self.my_client)
+ sn = client.RestClient.get_asup_info(self.my_client)['serial_numbers']
- self.assertEqual(expected_serial_numbers, serial_numbers)
+ self.assertEqual(expected_serial_numbers, sn)
- def test_get_model_name(self):
+ def test_get_asup_info_model_name(self):
+ self.mock_object(
+ client.RestClient, 'list_hardware_inventory',
+ mock.Mock(return_value=eseries_fake.HARDWARE_INVENTORY))
self.mock_object(
- client.RestClient, '_get_controllers',
- mock.Mock(return_value=eseries_fake.FAKE_CONTROLLERS))
+ 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_CONTROLLERS[0]['modelName'],
- model)
+ self.assertEqual(eseries_fake.HARDWARE_INVENTORY['controllers'][0]
+ ['modelName'], model_name)
- def test_get_model_name_empty_controllers_list(self):
+ def test_get_asup_info_model_name_empty_controllers_list(self):
self.mock_object(
- client.RestClient, '_get_controllers',
- mock.Mock(return_value=[]))
+ client.RestClient, 'list_hardware_inventory',
+ mock.Mock(return_value={}))
+ self.mock_object(
+ client.RestClient, 'list_storage_system',
+ mock.Mock(return_value={}))
- 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.FAKE_DEFAULT_MODEL, model_name)
def test_get_eseries_api_info(self):
fake_invoke_service = mock.Mock()
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')
@ddt.ddt
class TestWebserviceClientTestCase(test.TestCase):
-
def setUp(self):
"""sets up the mock tests"""
super(TestWebserviceClientTestCase, self).setUp()
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}))
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."""
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')
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]))
'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