FIX: Allow configuration of IPMI privilege level 78/1078/9
authordave kormann <dk3239@att.com>
Thu, 27 Jun 2019 16:52:59 +0000 (12:52 -0400)
committerdave kormann <davek@research.att.com>
Mon, 15 Jul 2019 13:03:37 +0000 (09:03 -0400)
This change updates the inventory handlers to provide an IPMI
privilege level (with a default of "ADMINISTRATOR") when making
hardware detection requests.  If the privilege level is not specified,
IPMI requests will fail if the user does not have ADMINISTRATOR
privileges.

This change depends on changes 1076 and 1077.

signed-off-by: dave kormann <davek@research.att.com>
Change-Id: I06225d00adc719c324de5fc1a4b18d7ea2ac56f4

inventoryhandlers/baremetal-node-inventory/zbaremetalnodeinventory.py
inventoryhandlers/hwinventory/hwinventory.py [changed mode: 0644->0755]
inventoryhandlers/openstack/openstackinventory.py
inventoryhandlers/storageinventory/storageinventory.py [changed mode: 0644->0755]
validators/src/HostsValidation.py
validators/src/VersionValidation.py

index 249a5c0..b6b90e9 100644 (file)
@@ -96,6 +96,7 @@ class zbaremetalnodeinventory(cmansibleinventoryconfig.CMAnsibleInventoryConfigP
 
     def handle(self):
         usersconf = self.confman.get_users_config_handler()
+        hostsconf = self.confman.get_hosts_config_handler()
         admin_user = usersconf.get_admin_user()
         self.add_global_var("home_dir", "/home/" + admin_user)
         all_vars = self.inventory['all']['vars']
@@ -177,6 +178,7 @@ class zbaremetalnodeinventory(cmansibleinventoryconfig.CMAnsibleInventoryConfigP
                 power["ipmi_address"] = all_vars['hosts'][host]['hwmgmt']['address']
                 power["ipmi_password"] = all_vars['hosts'][host]['hwmgmt']['password']
                 power["ipmi_username"] = all_vars['hosts'][host]['hwmgmt']['user']
+                power["ipmi_priv_level"] = hostsconf.get_hwmgmt_priv_level(host)
                 power["product_family"] = all_vars['hw_inventory_details'][host]['product_family']
                 power["vendor"] = all_vars['hw_inventory_details'][host]['vendor']
 
old mode 100644 (file)
new mode 100755 (executable)
index 76ea0a9..7768426
@@ -61,7 +61,7 @@ class hwinventory(cmansibleinventoryconfig.CMAnsibleInventoryConfigPlugin):
         self._set_hw_types()
         self._add_hw_config()
 
-    
+
     def _add_hw_config(self):
         try:
             text = Environment().from_string(JSON_HW_HOST_VAR).render(
@@ -78,8 +78,9 @@ class hwinventory(cmansibleinventoryconfig.CMAnsibleInventoryConfigPlugin):
         hwmgmt_addr = self._hosts_config_handler.get_hwmgmt_ip(name)
         hwmgmt_user = self._hosts_config_handler.get_hwmgmt_user(name)
         hwmgmt_pass = self._hosts_config_handler.get_hwmgmt_password(name)
-        return hw.get_hw_data(hwmgmt_addr, hwmgmt_user, hwmgmt_pass)
-        
+        hwmgmt_priv_level = self._hosts_config_handler.get_hwmgmt_priv_level(name)
+        return hw.get_hw_data(hwmgmt_addr, hwmgmt_user, hwmgmt_pass, hwmgmt_priv_level)
+
     def _set_hw_types(self):
         hosts = self._hosts_config_handler.get_hosts()
         for host in hosts:
@@ -88,4 +89,4 @@ class hwinventory(cmansibleinventoryconfig.CMAnsibleInventoryConfigPlugin):
             host_object.vendor = hw_details.get("vendor", "Unknown")
             host_object.product_family = hw_details.get("product_family", "Unknown")
             host_object.mgmt_mac = hw_details.get('info', {}).get("MAC Address", "00:00:00:00:00:00")
-            self.host_objects.append(host_object) 
+            self.host_objects.append(host_object)
index 1f6ee81..2dde0db 100644 (file)
@@ -1137,6 +1137,7 @@ class Host:
         self.hwmgmt_address = None
         self.hwmgmt_password = None
         self.hwmgmt_user = None
+        self.hwmgmt_priv_level = 'ADMINISTRATOR'
         self.mgmt_mac = None
         self.is_performance = False
         self.os_max_threads = 16
@@ -1427,6 +1428,7 @@ class openstackinventory(cmansibleinventoryconfig.CMAnsibleInventoryConfigPlugin
         host.hwmgmt_address = hostsconf.get_hwmgmt_ip(name)
         host.hwmgmt_user = hostsconf.get_hwmgmt_user(name)
         host.hwmgmt_password = hostsconf.get_hwmgmt_password(name)
+        host.hwmgmt_priv_level = hostsconf.get_hwmgmt_priv_level(name)
         host.mgmt_mac = hostsconf.get_mgmt_mac(name)
 
 
old mode 100644 (file)
new mode 100755 (executable)
index b0a9182..73a75b0
@@ -1319,7 +1319,8 @@ class storageinventory(cmansibleinventoryconfig.CMAnsibleInventoryConfigPlugin):
         hwmgmt_addr = self._hosts_config_handler.get_hwmgmt_ip(name)
         hwmgmt_user = self._hosts_config_handler.get_hwmgmt_user(name)
         hwmgmt_pass = self._hosts_config_handler.get_hwmgmt_password(name)
-        return hw.get_hw_type(hwmgmt_addr, hwmgmt_user, hwmgmt_pass)
+        hwmgmt_priv_level = self._hosts_config_handler.get_hwmgmt_priv_level(name)
+        return hw.get_hw_type(hwmgmt_addr, hwmgmt_user, hwmgmt_pass, hwmgmt_priv_level)
 
     @staticmethod
     def _get_os_disk(hw_type):
index 86494e8..e59ed26 100644 (file)
@@ -403,12 +403,22 @@ class HostsValidation(cmvalidator.CMValidator):
                                                  (attribute, profile, host))
 
     def validate_hwmgmt(self, hwmgmt, host):
+        # this list may not be comprehensive, but it matches ironic's idea
+        # of valid privileges.  In practice, we'll likely only see OPERATOR
+        # and ADMINISTRATOR.  Case seems to matter here.
+        valid_ipmi_priv = ['USER', 'CALLBACK', 'OPERATOR', 'ADMINISTRATOR']
+
         if not hwmgmt:
             raise validation.ValidationError('Missing hwmgmt configuration for %s' % host)
         if not hwmgmt.get('user'):
             raise validation.ValidationError('Missing hwmgmt username for %s' % host)
         if not hwmgmt.get('password'):
             raise validation.ValidationError('Missing hwmgmt password for %s' % host)
+        priv_level = hwmgmt.get('priv_level')
+        if priv_level and priv_level not in valid_ipmi_priv:
+            # priv_level is optional, but should be in the valid range.
+            raise validation.ValidationError('Invalid IPMI privilege level %s for %s' %
+                                             (priv_level, host))
         validationutils = validation.ValidationUtils()
         validationutils.validate_ip_address(hwmgmt.get('address'))
 
index f6e891a..813cf02 100644 (file)
@@ -22,10 +22,10 @@ from cmdatahandlers.api import validation
 
 class VersionValidation(cmvalidator.CMValidator):
     domain = 'cloud.version'
-    version = [2, 0, 2]
+    version = [2, 0, 3]
 
     # Should be same as 'version' in release build
-    devel_version = [2, 0, 2]
+    devel_version = [2, 0, 3]
 
     # Example:
     # {1: 'This is the first change requiring new template version (1.1.0)',