]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Add serial number to eseries ASUP payload
authorMike Rooney <rooneym@netapp.com>
Fri, 4 Dec 2015 17:14:45 +0000 (12:14 -0500)
committerMike Rooney <rooneym@netapp.com>
Thu, 17 Dec 2015 17:46:47 +0000 (17:46 +0000)
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

cinder/tests/unit/volume/drivers/netapp/eseries/fakes.py
cinder/tests/unit/volume/drivers/netapp/eseries/test_client.py
cinder/tests/unit/volume/drivers/netapp/eseries/test_library.py
cinder/volume/drivers/netapp/eseries/client.py
cinder/volume/drivers/netapp/eseries/library.py

index 4e49e3ba5767e6552686731fce763ce0b8af4c10..d862984d8dfdac89ef06ffc37bf181db74f488fe 100644 (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))
 
index 87a854ea1f8fbff637a6e1150c71164a90f82020..a14055615f5028aa9f3dae47621c717d54c33c51 100644 (file)
@@ -26,7 +26,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
 
@@ -346,16 +345,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}))
@@ -372,38 +363,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))
+        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()
@@ -699,8 +700,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')
@@ -755,7 +755,6 @@ class NetAppEseriesClientDriverTestCase(test.TestCase):
 
 @ddt.ddt
 class TestWebserviceClientTestCase(test.TestCase):
-
     def setUp(self):
         """sets up the mock tests"""
         super(TestWebserviceClientTestCase, self).setUp()
index d163471c868945bf216f5e8c84f8c336023afb2a..19c65c3c39a20be5ce80c74c1c98d7ffc0ae8cbc 100644 (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}))
index 60897216b18d936f137d0d46e1e20a6bd31d4da5..1709f8f2b701fa9e4bf366af4b41378559902881 100644 (file)
@@ -722,17 +722,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."""
@@ -750,23 +777,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')
index dc5d0e2064c89fa272daa0e57dcbd4ce9347240a..92ccfd82de9fb3bd1b88cac5e35447474fea9b74 100644 (file)
@@ -1020,12 +1020,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]))
@@ -1043,6 +1045,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