From 3b7d22248c2fdcaf14a53b24bebd13089c474ed4 Mon Sep 17 00:00:00 2001 From: "C. R. Oldham" Date: Thu, 12 Nov 2015 14:50:03 -0700 Subject: [PATCH] Fix fallback credentials, add grains based on dracr.server_info and dracr.inventory, fix short-circuited for loop that was preventing retrieval of most data from CMC and DRAC devices, format responses from racadm more clearly. --- salt/grains/fx2.py | 67 +++++++++++++++++++++++++++++++++----- salt/modules/chassis.py | 7 ++-- salt/modules/dracr.py | 20 +++++++++--- salt/proxy/fx2.py | 12 +++++++ salt/states/dellchassis.py | 30 +++++++++++++++-- 5 files changed, 117 insertions(+), 19 deletions(-) diff --git a/salt/grains/fx2.py b/salt/grains/fx2.py index d33a380e5a..0b6b646a26 100644 --- a/salt/grains/fx2.py +++ b/salt/grains/fx2.py @@ -1,13 +1,26 @@ # -*- coding: utf-8 -*- ''' -Generate baseline proxy minion grains +Generate baseline proxy minion grains for Dell FX2 chassis. +The challenge is that most of Salt isn't bootstrapped yet, +so we need to repeat a bunch of things that would normally happen +in proxy/fx2.py--just enough to get data from the chassis to include +in grains. ''' from __future__ import absolute_import import salt.utils +import logging +import salt.proxy.fx2 +import salt.modules.cmdmod +import salt.modules.dracr -__proxyenabled__ = ['rest_sample'] +__proxyenabled__ = ['fx2'] -__virtualname__ = 'rest_sample' +__virtualname__ = 'fx2' + +logger = logging.getLogger(__file__) + + +GRAINS_CACHE = {} def __virtual__(): @@ -17,16 +30,52 @@ def __virtual__(): return __virtualname__ +def _grains(): + ''' + Get the grains from the proxied device + ''' + r = salt.modules.dracr.system_info(host=__pillar__['proxy']['host'], + admin_username=__pillar__['proxy']['admin_username'], + admin_password=__pillar__['proxy']['admin_password']) + + if r.get('retcode', 0) == 0: + GRAINS_CACHE = r + username = __pillar__['proxy']['admin_username'] + password = __pillar__['proxy']['admin_password'] + else: + r = salt.modules.dracr.system_info(host=__pillar__['proxy']['host'], + admin_username=__pillar__['proxy']['fallback_admin_username'], + admin_password=__pillar__['proxy']['fallback_admin_password']) + if r.get('retcode', 0) == 0: + GRAINS_CACHE = r + username = __pillar__['proxy']['fallback_admin_username'] + password = __pillar__['proxy']['fallback_admin_password'] + else: + GRAINS_CACHE = {} + + GRAINS_CACHE.update(salt.modules.dracr.inventory(host=__pillar__['proxy']['host'], + admin_username=username, + admin_password=password)) + + return GRAINS_CACHE + + +def fx2(): + return _grains() + + def kernel(): return {'kernel': 'proxy'} -def os(): - return {'os': 'RestExampleOS'} - - def location(): - return {'location': 'In this darn virtual machine. Let me out!'} + if not GRAINS_CACHE: + GRAINS_CACHE.update(_grains()) + + try: + return GRAINS_CACHE.get('Chassis Information').get('Chassis Location') + except AttributeError: + return "Unknown" def os_family(): @@ -34,4 +83,4 @@ def os_family(): def os_data(): - return {'os_data': 'funkyHttp release 1.0.a.4.g'} + return {'os_data': 'Unknown'} diff --git a/salt/modules/chassis.py b/salt/modules/chassis.py index ff58747aa5..7485093c72 100644 --- a/salt/modules/chassis.py +++ b/salt/modules/chassis.py @@ -36,8 +36,9 @@ def __virtual__(): def cmd(cmd, *args, **kwargs): + proxyprefix = __opts__['proxy']['proxytype'] + kwargs['admin_username'] = __proxy__[proxyprefix+'.admin_username']() + kwargs['admin_password'] = __proxy__[proxyprefix+'.admin_password']() + kwargs['host'] = __proxy__[proxyprefix+'.host']() proxycmd = __opts__['proxy']['proxytype'] + '.chconfig' - kwargs['admin_username'] = __pillar__['proxy']['admin_username'] - kwargs['admin_password'] = __pillar__['proxy']['admin_password'] - kwargs['host'] = __pillar__['proxy']['host'] return __proxy__[proxycmd](cmd, *args, **kwargs) diff --git a/salt/modules/dracr.py b/salt/modules/dracr.py index 8b522cdb1a..7c39ee8f40 100644 --- a/salt/modules/dracr.py +++ b/salt/modules/dracr.py @@ -21,6 +21,13 @@ from salt.ext.six.moves import map log = logging.getLogger(__name__) +try: + run_all = __salt__['cmd.run_all'] +except NameError: + import salt.modules.cmdmod + __salt__ = { + 'cmd.run_all': salt.modules.cmdmod._run_all_quiet + } def __virtual__(): if salt.utils.which('racadm'): @@ -37,13 +44,16 @@ def __parse_drac(output): section = '' for i in output.splitlines(): + if i.strip().endswith(':') and '=' not in i: + section = i[0:-1] + drac[section] = {} if len(i.rstrip()) > 0 and '=' in i: if section in drac: drac[section].update(dict( [[prop.strip() for prop in i.split('=')]] )) else: - section = i.strip()[1:-1] + section = i.strip() if section not in drac and section: drac[section] = {} @@ -127,7 +137,6 @@ def __execute_ret(command, host=None, fmtlines.append(l) if '=' in l: continue - break cmd['stdout'] = '\n'.join(fmtlines) return cmd @@ -135,8 +144,6 @@ def __execute_ret(command, host=None, def get_dns_dracname(host=None, admin_username=None, admin_password=None): - import pydevd - pydevd.settrace('172.16.207.1', port=65500, stdoutToServer=True, stderrToServer=True) ret = __execute_ret('get iDRAC.NIC.DNSRacName', host=host, admin_username=admin_username, @@ -976,7 +983,10 @@ def get_slotname(slot, host=None, admin_username=None, admin_password=None): ''' slots = list_slotnames(host=host, admin_username=admin_username, admin_password=admin_password) - return slots[slot] + # The keys for this dictionary are strings, not integers, so convert the + # argument to a string + slot = str(slot) + return slots[slot]['slotname'] def set_slotname(slot, name, host=None, diff --git a/salt/proxy/fx2.py b/salt/proxy/fx2.py index 4ce021aafc..ad59c8314d 100644 --- a/salt/proxy/fx2.py +++ b/salt/proxy/fx2.py @@ -216,6 +216,18 @@ def init(opts): return False +def admin_username(): + return DETAILS['admin_username'] + + +def admin_password(): + return DETAILS['admin_password'] + + +def host(): + return DETAILS['host'] + + def _grains(host, user, password): ''' Get the grains from the proxied device diff --git a/salt/states/dellchassis.py b/salt/states/dellchassis.py index 227718c8ca..94898027cd 100644 --- a/salt/states/dellchassis.py +++ b/salt/states/dellchassis.py @@ -87,11 +87,37 @@ structure: snmp: nonpublic password: saltstack1 -And to go with it, here's an example state that pulls the data from pillar +And to go with it, here's an example state that pulls the data from pillar. +This example assumes that the pillar data would be structured like + +Pillar: .. code-block:: yaml - {% set details = pillar['chassis'] with context %} + proxy: + host: 192.168.1.1 + admin_username: root + admin_password: sekrit + fallback_admin_username: root + fallback_admin_password: old_sekrit + proxytype: fx2 + + chassis: + name: fx2-1 + username: root + datacenter: UT1 + location: UT1 + management_mode: 2 + idrac_launch: 0 + slot_names: + 1: blade1 + 2: blade2 + +State: + +.. code-block:: yaml + + {% set details = pillar.get('proxy:chassis', {}) %} standup-step1: dellchassis.chassis: - name: {{ details['name'] }}