<commit_before># -*- coding: utf-8 -*-
'''
Manage Dell DRAC
'''
from __future__ import absolute_import

import salt.utils

import logging
from six.moves import range

log = logging.getLogger(__name__)

def __virtual__():
    '''

    '''
    if salt.utils.which('racadm'):
        return True

    return False

def __parse_drac(output):
    '''
    Parse Dell DRAC output
    '''
    drac = {}
    section = ''

    for i in output.splitlines():
        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]
            if section not in drac and section:
                drac[section] = {}

    return drac

def __execute_cmd(command):
    '''
    Execute rac commands
    '''
    cmd = __salt__['cmd.run_all']('racadm {0}'.format(command))

    if cmd['retcode'] != 0:
        log.warn('racadm return an exit code \'{0}\'.'.format(cmd['retcode']))
        return False

    return True

def system_info():
    '''
    Return System information

    CLI Example:

    .. code-block:: bash

        salt dell drac.getsysinfo
    '''
    drac = {}
    section = ''

    cmd = __salt__['cmd.run_all']('racadm getsysinfo')

    if cmd['retcode'] != 0:
        log.warn('racadm return an exit code \'{0}\'.'.format(cmd['retcode']))

    return __parse_drac(cmd['stdout'])

def network_info():
    '''
    Return Network Configuration

    CLI Example:

    .. code-block:: bash

        salt dell drac.getniccfg
    '''

    cmd = __salt__['cmd.run_all']('racadm getniccfg')

    if cmd['retcode'] != 0:
        log.warn('racadm return an exit code \'{0}\'.'.format(cmd['retcode']))

    return __parse_drac(cmd['stdout'])

def nameservers(*ns):
    '''
    Configure the nameservers on the DRAC

    CLI Example:

    .. code-block:: bash

        salt dell drac.nameservers [NAMESERVERS]
        salt dell drac.nameservers ns1.example.com ns2.example.com
    '''
    if len(ns) > 2:
        log.warn('racadm only supports two nameservers')
        return False

    for i in range(1, len(ns) + 1):
        if not __execute_cmd('config -g cfgLanNetworking -o \
                cfgDNSServer{0} {1}'.format(i, ns[i - 1])):
            return False

    return True

def syslog(server, enable=True):
    '''
    Configure syslog remote logging, by default syslog will automatically be
    enabled if a server is specified. However, if you want to disable syslog
    you will need to specify a server followed by False

    CLI Example:

    .. code-block:: bash

        salt dell drac.syslog [SYSLOG IP] [ENABLE/DISABLE]
        salt dell drac.syslog 0.0.0.0 False
    '''
    if enable:
        if __execute_cmd('config -g cfgRemoteHosts -o \
                cfgRhostsSyslogEnable 1'):
            return __execute_cmd('config -g cfgRemoteHosts -o \
                    cfgRhostsSyslogServer1 {0}'.format(server))

    return __execute_cmd('config -g cfgRemoteHosts -o cfgRhostsSyslogEnable 0')

def email_alerts(action):
    '''
    Enable/Disable email alerts

    CLI Example:

    .. code-block:: bash

        salt dell drac.email_alerts True
        salt dell drac.email_alerts False
    '''

    if action:
        return __execute_cmd('config -g cfgEmailAlert -o \
                cfgEmailAlertEnable -i 1 1')
    else:
        return __execute_cmd('config -g cfgEmailAlert -o \
                cfgEmailAlertEnable -i 1 0')

def list_users():
    '''
    List all DRAC users

    CLI Example:

    .. code-block:: bash

        salt dell drac.list_users
    '''
    users = {}
    _username = ''

    for i in range(1, 12):
        cmd = __salt__['cmd.run_all']('racadm getconfig -g \
                cfgUserAdmin -i {0}'.format(i))

        if cmd['retcode'] != 0:
            log.warn('racadm return an exit \
                    code \'{0}\'.'.format(cmd['retcode']))

        for user in cmd['stdout'].splitlines():
            if 'cfgUserAdminIndex' in user or user.startswith('#'):
                continue

            (k, v) = user.split('=')

            if k.startswith('cfgUserAdminUserName'):
                _username = v.strip()

                if v:
                    users[_username] = {'index': i}
                else:
                    break
            else:
                users[_username].update({k: v})

    return users

def delete_user(username, uid=None):
    '''
    Delete a user

    CLI Example:

    .. code-block:: bash

        salt dell drac.delete_user [USERNAME] [UID - optional]
        salt dell drac.delete_user diana 4
    '''
    if uid is None:
        user = list_users()
        uid = user[username]['index']

    if uid:
        return __execute_cmd('config -g cfgUserAdmin -o \
                              cfgUserAdminUserName -i {0} ""'.format(uid))

    else:
        log.warn('\'{0}\' does not exist'.format(username))
        return False

    return True

def change_password(username, password, uid=None):
    '''
    Change users password

    CLI Example:

    .. code-block:: bash

        salt dell drac.change_password [USERNAME] [PASSWORD] [UID - optional]
        salt dell drac.change_password diana secret
    '''
    if uid is None:
        user = list_users()
        uid = user[username]['index']

    if uid:
        return __execute_cmd('config -g cfgUserAdmin -o \
                cfgUserAdminPassword -i {0} {1}'.format(uid, password))
    else:
        log.warn('\'{0}\' does not exist'.format(username))
        return False

    return True

def create_user(username, password, permissions, users=None):
    '''
    Create user accounts

    CLI Example:

    .. code-block:: bash

        salt dell drac.create_user [USERNAME] [PASSWORD] [PRIVELEGES]
        salt dell drac.create_user diana secret login,test_alerts,clear_logs

    DRAC Privileges
      * login                   : Login to iDRAC
      * drac                    : Configure iDRAC
      * user_management         : Configure Users
      * clear_logs              : Clear Logs
      * server_control_commands : Execute Server Control Commands
      * console_redirection     : Access Console Redirection
      * virtual_media           : Access Virtual Media
      * test_alerts             : Test Alerts
      * debug_commands          : Execute Debug Commands
    '''
    _uids = set()

    if users is None:
        users = list_users()

    if username in users:
        log.warn('\'{0}\' already exists'.format(username))
        return False

    for i in users.keys():
        _uids.add(users[i]['index'])

    uid = sorted(list(set(range(2, 12)) - _uids), reverse=True).pop()

    # Create user accountvfirst
    if not __execute_cmd('config -g cfgUserAdmin -o \
                 cfgUserAdminUserName -i {0} {1}'.format(uid, username)):
        delete_user(username, uid)
        return False

    # Configure users permissions
    if not set_permissions(username, permissions, uid):
        log.warn('unable to set user permissions')
        delete_user(username, uid)
        return False

    # Configure users password
    if not change_password(username, password, uid):
        log.warn('unable to set user password')
        delete_user(username, uid)
        return False

    # Enable users admin
    if not __execute_cmd('config -g cfgUserAdmin -o \
                          cfgUserAdminEnable -i {0} 1'.format(uid)):
        delete_user(username, uid)
        return False

    return True

def set_permissions(username, permissions, uid=None):
    '''
    Configure users permissions

    CLI Example:

    .. code-block:: bash

        salt dell drac.set_permissions [USERNAME] [PRIVELEGES] [USER INDEX - optional]
        salt dell drac.set_permissions diana login,test_alerts,clear_logs 4

    DRAC Privileges
      * login                   : Login to iDRAC
      * drac                    : Configure iDRAC
      * user_management         : Configure Users
      * clear_logs              : Clear Logs
      * server_control_commands : Execute Server Control Commands
      * console_redirection     : Access Console Redirection
      * virtual_media           : Access Virtual Media
      * test_alerts             : Test Alerts
      * debug_commands          : Execute Debug Commands
    '''
    privileges = {'login': '0x0000001',
                  'drac': '0x0000002',
                  'user_management': '0x0000004',
                  'clear_logs': '0x0000008',
                  'server_control_commands': '0x0000010',
                  'console_redirection': '0x0000020',
                  'virtual_media': '0x0000040',
                  'test_alerts': '0x0000080',
                  'debug_commands': '0x0000100'}

    permission = 0

    # When users don't provide a user ID we need to search for this
    if uid is None:
        user = list_users()
        uid = user[username]['index']

    # Generate privilege bit mask
    for i in permissions.split(','):
        perm = i.strip()

        if perm in privileges:
            permission += int(privileges[perm], 16)

    return __execute_cmd('config -g cfgUserAdmin -o \
            cfgUserAdminPrivilege -i {0} 0x{1:08X}'.format(uid, permission))

def set_snmp(community):
    '''
    Configure SNMP community string

    CLI Example:

    .. code-block:: bash

        salt dell drac.set_snmp [COMMUNITY]
        salt dell drac.set_snmp public
    '''
    return __execute_cmd('config -g cfgOobSnmp -o \
            cfgOobSnmpAgentCommunity {0}'.format(community))

def set_network(ip, netmask, gateway):
    '''
    Configure Network

    CLI Example:

    .. code-block:: bash

        salt dell drac.set_network [DRAC IP] [NETMASK] [GATEWAY]
        salt dell drac.set_network 192.168.0.2 255.255.255.0 192.168.0.1
    '''
    return __execute_cmd('setniccfg -s {0} {1} {2}'.format(
        ip, netmask, gateway
        ))

def server_reboot():
    '''
    Issues a power-cycle operation on the managed server. This action is
    similar to pressing the power button on the system's front panel to
    power down and then power up the system.

    CLI Example:

    .. code-block:: bash

        salt dell drac.server_reboot
    '''
    return __execute_cmd('serveraction powercycle')

def server_poweroff():
    '''
    Powers down the managed server.

    CLI Example:

    .. code-block:: bash

        salt dell drac.server_poweroff
    '''
    return __execute_cmd('serveraction powerdown')

def server_poweron():
    '''
    Powers up the managed server.

    CLI Example:

    .. code-block:: bash

        salt dell drac.server_poweron
    '''
    return __execute_cmd('serveraction powerup')

def server_hardreset():
    '''
    Performs a reset (reboot) operation on the managed server.

    CLI Example:

    .. code-block:: bash

        salt dell drac.server_hardreset
    '''
    return __execute_cmd('serveraction hardreset')

def server_pxe():
    '''
    Configure server to PXE perform a one off PXE boot

    CLI Example:

    .. code-block:: bash

        salt dell drac.server_pxe
    '''
    if __execute_cmd('config -g cfgServerInfo -o \
            cfgServerFirstBootDevice PXE'):
        if __execute_cmd('config -g cfgServerInfo -o cfgServerBootOnce 1'):
            return server_reboot
        else:
            log.warn('failed to set boot order')
            return False

    log.warn('failed to to configure PXE boot')
    return False
<commit_msg>Replaced module six in file /salt/modules/drac.py<commit_after># -*- coding: utf-8 -*-
'''
Manage Dell DRAC
'''
from __future__ import absolute_import

import salt.utils

import logging
from salt.utils.six.moves import range

log = logging.getLogger(__name__)

def __virtual__():
    '''

    '''
    if salt.utils.which('racadm'):
        return True

    return False

def __parse_drac(output):
    '''
    Parse Dell DRAC output
    '''
    drac = {}
    section = ''

    for i in output.splitlines():
        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]
            if section not in drac and section:
                drac[section] = {}

    return drac

def __execute_cmd(command):
    '''
    Execute rac commands
    '''
    cmd = __salt__['cmd.run_all']('racadm {0}'.format(command))

    if cmd['retcode'] != 0:
        log.warn('racadm return an exit code \'{0}\'.'.format(cmd['retcode']))
        return False

    return True

def system_info():
    '''
    Return System information

    CLI Example:

    .. code-block:: bash

        salt dell drac.getsysinfo
    '''
    drac = {}
    section = ''

    cmd = __salt__['cmd.run_all']('racadm getsysinfo')

    if cmd['retcode'] != 0:
        log.warn('racadm return an exit code \'{0}\'.'.format(cmd['retcode']))

    return __parse_drac(cmd['stdout'])

def network_info():
    '''
    Return Network Configuration

    CLI Example:

    .. code-block:: bash

        salt dell drac.getniccfg
    '''

    cmd = __salt__['cmd.run_all']('racadm getniccfg')

    if cmd['retcode'] != 0:
        log.warn('racadm return an exit code \'{0}\'.'.format(cmd['retcode']))

    return __parse_drac(cmd['stdout'])

def nameservers(*ns):
    '''
    Configure the nameservers on the DRAC

    CLI Example:

    .. code-block:: bash

        salt dell drac.nameservers [NAMESERVERS]
        salt dell drac.nameservers ns1.example.com ns2.example.com
    '''
    if len(ns) > 2:
        log.warn('racadm only supports two nameservers')
        return False

    for i in range(1, len(ns) + 1):
        if not __execute_cmd('config -g cfgLanNetworking -o \
                cfgDNSServer{0} {1}'.format(i, ns[i - 1])):
            return False

    return True

def syslog(server, enable=True):
    '''
    Configure syslog remote logging, by default syslog will automatically be
    enabled if a server is specified. However, if you want to disable syslog
    you will need to specify a server followed by False

    CLI Example:

    .. code-block:: bash

        salt dell drac.syslog [SYSLOG IP] [ENABLE/DISABLE]
        salt dell drac.syslog 0.0.0.0 False
    '''
    if enable:
        if __execute_cmd('config -g cfgRemoteHosts -o \
                cfgRhostsSyslogEnable 1'):
            return __execute_cmd('config -g cfgRemoteHosts -o \
                    cfgRhostsSyslogServer1 {0}'.format(server))

    return __execute_cmd('config -g cfgRemoteHosts -o cfgRhostsSyslogEnable 0')

def email_alerts(action):
    '''
    Enable/Disable email alerts

    CLI Example:

    .. code-block:: bash

        salt dell drac.email_alerts True
        salt dell drac.email_alerts False
    '''

    if action:
        return __execute_cmd('config -g cfgEmailAlert -o \
                cfgEmailAlertEnable -i 1 1')
    else:
        return __execute_cmd('config -g cfgEmailAlert -o \
                cfgEmailAlertEnable -i 1 0')

def list_users():
    '''
    List all DRAC users

    CLI Example:

    .. code-block:: bash

        salt dell drac.list_users
    '''
    users = {}
    _username = ''

    for i in range(1, 12):
        cmd = __salt__['cmd.run_all']('racadm getconfig -g \
                cfgUserAdmin -i {0}'.format(i))

        if cmd['retcode'] != 0:
            log.warn('racadm return an exit \
                    code \'{0}\'.'.format(cmd['retcode']))

        for user in cmd['stdout'].splitlines():
            if 'cfgUserAdminIndex' in user or user.startswith('#'):
                continue

            (k, v) = user.split('=')

            if k.startswith('cfgUserAdminUserName'):
                _username = v.strip()

                if v:
                    users[_username] = {'index': i}
                else:
                    break
            else:
                users[_username].update({k: v})

    return users

def delete_user(username, uid=None):
    '''
    Delete a user

    CLI Example:

    .. code-block:: bash

        salt dell drac.delete_user [USERNAME] [UID - optional]
        salt dell drac.delete_user diana 4
    '''
    if uid is None:
        user = list_users()
        uid = user[username]['index']

    if uid:
        return __execute_cmd('config -g cfgUserAdmin -o \
                              cfgUserAdminUserName -i {0} ""'.format(uid))

    else:
        log.warn('\'{0}\' does not exist'.format(username))
        return False

    return True

def change_password(username, password, uid=None):
    '''
    Change users password

    CLI Example:

    .. code-block:: bash

        salt dell drac.change_password [USERNAME] [PASSWORD] [UID - optional]
        salt dell drac.change_password diana secret
    '''
    if uid is None:
        user = list_users()
        uid = user[username]['index']

    if uid:
        return __execute_cmd('config -g cfgUserAdmin -o \
                cfgUserAdminPassword -i {0} {1}'.format(uid, password))
    else:
        log.warn('\'{0}\' does not exist'.format(username))
        return False

    return True

def create_user(username, password, permissions, users=None):
    '''
    Create user accounts

    CLI Example:

    .. code-block:: bash

        salt dell drac.create_user [USERNAME] [PASSWORD] [PRIVELEGES]
        salt dell drac.create_user diana secret login,test_alerts,clear_logs

    DRAC Privileges
      * login                   : Login to iDRAC
      * drac                    : Configure iDRAC
      * user_management         : Configure Users
      * clear_logs              : Clear Logs
      * server_control_commands : Execute Server Control Commands
      * console_redirection     : Access Console Redirection
      * virtual_media           : Access Virtual Media
      * test_alerts             : Test Alerts
      * debug_commands          : Execute Debug Commands
    '''
    _uids = set()

    if users is None:
        users = list_users()

    if username in users:
        log.warn('\'{0}\' already exists'.format(username))
        return False

    for i in users.keys():
        _uids.add(users[i]['index'])

    uid = sorted(list(set(range(2, 12)) - _uids), reverse=True).pop()

    # Create user accountvfirst
    if not __execute_cmd('config -g cfgUserAdmin -o \
                 cfgUserAdminUserName -i {0} {1}'.format(uid, username)):
        delete_user(username, uid)
        return False

    # Configure users permissions
    if not set_permissions(username, permissions, uid):
        log.warn('unable to set user permissions')
        delete_user(username, uid)
        return False

    # Configure users password
    if not change_password(username, password, uid):
        log.warn('unable to set user password')
        delete_user(username, uid)
        return False

    # Enable users admin
    if not __execute_cmd('config -g cfgUserAdmin -o \
                          cfgUserAdminEnable -i {0} 1'.format(uid)):
        delete_user(username, uid)
        return False

    return True

def set_permissions(username, permissions, uid=None):
    '''
    Configure users permissions

    CLI Example:

    .. code-block:: bash

        salt dell drac.set_permissions [USERNAME] [PRIVELEGES] [USER INDEX - optional]
        salt dell drac.set_permissions diana login,test_alerts,clear_logs 4

    DRAC Privileges
      * login                   : Login to iDRAC
      * drac                    : Configure iDRAC
      * user_management         : Configure Users
      * clear_logs              : Clear Logs
      * server_control_commands : Execute Server Control Commands
      * console_redirection     : Access Console Redirection
      * virtual_media           : Access Virtual Media
      * test_alerts             : Test Alerts
      * debug_commands          : Execute Debug Commands
    '''
    privileges = {'login': '0x0000001',
                  'drac': '0x0000002',
                  'user_management': '0x0000004',
                  'clear_logs': '0x0000008',
                  'server_control_commands': '0x0000010',
                  'console_redirection': '0x0000020',
                  'virtual_media': '0x0000040',
                  'test_alerts': '0x0000080',
                  'debug_commands': '0x0000100'}

    permission = 0

    # When users don't provide a user ID we need to search for this
    if uid is None:
        user = list_users()
        uid = user[username]['index']

    # Generate privilege bit mask
    for i in permissions.split(','):
        perm = i.strip()

        if perm in privileges:
            permission += int(privileges[perm], 16)

    return __execute_cmd('config -g cfgUserAdmin -o \
            cfgUserAdminPrivilege -i {0} 0x{1:08X}'.format(uid, permission))

def set_snmp(community):
    '''
    Configure SNMP community string

    CLI Example:

    .. code-block:: bash

        salt dell drac.set_snmp [COMMUNITY]
        salt dell drac.set_snmp public
    '''
    return __execute_cmd('config -g cfgOobSnmp -o \
            cfgOobSnmpAgentCommunity {0}'.format(community))

def set_network(ip, netmask, gateway):
    '''
    Configure Network

    CLI Example:

    .. code-block:: bash

        salt dell drac.set_network [DRAC IP] [NETMASK] [GATEWAY]
        salt dell drac.set_network 192.168.0.2 255.255.255.0 192.168.0.1
    '''
    return __execute_cmd('setniccfg -s {0} {1} {2}'.format(
        ip, netmask, gateway
        ))

def server_reboot():
    '''
    Issues a power-cycle operation on the managed server. This action is
    similar to pressing the power button on the system's front panel to
    power down and then power up the system.

    CLI Example:

    .. code-block:: bash

        salt dell drac.server_reboot
    '''
    return __execute_cmd('serveraction powercycle')

def server_poweroff():
    '''
    Powers down the managed server.

    CLI Example:

    .. code-block:: bash

        salt dell drac.server_poweroff
    '''
    return __execute_cmd('serveraction powerdown')

def server_poweron():
    '''
    Powers up the managed server.

    CLI Example:

    .. code-block:: bash

        salt dell drac.server_poweron
    '''
    return __execute_cmd('serveraction powerup')

def server_hardreset():
    '''
    Performs a reset (reboot) operation on the managed server.

    CLI Example:

    .. code-block:: bash

        salt dell drac.server_hardreset
    '''
    return __execute_cmd('serveraction hardreset')

def server_pxe():
    '''
    Configure server to PXE perform a one off PXE boot

    CLI Example:

    .. code-block:: bash

        salt dell drac.server_pxe
    '''
    if __execute_cmd('config -g cfgServerInfo -o \
            cfgServerFirstBootDevice PXE'):
        if __execute_cmd('config -g cfgServerInfo -o cfgServerBootOnce 1'):
            return server_reboot
        else:
            log.warn('failed to set boot order')
            return False

    log.warn('failed to to configure PXE boot')
    return False
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''
DRBD administration module
'''

import logging

log = logging.getLogger(__name__)

def overview():
    '''
    Show status of the DRBD devices

    CLI Example:

    .. code-block:: bash

        salt '*' drbd.overview
    '''
    cmd = 'drbd-overview'
    for line in __salt__['cmd.run'](cmd).splitlines():
        ret = {}
        fields = line.strip().split()
        minnum = fields[0].split(':')[0]
        device = fields[0].split(':')[1]
        connstate = fields[1]
        role = fields[2].split('/')
        localrole = role[0]
        partnerrole = role[1]
        diskstate = fields[3].split('/')
        localdiskstate = diskstate[0]
        partnerdiskstate = diskstate[1]
        if localdiskstate == "UpToDate":
            if partnerdiskstate == "UpToDate":
                if fields[4]:
                    mountpoint = fields[4]
                    fs_mounted = fields[5]
                    totalsize = fields[6]
                    usedsize = fields[7]
                    remainsize = fields[8]
                    perc = fields[9]
                    ret = {
                        'minor number': minnum,
                        'device': device,
                        'connection state': connstate,
                        'local role': localrole,
                        'partner role': partnerrole,
                        'local disk state': localdiskstate,
                        'partner disk state': partnerdiskstate,
                        'mountpoint': mountpoint,
                        'fs': fs_mounted,
                        'total size': totalsize,
                        'used': usedsize,
                        'remains': remainsize,
                        'percent': perc,
                    }
                else:
                    ret = {
                        'minor number': minnum,
                        'device': device,
                        'connection state': connstate,
                        'local role': localrole,
                        'partner role': partnerrole,
                        'local disk state': localdiskstate,
                        'partner disk state': partnerdiskstate,
                    }
            else:
                syncbar = fields[4]
                synced = fields[6]
                syncedbytes = fields[7]
                sync = synced+syncedbytes
                ret = {
                    'minor number': minnum,
                    'device': device,
                    'connection state': connstate,
                    'local role': localrole,
                    'partner role': partnerrole,
                    'local disk state': localdiskstate,
                    'partner disk state': partnerdiskstate,
                    'synchronisation: ': syncbar,
                    'synched': sync,
                }
    return ret
<commit_msg>Making salt.modules.drbd python3 compatible<commit_after># -*- coding: utf-8 -*-
'''
DRBD administration module
'''
from __future__ import absolute_import

import logging

log = logging.getLogger(__name__)

def overview():
    '''
    Show status of the DRBD devices

    CLI Example:

    .. code-block:: bash

        salt '*' drbd.overview
    '''
    cmd = 'drbd-overview'
    for line in __salt__['cmd.run'](cmd).splitlines():
        ret = {}
        fields = line.strip().split()
        minnum = fields[0].split(':')[0]
        device = fields[0].split(':')[1]
        connstate = fields[1]
        role = fields[2].split('/')
        localrole = role[0]
        partnerrole = role[1]
        diskstate = fields[3].split('/')
        localdiskstate = diskstate[0]
        partnerdiskstate = diskstate[1]
        if localdiskstate == "UpToDate":
            if partnerdiskstate == "UpToDate":
                if fields[4]:
                    mountpoint = fields[4]
                    fs_mounted = fields[5]
                    totalsize = fields[6]
                    usedsize = fields[7]
                    remainsize = fields[8]
                    perc = fields[9]
                    ret = {
                        'minor number': minnum,
                        'device': device,
                        'connection state': connstate,
                        'local role': localrole,
                        'partner role': partnerrole,
                        'local disk state': localdiskstate,
                        'partner disk state': partnerdiskstate,
                        'mountpoint': mountpoint,
                        'fs': fs_mounted,
                        'total size': totalsize,
                        'used': usedsize,
                        'remains': remainsize,
                        'percent': perc,
                    }
                else:
                    ret = {
                        'minor number': minnum,
                        'device': device,
                        'connection state': connstate,
                        'local role': localrole,
                        'partner role': partnerrole,
                        'local disk state': localdiskstate,
                        'partner disk state': partnerdiskstate,
                    }
            else:
                syncbar = fields[4]
                synced = fields[6]
                syncedbytes = fields[7]
                sync = synced+syncedbytes
                ret = {
                    'minor number': minnum,
                    'device': device,
                    'connection state': connstate,
                    'local role': localrole,
                    'partner role': partnerrole,
                    'local disk state': localdiskstate,
                    'partner disk state': partnerdiskstate,
                    'synchronisation: ': syncbar,
                    'synched': sync,
                }
    return ret
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''
DRBD administration module
'''
from __future__ import absolute_import, print_function, unicode_literals

import logging

log = logging.getLogger(__name__)

def _analyse_overview_field(content):
    if "(" in content:
        # Output like "Connected(2*)" or "UpToDate(2*)"
        return content.split("(")[0], content.split("(")[0]
    elif "/" in content:
        # Output like "Primar/Second" or "UpToDa/UpToDa"
        return content.split("/")[0], content.split("/")[1]

    return content, ""

def overview():
    '''
    Show status of the DRBD devices, support two nodes only.

    CLI Example:

    .. code-block:: bash

        salt '*' drbd.overview
    '''
    cmd = 'drbd-overview'
    for line in __salt__['cmd.run'](cmd).splitlines():
        ret = {}
        fields = line.strip().split()
        minnum = fields[0].split(':')[0]
        device = fields[0].split(':')[1]
        connstate, _ = _analyse_overview_field(fields[1])
        localrole, partnerrole = _analyse_overview_field(fields[2])
        localdiskstate, partnerdiskstate = _analyse_overview_field(fields[3])
        if localdiskstate.startswith("UpTo"):
            if partnerdiskstate.startswith("UpTo"):
                if len(fields) >= 5:
                    mountpoint = fields[4]
                    fs_mounted = fields[5]
                    totalsize = fields[6]
                    usedsize = fields[7]
                    remainsize = fields[8]
                    perc = fields[9]
                    ret = {
                        'minor number': minnum,
                        'device': device,
                        'connection state': connstate,
                        'local role': localrole,
                        'partner role': partnerrole,
                        'local disk state': localdiskstate,
                        'partner disk state': partnerdiskstate,
                        'mountpoint': mountpoint,
                        'fs': fs_mounted,
                        'total size': totalsize,
                        'used': usedsize,
                        'remains': remainsize,
                        'percent': perc,
                    }
                else:
                    ret = {
                        'minor number': minnum,
                        'device': device,
                        'connection state': connstate,
                        'local role': localrole,
                        'partner role': partnerrole,
                        'local disk state': localdiskstate,
                        'partner disk state': partnerdiskstate,
                    }
            else:
                syncbar = fields[4]
                synced = fields[6]
                syncedbytes = fields[7]
                sync = synced+syncedbytes
                ret = {
                    'minor number': minnum,
                    'device': device,
                    'connection state': connstate,
                    'local role': localrole,
                    'partner role': partnerrole,
                    'local disk state': localdiskstate,
                    'partner disk state': partnerdiskstate,
                    'synchronisation: ': syncbar,
                    'synched': sync,
                }
    return ret
<commit_msg>Fix the error of pylint.<commit_after># -*- coding: utf-8 -*-
'''
DRBD administration module
'''
from __future__ import absolute_import, print_function, unicode_literals

import logging

log = logging.getLogger(__name__)

def _analyse_overview_field(content):
    if "(" in content:
        # Output like "Connected(2*)" or "UpToDate(2*)"
        return content.split("(")[0], content.split("(")[0]
    elif "/" in content:
        # Output like "Primar/Second" or "UpToDa/UpToDa"
        return content.split("/")[0], content.split("/")[1]

    return content, ""

def overview():
    '''
    Show status of the DRBD devices, support two nodes only.

    CLI Example:

    .. code-block:: bash

        salt '*' drbd.overview
    '''
    cmd = 'drbd-overview'
    for line in __salt__['cmd.run'](cmd).splitlines():
        ret = {}
        fields = line.strip().split()
        minnum = fields[0].split(':')[0]
        device = fields[0].split(':')[1]
        connstate, _ = _analyse_overview_field(fields[1])
        localrole, partnerrole = _analyse_overview_field(fields[2])
        localdiskstate, partnerdiskstate = _analyse_overview_field(fields[3])
        if localdiskstate.startswith("UpTo"):
            if partnerdiskstate.startswith("UpTo"):
                if len(fields) >= 5:
                    mountpoint = fields[4]
                    fs_mounted = fields[5]
                    totalsize = fields[6]
                    usedsize = fields[7]
                    remainsize = fields[8]
                    perc = fields[9]
                    ret = {
                        'minor number': minnum,
                        'device': device,
                        'connection state': connstate,
                        'local role': localrole,
                        'partner role': partnerrole,
                        'local disk state': localdiskstate,
                        'partner disk state': partnerdiskstate,
                        'mountpoint': mountpoint,
                        'fs': fs_mounted,
                        'total size': totalsize,
                        'used': usedsize,
                        'remains': remainsize,
                        'percent': perc,
                    }
                else:
                    ret = {
                        'minor number': minnum,
                        'device': device,
                        'connection state': connstate,
                        'local role': localrole,
                        'partner role': partnerrole,
                        'local disk state': localdiskstate,
                        'partner disk state': partnerdiskstate,
                    }
            else:
                syncbar = fields[4]
                synced = fields[6]
                syncedbytes = fields[7]
                sync = synced+syncedbytes
                ret = {
                    'minor number': minnum,
                    'device': device,
                    'connection state': connstate,
                    'local role': localrole,
                    'partner role': partnerrole,
                    'local disk state': localdiskstate,
                    'partner disk state': partnerdiskstate,
                    'synchronisation: ': syncbar,
                    'synched': sync,
                }
    return ret
<|endoftext|>


<commit_before>import sys
if sys.version_info >= (3,):
    import builtins
    if not hasattr(builtins, "WindowsError"):
        class WindowsError(Exception):
            pass
    else:
        WindowsError = builtins.WindowsError
else:
    import __builtin__
    if not hasattr(__builtin__, "WindowsError"):
        class WindowsError(Exception):
            pass
    else:
        WindowsError = __builtin__.WindowsError

class YakuError(Exception):
    pass

class TaskRunFailure(YakuError):
    def __init__(self, cmd, explain=None):
        self.cmd = cmd
        self.explain = explain

    def __str__(self):
        ret = "cmd %s failed: \n\n%s" % (" ".join(self.cmd), self.explain)
        return ret.encode("utf-8")

class UnknownTask(YakuError):
    pass

class ToolNotFound(YakuError):
    pass
<commit_msg>BUG: fix encoding issue on python 3.<commit_after>import sys
if sys.version_info >= (3,):
    import builtins
    if not hasattr(builtins, "WindowsError"):
        class WindowsError(Exception):
            pass
    else:
        WindowsError = builtins.WindowsError
else:
    import __builtin__
    if not hasattr(__builtin__, "WindowsError"):
        class WindowsError(Exception):
            pass
    else:
        WindowsError = __builtin__.WindowsError

class YakuError(Exception):
    pass

class TaskRunFailure(YakuError):
    def __init__(self, cmd, explain=None):
        self.cmd = cmd
        self.explain = explain

    def __str__(self):
        ret = "cmd %s failed: \n\n%s" % (" ".join(self.cmd), self.explain)
        if sys.version_info < (3,):
            return ret.encode("utf-8")
        else:
            return ret

class UnknownTask(YakuError):
    pass

class ToolNotFound(YakuError):
    pass
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''
The function cache system allows for data to be stored on the master so it can be easily read by other minions
'''

# Import python libs
from __future__ import absolute_import
import copy
import logging
import time
import traceback

# Import salt libs
import salt.crypt
import salt.payload
import salt.utils
import salt.utils.network
import salt.utils.event
from salt.exceptions import SaltClientError

# Import 3rd-party libs
import salt.ext.six as six

MINE_INTERNAL_KEYWORDS = frozenset([
    '__pub_user',
    '__pub_arg',
    '__pub_fun',
    '__pub_jid',
    '__pub_tgt',
    '__pub_tgt_type',
    '__pub_ret'
])

__proxyenabled__ = ['*']

log = logging.getLogger(__name__)

def _auth():
    '''
    Return the auth object
    '''
    if 'auth' not in __context__:
        try:
            __context__['auth'] = salt.crypt.SAuth(__opts__)
        except SaltClientError:
            log.error('Could not authenticate with master.'
                      'Mine data will not be transmitted.')
    return __context__['auth']

def _mine_function_available(func):
    if func not in __salt__:
        log.error('Function {0} in mine_functions not available'
                 .format(func))
        return False
    return True

def _mine_send(load, opts):
    eventer = salt.utils.event.MinionEvent(opts, listen=False)
    event_ret = eventer.fire_event(load, '_minion_mine')
    # We need to pause here to allow for the decoupled nature of
    # events time to allow the mine to propagate
    time.sleep(0.5)
    return event_ret

def _mine_get(load, opts):
    if opts.get('transport', '') in ('zeromq', 'tcp'):
        try:
            load['tok'] = _auth().gen_token('salt')
        except AttributeError:
            log.error('Mine could not authenticate with master. '
                      'Mine could not be retrieved.'
                      )
            return False
    channel = salt.transport.Channel.factory(opts)
    ret = channel.send(load)
    return ret

def update(clear=False):
    '''
    Execute the configured functions and send the data back up to the master.
    The functions to be executed are merged from the master config, pillar and
    minion config under the option `mine_functions`:

    .. code-block:: yaml

        mine_functions:
          network.ip_addrs:
            - eth0
          disk.usage: []

    The function cache will be populated with information from executing these
    functions

    CLI Example:

    .. code-block:: bash

        salt '*' mine.update
    '''
    m_data = __salt__['config.merge']('mine_functions', {})
    # If we don't have any mine functions configured, then we should just bail out
    if not m_data:
        return

    data = {}
    for func in m_data:
        try:
            if m_data[func] and isinstance(m_data[func], dict):
                mine_func = m_data[func].pop('mine_function', func)
                if not _mine_function_available(mine_func):
                    continue
                data[func] = __salt__[mine_func](**m_data[func])
            elif m_data[func] and isinstance(m_data[func], list):
                mine_func = func
                if isinstance(m_data[func][0], dict) and 'mine_function' in m_data[func][0]:
                    mine_func = m_data[func][0]['mine_function']
                    m_data[func].pop(0)

                if not _mine_function_available(mine_func):
                    continue
                data[func] = __salt__[mine_func](*m_data[func])
            else:
                if not _mine_function_available(func):
                    continue
                data[func] = __salt__[func]()
        except Exception:
            trace = traceback.format_exc()
            log.error('Function {0} in mine_functions failed to execute'
                      .format(func))
            log.debug('Error: {0}'.format(trace))
            continue
    if __opts__['file_client'] == 'local':
        if not clear:
            old = __salt__['data.get']('mine_cache')
            if isinstance(old, dict):
                old.update(data)
                data = old
        return __salt__['data.update']('mine_cache', data)
    load = {
            'cmd': '_mine',
            'data': data,
            'id': __opts__['id'],
            'clear': clear,
    }
    return _mine_send(load, __opts__)

def send(func, *args, **kwargs):
    '''
    Send a specific function to the mine.

    CLI Example:

    .. code-block:: bash

        salt '*' mine.send network.ip_addrs eth0
        salt '*' mine.send eth0_ip_addrs mine_function=network.ip_addrs eth0
    '''
    kwargs = salt.utils.clean_kwargs(**kwargs)
    mine_func = kwargs.pop('mine_function', func)
    if mine_func not in __salt__:
        return False
    data = {}
    arg_data = salt.utils.arg_lookup(__salt__[mine_func])
    func_data = copy.deepcopy(kwargs)
    for ind, _ in enumerate(arg_data.get('args', [])):
        try:
            func_data[arg_data['args'][ind]] = args[ind]
        except IndexError:
            # Safe error, arg may be in kwargs
            pass
    f_call = salt.utils.format_call(__salt__[mine_func],
                                    func_data,
                                    expected_extra_kws=MINE_INTERNAL_KEYWORDS)
    for arg in args:
        if arg not in f_call['args']:
            f_call['args'].append(arg)
    try:
        if 'kwargs' in f_call:
            data[func] = __salt__[mine_func](*f_call['args'], **f_call['kwargs'])
        else:
            data[func] = __salt__[mine_func](*f_call['args'])
    except Exception as exc:
        log.error('Function {0} in mine.send failed to execute: {1}'
                  .format(mine_func, exc))
        return False
    if __opts__['file_client'] == 'local':
        old = __salt__['data.get']('mine_cache')
        if isinstance(old, dict):
            old.update(data)
            data = old
        return __salt__['data.update']('mine_cache', data)
    load = {
            'cmd': '_mine',
            'data': data,
            'id': __opts__['id'],
    }
    return _mine_send(load, __opts__)

def get(tgt,
        fun,
        tgt_type='glob',
        exclude_minion=False,
        expr_form=None):
    '''
    Get data from the mine based on the target, function and tgt_type

    Targets can be matched based on any standard matching system that can be
    matched on the master via these keywords:

    - glob
    - pcre
    - grain
    - grain_pcre
    - compound
    - pillar
    - pillar_pcre

    Note that all pillar matches, whether using the compound matching system or
    the pillar matching system, will be exact matches, with globbing disabled.

    exclude_minion
        Excludes the current minion from the result set

    CLI Example:

    .. code-block:: bash

        salt '*' mine.get '*' network.interfaces
        salt '*' mine.get 'os:Fedora' network.interfaces grain
        salt '*' mine.get 'os:Fedora and S@192.168.5.0/24' network.ipaddrs compound

    .. seealso:: Retrieving Mine data from Pillar and Orchestrate

        This execution module is intended to be executed on minions.
        Master-side operations such as Pillar or Orchestrate that require Mine
        data should use the :py:mod:`Mine Runner module <salt.runners.mine>`
        instead; it can be invoked from a Pillar SLS file using the
        :py:func:`saltutil.runner <salt.modules.saltutil.runner>` module. For
        example:

        .. code-block:: yaml

            {% set minion_ips = salt.saltutil.runner('mine.get',
                tgt='*',
                fun='network.ip_addrs',
                tgt_type='glob') %}
    '''
    # remember to remove the expr_form argument from this function when
    # performing the cleanup on this deprecation.
    if expr_form is not None:
        salt.utils.warn_until(
            'Fluorine',
            'the target type should be passed using the \'tgt_type\' '
            'argument instead of \'expr_form\'. Support for using '
            '\'expr_form\' will be removed in Salt Fluorine.'
        )
        tgt_type = expr_form

    if __opts__['file_client'] == 'local':
        ret = {}
        is_target = {'glob': __salt__['match.glob'],
                     'pcre': __salt__['match.pcre'],
                     'list': __salt__['match.list'],
                     'grain': __salt__['match.grain'],
                     'grain_pcre': __salt__['match.grain_pcre'],
                     'ipcidr': __salt__['match.ipcidr'],
                     'compound': __salt__['match.compound'],
                     'pillar': __salt__['match.pillar'],
                     'pillar_pcre': __salt__['match.pillar_pcre'],
                     }[tgt_type](tgt)
        if is_target:
            data = __salt__['data.get']('mine_cache')
            if isinstance(data, dict) and fun in data:
                ret[__opts__['id']] = data[fun]
        return ret
    load = {
            'cmd': '_mine_get',
            'id': __opts__['id'],
            'tgt': tgt,
            'fun': fun,
            'tgt_type': tgt_type,
    }
    ret = _mine_get(load, __opts__)
    if exclude_minion:
        if __opts__['id'] in ret:
            del ret[__opts__['id']]
    return ret

def delete(fun):
    '''
    Remove specific function contents of minion. Returns True on success.

    CLI Example:

    .. code-block:: bash

        salt '*' mine.delete 'network.interfaces'
    '''
    if __opts__['file_client'] == 'local':
        data = __salt__['data.get']('mine_cache')
        if isinstance(data, dict) and fun in data:
            del data[fun]
        return __salt__['data.update']('mine_cache', data)
    load = {
            'cmd': '_mine_delete',
            'id': __opts__['id'],
            'fun': fun,
    }
    return _mine_send(load, __opts__)

def flush():
    '''
    Remove all mine contents of minion. Returns True on success.

    CLI Example:

    .. code-block:: bash

        salt '*' mine.flush
    '''
    if __opts__['file_client'] == 'local':
        return __salt__['data.update']('mine_cache', {})
    load = {
            'cmd': '_mine_flush',
            'id': __opts__['id'],
    }
    return _mine_send(load, __opts__)

def get_docker(interfaces=None, cidrs=None, with_container_id=False):
    '''
    Get all mine data for 'docker.get_containers' and run an aggregation
    routine. The "interfaces" parameter allows for specifying which network
    interfaces to select ip addresses from. The "cidrs" parameter allows for
    specifying a list of cidrs which the ip address must match.

    with_container_id
        Boolean, to expose container_id in the list of results

        .. versionadded:: 2015.8.2

    CLI Example:

    .. code-block:: bash

        salt '*' mine.get_docker
        salt '*' mine.get_docker interfaces='eth0'
        salt '*' mine.get_docker interfaces='["eth0", "eth1"]'
        salt '*' mine.get_docker cidrs='107.170.147.0/24'
        salt '*' mine.get_docker cidrs='["107.170.147.0/24", "172.17.42.0/24"]'
        salt '*' mine.get_docker interfaces='["eth0", "eth1"]' cidrs='["107.170.147.0/24", "172.17.42.0/24"]'
    '''
    # Enforce that interface and cidr are lists
    if interfaces:
        interface_ = []
        interface_.extend(interfaces if isinstance(interfaces, list) else [interfaces])
        interfaces = interface_
    if cidrs:
        cidr_ = []
        cidr_.extend(cidrs if isinstance(cidrs, list) else [cidrs])
        cidrs = cidr_

    # Get docker info
    cmd = 'dockerng.ps'
    docker_hosts = get('*', cmd)

    proxy_lists = {}

    # Process docker info
    for containers in six.itervalues(docker_hosts):
        host = containers.pop('host')
        host_ips = []

        # Prepare host_ips list
        if not interfaces:
            for info in six.itervalues(host['interfaces']):
                if 'inet' in info:
                    for ip_ in info['inet']:
                        host_ips.append(ip_['address'])
        else:
            for interface in interfaces:
                if interface in host['interfaces']:
                    if 'inet' in host['interfaces'][interface]:
                        for item in host['interfaces'][interface]['inet']:
                            host_ips.append(item['address'])
        host_ips = list(set(host_ips))

        # Filter out ips from host_ips with cidrs
        if cidrs:
            good_ips = []
            for cidr in cidrs:
                for ip_ in host_ips:
                    if salt.utils.network.in_subnet(cidr, [ip_]):
                        good_ips.append(ip_)
            host_ips = list(set(good_ips))

        # Process each container
        for container in six.itervalues(containers):
            container_id = container['Info']['Id']
            if container['Image'] not in proxy_lists:
                proxy_lists[container['Image']] = {}
            for dock_port in container['Ports']:
                # IP exists only if port is exposed
                ip_address = dock_port.get('IP')
                # If port is 0.0.0.0, then we must get the docker host IP
                if ip_address == '0.0.0.0':
                    for ip_ in host_ips:
                        containers = proxy_lists[container['Image']].setdefault('ipv4', {}).setdefault(dock_port['PrivatePort'], [])
                        container_network_footprint = '{0}:{1}'.format(ip_, dock_port['PublicPort'])
                        if with_container_id:
                            value = (container_network_footprint, container_id)
                        else:
                            value = container_network_footprint
                        if value not in containers:
                            containers.append(value)
                elif ip_address:
                    containers = proxy_lists[container['Image']].setdefault('ipv4', {}).setdefault(dock_port['PrivatePort'], [])
                    container_network_footprint = '{0}:{1}'.format(dock_port['IP'], dock_port['PublicPort'])
                    if with_container_id:
                        value = (container_network_footprint, container_id)
                    else:
                        value = container_network_footprint
                    if value not in containers:
                        containers.append(value)

    return proxy_lists

def valid():
    '''
    List valid entries in mine configuration.

    CLI Example:

    .. code-block:: bash

        salt '*' mine.valid
    '''
    m_data = __salt__['config.merge']('mine_functions', {})
    # If we don't have any mine functions configured, then we should just bail out
    if not m_data:
        return

    data = {}
    for func in m_data:
        if m_data[func] and isinstance(m_data[func], dict):
            mine_func = m_data[func].pop('mine_function', func)
            if not _mine_function_available(mine_func):
                continue
            data[func] = {mine_func: m_data[func]}
        elif m_data[func] and isinstance(m_data[func], list):
            mine_func = func
            if isinstance(m_data[func][0], dict) and 'mine_function' in m_data[func][0]:
                mine_func = m_data[func][0]['mine_function']
                m_data[func].pop(0)

            if not _mine_function_available(mine_func):
                continue
            data[func] = {mine_func: m_data[func]}
        else:
            if not _mine_function_available(func):
                continue
            data[func] = m_data[func]

    return data
<commit_msg>`mine.update` only on certain functions (#38874)<commit_after># -*- coding: utf-8 -*-
'''
The function cache system allows for data to be stored on the master so it can be easily read by other minions
'''

# Import python libs
from __future__ import absolute_import
import copy
import logging
import time
import traceback

# Import salt libs
import salt.crypt
import salt.payload
import salt.utils
import salt.utils.network
import salt.utils.event
from salt.exceptions import SaltClientError

# Import 3rd-party libs
import salt.ext.six as six

MINE_INTERNAL_KEYWORDS = frozenset([
    '__pub_user',
    '__pub_arg',
    '__pub_fun',
    '__pub_jid',
    '__pub_tgt',
    '__pub_tgt_type',
    '__pub_ret'
])

__proxyenabled__ = ['*']

log = logging.getLogger(__name__)

def _auth():
    '''
    Return the auth object
    '''
    if 'auth' not in __context__:
        try:
            __context__['auth'] = salt.crypt.SAuth(__opts__)
        except SaltClientError:
            log.error('Could not authenticate with master.'
                      'Mine data will not be transmitted.')
    return __context__['auth']

def _mine_function_available(func):
    if func not in __salt__:
        log.error('Function {0} in mine_functions not available'
                 .format(func))
        return False
    return True

def _mine_send(load, opts):
    eventer = salt.utils.event.MinionEvent(opts, listen=False)
    event_ret = eventer.fire_event(load, '_minion_mine')
    # We need to pause here to allow for the decoupled nature of
    # events time to allow the mine to propagate
    time.sleep(0.5)
    return event_ret

def _mine_get(load, opts):
    if opts.get('transport', '') in ('zeromq', 'tcp'):
        try:
            load['tok'] = _auth().gen_token('salt')
        except AttributeError:
            log.error('Mine could not authenticate with master. '
                      'Mine could not be retrieved.'
                      )
            return False
    channel = salt.transport.Channel.factory(opts)
    ret = channel.send(load)
    return ret

def update(clear=False, mine_functions=None):
    '''
    Execute the configured functions and send the data back up to the master.
    The functions to be executed are merged from the master config, pillar and
    minion config under the option `mine_functions`:

    .. code-block:: yaml

        mine_functions:
          network.ip_addrs:
            - eth0
          disk.usage: []

    This function accepts the following arguments:

    clear: False
        Boolean flag specifying whether updating will clear the existing
        mines, or will update. Default: `False` (update).

    mine_functions
        Update the mine data on certain functions only.
        This feature can be used when updating the mine for functions
        that require refresh at different intervals than the rest of
        the functions specified under `mine_functions` in the
        minion/master config or pillar.
        A potential use would be together with the `scheduler`, for example:

        .. code-block:: yaml

            schedule:
              lldp_mine_update:
                function: mine.update
                kwargs:
                    mine_functions:
                      net.lldp: []
                hours: 12

        In the example above, the mine for `net.lldp` would be refreshed
        every 12 hours, while  `network.ip_addrs` would continue to be updated
        as specified in `mine_interval`.

    The function cache will be populated with information from executing these
    functions

    CLI Example:

    .. code-block:: bash

        salt '*' mine.update
    '''
    m_data = {}
    if not mine_functions:
        m_data = __salt__['config.merge']('mine_functions', {})
        # If we don't have any mine functions configured, then we should just bail out
        if not m_data:
            return
    elif mine_functions and isinstance(mine_functions, list):
        m_data = dict((fun, {}) for fun in mine_functions)
    elif mine_functions and isinstance(mine_functions, dict):
        m_data = mine_functions
    else:
        return

    data = {}
    for func in m_data:
        try:
            if m_data[func] and isinstance(m_data[func], dict):
                mine_func = m_data[func].pop('mine_function', func)
                if not _mine_function_available(mine_func):
                    continue
                data[func] = __salt__[mine_func](**m_data[func])
            elif m_data[func] and isinstance(m_data[func], list):
                mine_func = func
                if isinstance(m_data[func][0], dict) and 'mine_function' in m_data[func][0]:
                    mine_func = m_data[func][0]['mine_function']
                    m_data[func].pop(0)

                if not _mine_function_available(mine_func):
                    continue
                data[func] = __salt__[mine_func](*m_data[func])
            else:
                if not _mine_function_available(func):
                    continue
                data[func] = __salt__[func]()
        except Exception:
            trace = traceback.format_exc()
            log.error('Function {0} in mine_functions failed to execute'
                      .format(func))
            log.debug('Error: {0}'.format(trace))
            continue
    if __opts__['file_client'] == 'local':
        if not clear:
            old = __salt__['data.get']('mine_cache')
            if isinstance(old, dict):
                old.update(data)
                data = old
        return __salt__['data.update']('mine_cache', data)
    load = {
            'cmd': '_mine',
            'data': data,
            'id': __opts__['id'],
            'clear': clear,
    }
    return _mine_send(load, __opts__)

def send(func, *args, **kwargs):
    '''
    Send a specific function to the mine.

    CLI Example:

    .. code-block:: bash

        salt '*' mine.send network.ip_addrs eth0
        salt '*' mine.send eth0_ip_addrs mine_function=network.ip_addrs eth0
    '''
    kwargs = salt.utils.clean_kwargs(**kwargs)
    mine_func = kwargs.pop('mine_function', func)
    if mine_func not in __salt__:
        return False
    data = {}
    arg_data = salt.utils.arg_lookup(__salt__[mine_func])
    func_data = copy.deepcopy(kwargs)
    for ind, _ in enumerate(arg_data.get('args', [])):
        try:
            func_data[arg_data['args'][ind]] = args[ind]
        except IndexError:
            # Safe error, arg may be in kwargs
            pass
    f_call = salt.utils.format_call(__salt__[mine_func],
                                    func_data,
                                    expected_extra_kws=MINE_INTERNAL_KEYWORDS)
    for arg in args:
        if arg not in f_call['args']:
            f_call['args'].append(arg)
    try:
        if 'kwargs' in f_call:
            data[func] = __salt__[mine_func](*f_call['args'], **f_call['kwargs'])
        else:
            data[func] = __salt__[mine_func](*f_call['args'])
    except Exception as exc:
        log.error('Function {0} in mine.send failed to execute: {1}'
                  .format(mine_func, exc))
        return False
    if __opts__['file_client'] == 'local':
        old = __salt__['data.get']('mine_cache')
        if isinstance(old, dict):
            old.update(data)
            data = old
        return __salt__['data.update']('mine_cache', data)
    load = {
            'cmd': '_mine',
            'data': data,
            'id': __opts__['id'],
    }
    return _mine_send(load, __opts__)

def get(tgt,
        fun,
        tgt_type='glob',
        exclude_minion=False,
        expr_form=None):
    '''
    Get data from the mine based on the target, function and tgt_type

    Targets can be matched based on any standard matching system that can be
    matched on the master via these keywords:

    - glob
    - pcre
    - grain
    - grain_pcre
    - compound
    - pillar
    - pillar_pcre

    Note that all pillar matches, whether using the compound matching system or
    the pillar matching system, will be exact matches, with globbing disabled.

    exclude_minion
        Excludes the current minion from the result set

    CLI Example:

    .. code-block:: bash

        salt '*' mine.get '*' network.interfaces
        salt '*' mine.get 'os:Fedora' network.interfaces grain
        salt '*' mine.get 'os:Fedora and S@192.168.5.0/24' network.ipaddrs compound

    .. seealso:: Retrieving Mine data from Pillar and Orchestrate

        This execution module is intended to be executed on minions.
        Master-side operations such as Pillar or Orchestrate that require Mine
        data should use the :py:mod:`Mine Runner module <salt.runners.mine>`
        instead; it can be invoked from a Pillar SLS file using the
        :py:func:`saltutil.runner <salt.modules.saltutil.runner>` module. For
        example:

        .. code-block:: yaml

            {% set minion_ips = salt.saltutil.runner('mine.get',
                tgt='*',
                fun='network.ip_addrs',
                tgt_type='glob') %}
    '''
    # remember to remove the expr_form argument from this function when
    # performing the cleanup on this deprecation.
    if expr_form is not None:
        salt.utils.warn_until(
            'Fluorine',
            'the target type should be passed using the \'tgt_type\' '
            'argument instead of \'expr_form\'. Support for using '
            '\'expr_form\' will be removed in Salt Fluorine.'
        )
        tgt_type = expr_form

    if __opts__['file_client'] == 'local':
        ret = {}
        is_target = {'glob': __salt__['match.glob'],
                     'pcre': __salt__['match.pcre'],
                     'list': __salt__['match.list'],
                     'grain': __salt__['match.grain'],
                     'grain_pcre': __salt__['match.grain_pcre'],
                     'ipcidr': __salt__['match.ipcidr'],
                     'compound': __salt__['match.compound'],
                     'pillar': __salt__['match.pillar'],
                     'pillar_pcre': __salt__['match.pillar_pcre'],
                     }[tgt_type](tgt)
        if is_target:
            data = __salt__['data.get']('mine_cache')
            if isinstance(data, dict) and fun in data:
                ret[__opts__['id']] = data[fun]
        return ret
    load = {
            'cmd': '_mine_get',
            'id': __opts__['id'],
            'tgt': tgt,
            'fun': fun,
            'tgt_type': tgt_type,
    }
    ret = _mine_get(load, __opts__)
    if exclude_minion:
        if __opts__['id'] in ret:
            del ret[__opts__['id']]
    return ret

def delete(fun):
    '''
    Remove specific function contents of minion. Returns True on success.

    CLI Example:

    .. code-block:: bash

        salt '*' mine.delete 'network.interfaces'
    '''
    if __opts__['file_client'] == 'local':
        data = __salt__['data.get']('mine_cache')
        if isinstance(data, dict) and fun in data:
            del data[fun]
        return __salt__['data.update']('mine_cache', data)
    load = {
            'cmd': '_mine_delete',
            'id': __opts__['id'],
            'fun': fun,
    }
    return _mine_send(load, __opts__)

def flush():
    '''
    Remove all mine contents of minion. Returns True on success.

    CLI Example:

    .. code-block:: bash

        salt '*' mine.flush
    '''
    if __opts__['file_client'] == 'local':
        return __salt__['data.update']('mine_cache', {})
    load = {
            'cmd': '_mine_flush',
            'id': __opts__['id'],
    }
    return _mine_send(load, __opts__)

def get_docker(interfaces=None, cidrs=None, with_container_id=False):
    '''
    Get all mine data for 'docker.get_containers' and run an aggregation
    routine. The "interfaces" parameter allows for specifying which network
    interfaces to select ip addresses from. The "cidrs" parameter allows for
    specifying a list of cidrs which the ip address must match.

    with_container_id
        Boolean, to expose container_id in the list of results

        .. versionadded:: 2015.8.2

    CLI Example:

    .. code-block:: bash

        salt '*' mine.get_docker
        salt '*' mine.get_docker interfaces='eth0'
        salt '*' mine.get_docker interfaces='["eth0", "eth1"]'
        salt '*' mine.get_docker cidrs='107.170.147.0/24'
        salt '*' mine.get_docker cidrs='["107.170.147.0/24", "172.17.42.0/24"]'
        salt '*' mine.get_docker interfaces='["eth0", "eth1"]' cidrs='["107.170.147.0/24", "172.17.42.0/24"]'
    '''
    # Enforce that interface and cidr are lists
    if interfaces:
        interface_ = []
        interface_.extend(interfaces if isinstance(interfaces, list) else [interfaces])
        interfaces = interface_
    if cidrs:
        cidr_ = []
        cidr_.extend(cidrs if isinstance(cidrs, list) else [cidrs])
        cidrs = cidr_

    # Get docker info
    cmd = 'dockerng.ps'
    docker_hosts = get('*', cmd)

    proxy_lists = {}

    # Process docker info
    for containers in six.itervalues(docker_hosts):
        host = containers.pop('host')
        host_ips = []

        # Prepare host_ips list
        if not interfaces:
            for info in six.itervalues(host['interfaces']):
                if 'inet' in info:
                    for ip_ in info['inet']:
                        host_ips.append(ip_['address'])
        else:
            for interface in interfaces:
                if interface in host['interfaces']:
                    if 'inet' in host['interfaces'][interface]:
                        for item in host['interfaces'][interface]['inet']:
                            host_ips.append(item['address'])
        host_ips = list(set(host_ips))

        # Filter out ips from host_ips with cidrs
        if cidrs:
            good_ips = []
            for cidr in cidrs:
                for ip_ in host_ips:
                    if salt.utils.network.in_subnet(cidr, [ip_]):
                        good_ips.append(ip_)
            host_ips = list(set(good_ips))

        # Process each container
        for container in six.itervalues(containers):
            container_id = container['Info']['Id']
            if container['Image'] not in proxy_lists:
                proxy_lists[container['Image']] = {}
            for dock_port in container['Ports']:
                # IP exists only if port is exposed
                ip_address = dock_port.get('IP')
                # If port is 0.0.0.0, then we must get the docker host IP
                if ip_address == '0.0.0.0':
                    for ip_ in host_ips:
                        containers = proxy_lists[container['Image']].setdefault('ipv4', {}).setdefault(dock_port['PrivatePort'], [])
                        container_network_footprint = '{0}:{1}'.format(ip_, dock_port['PublicPort'])
                        if with_container_id:
                            value = (container_network_footprint, container_id)
                        else:
                            value = container_network_footprint
                        if value not in containers:
                            containers.append(value)
                elif ip_address:
                    containers = proxy_lists[container['Image']].setdefault('ipv4', {}).setdefault(dock_port['PrivatePort'], [])
                    container_network_footprint = '{0}:{1}'.format(dock_port['IP'], dock_port['PublicPort'])
                    if with_container_id:
                        value = (container_network_footprint, container_id)
                    else:
                        value = container_network_footprint
                    if value not in containers:
                        containers.append(value)

    return proxy_lists

def valid():
    '''
    List valid entries in mine configuration.

    CLI Example:

    .. code-block:: bash

        salt '*' mine.valid
    '''
    m_data = __salt__['config.merge']('mine_functions', {})
    # If we don't have any mine functions configured, then we should just bail out
    if not m_data:
        return

    data = {}
    for func in m_data:
        if m_data[func] and isinstance(m_data[func], dict):
            mine_func = m_data[func].pop('mine_function', func)
            if not _mine_function_available(mine_func):
                continue
            data[func] = {mine_func: m_data[func]}
        elif m_data[func] and isinstance(m_data[func], list):
            mine_func = func
            if isinstance(m_data[func][0], dict) and 'mine_function' in m_data[func][0]:
                mine_func = m_data[func][0]['mine_function']
                m_data[func].pop(0)

            if not _mine_function_available(mine_func):
                continue
            data[func] = {mine_func: m_data[func]}
        else:
            if not _mine_function_available(func):
                continue
            data[func] = m_data[func]

    return data
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''
Execution module for Cisco NX OS Switches Proxy minions

.. versionadded:: 2016.11.0

For documentation on setting up the nxos proxy minion look in the documentation
for :mod:`salt.proxy.nxos <salt.proxy.nxos>`.
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals

# Import Salt libs
import salt.utils.platform

__proxyenabled__ = ['nxos']
__virtualname__ = 'nxos'

def __virtual__():
    if salt.utils.platform.is_proxy():
        return __virtualname__
    return (False, 'The nxos execution module failed to load: '
            'only available on proxy minions.')

def system_info():
    '''
    Return system information for grains of the NX OS proxy minion

    .. code-block:: bash

        salt '*' nxos.system_info
    '''
    return cmd('system_info')

def cmd(command, *args, **kwargs):
    '''
    run commands from __proxy__
    :mod:`salt.proxy.nxos<salt.proxy.nxos>`

    command
        function from `salt.proxy.nxos` to run

    args
        positional args to pass to `command` function

    kwargs
        key word arguments to pass to `command` function

    .. code-block:: bash

        salt '*' nxos.cmd sendline 'show ver'
        salt '*' nxos.cmd show_run
        salt '*' nxos.cmd check_password username=admin password='$5$lkjsdfoi$blahblahblah' encrypted=True
    '''
    proxy_prefix = __opts__['proxy']['proxytype']
    proxy_cmd = '.'.join([proxy_prefix, command])
    if proxy_cmd not in __proxy__:
        return False
    for k in kwargs:
        if k.startswith('__pub_'):
            kwargs.pop(k)
    return __proxy__[proxy_cmd](*args, **kwargs)
<commit_msg>Ensure kwargs is a list before we attempt to loop through.  Similar fix to https://github.com/rallytime/salt/commit/430c462f34eb4eedf2384e06fbee8dc19b8026f6 in the proxy module.<commit_after># -*- coding: utf-8 -*-
'''
Execution module for Cisco NX OS Switches Proxy minions

.. versionadded:: 2016.11.0

For documentation on setting up the nxos proxy minion look in the documentation
for :mod:`salt.proxy.nxos <salt.proxy.nxos>`.
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals

# Import Salt libs
import salt.utils.platform

__proxyenabled__ = ['nxos']
__virtualname__ = 'nxos'

def __virtual__():
    if salt.utils.platform.is_proxy():
        return __virtualname__
    return (False, 'The nxos execution module failed to load: '
            'only available on proxy minions.')

def system_info():
    '''
    Return system information for grains of the NX OS proxy minion

    .. code-block:: bash

        salt '*' nxos.system_info
    '''
    return cmd('system_info')

def cmd(command, *args, **kwargs):
    '''
    run commands from __proxy__
    :mod:`salt.proxy.nxos<salt.proxy.nxos>`

    command
        function from `salt.proxy.nxos` to run

    args
        positional args to pass to `command` function

    kwargs
        key word arguments to pass to `command` function

    .. code-block:: bash

        salt '*' nxos.cmd sendline 'show ver'
        salt '*' nxos.cmd show_run
        salt '*' nxos.cmd check_password username=admin password='$5$lkjsdfoi$blahblahblah' encrypted=True
    '''
    proxy_prefix = __opts__['proxy']['proxytype']
    proxy_cmd = '.'.join([proxy_prefix, command])
    if proxy_cmd not in __proxy__:
        return False
    for k in list(kwargs):
        if k.startswith('__pub_'):
            kwargs.pop(k)
    return __proxy__[proxy_cmd](*args, **kwargs)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''
Module for running arbitrary tests
'''
from __future__ import absolute_import

# Import Python libs
import logging
import os
import sys
import time
import traceback
import random

# Import Salt libs
import salt
import salt.utils
import salt.version
import salt.loader
import salt.ext.six as six
from salt.utils.decorators import depends

__proxyenabled__ = ['*']

# Don't shadow built-in's.
__func_alias__ = {
    'true_': 'true',
    'false_': 'false'
}

log = logging.getLogger(__name__)

@depends('non_existantmodulename')
def missing_func():
    return 'foo'

def attr_call():
    '''
    Call grains.items via the attribute

    CLI Example:

    .. code-block:: bash

        salt '*' test.attr_call
    '''
    return __salt__.grains.items()

def module_report():
    '''
    Return a dict containing all of the execution modules with a report on
    the overall availability via different references

    CLI Example:

    .. code-block:: bash

        salt '*' test.module_report
    '''
    ret = {'functions': [],
           'function_attrs': [],
           'function_subs': [],
           'modules': [],
           'module_attrs': [],
           'missing_attrs': [],
           'missing_subs': []}
    for ref in __salt__:
        if '.' in ref:
            ret['functions'].append(ref)
        else:
            ret['modules'].append(ref)
            if hasattr(__salt__, ref):
                ret['module_attrs'].append(ref)
            for func in __salt__[ref]:
                full = '{0}.{1}'.format(ref, func)
                if hasattr(getattr(__salt__, ref), func):
                    ret['function_attrs'].append(full)
                if func in __salt__[ref]:
                    ret['function_subs'].append(full)
    for func in ret['functions']:
        if func not in ret['function_attrs']:
            ret['missing_attrs'].append(func)
        if func not in ret['function_subs']:
            ret['missing_subs'].append(func)
    return ret

def echo(text):
    '''
    Return a string - used for testing the connection

    CLI Example:

    .. code-block:: bash

        salt '*' test.echo 'foo bar baz quo qux'
    '''
    return text

def ping():
    '''
    Used to make sure the minion is up and responding. Not an ICMP ping.

    Returns ``True``.

    CLI Example:

    .. code-block:: bash

        salt '*' test.ping
    '''

    if not salt.utils.is_proxy():
        log.debug('test.ping received for minion \'%s\'', __opts__.get('id'))
        return True
    else:
        ping_cmd = __opts__['proxy']['proxytype'] + '.ping'
        if __opts__.get('add_proxymodule_to_opts', False):
            return __opts__['proxymodule'][ping_cmd]()
        else:
            return __proxy__[ping_cmd]()

def sleep(length):
    '''
    Instruct the minion to initiate a process that will sleep for a given
    period of time.

    CLI Example:

    .. code-block:: bash

        salt '*' test.sleep 20
    '''
    time.sleep(int(length))
    return True

def rand_sleep(max=60):
    '''
    Sleep for a random number of seconds, used to test long-running commands
    and minions returning at differing intervals

    CLI Example:

    .. code-block:: bash

        salt '*' test.rand_sleep 60
    '''
    time.sleep(random.randint(0, max))
    return True

def version():
    '''
    Return the version of salt on the minion

    CLI Example:

    .. code-block:: bash

        salt '*' test.version
    '''
    return salt.version.__version__

def versions_information():
    '''
    Report the versions of dependent and system software

    CLI Example:

    .. code-block:: bash

        salt '*' test.versions_information
    '''
    return salt.version.versions_information()

def versions_report():
    '''
    Returns versions of components used by salt

    CLI Example:

    .. code-block:: bash

        salt '*' test.versions_report
    '''
    return '\n'.join(salt.version.versions_report())

versions = salt.utils.alias_function(versions_report, 'versions')

def conf_test():
    '''
    Return the value for test.foo in the minion configuration file, or return
    the default value

    CLI Example:

    .. code-block:: bash

        salt '*' test.conf_test
    '''
    return __salt__['config.option']('test.foo')

def get_opts():
    '''
    Return the configuration options passed to this minion

    CLI Example:

    .. code-block:: bash

        salt '*' test.get_opts
    '''
    return __opts__

def cross_test(func, args=None):
    '''
    Execute a minion function via the __salt__ object in the test
    module, used to verify that the minion functions can be called
    via the __salt__ module.

    CLI Example:

    .. code-block:: bash

        salt '*' test.cross_test file.gid_to_group 0
    '''
    if args is None:
        args = []
    return __salt__[func](*args)

def kwarg(**kwargs):
    '''
    Print out the data passed into the function ``**kwargs``, this is used to
    both test the publication data and cli kwarg passing, but also to display
    the information available within the publication data.

    CLI Example:

    .. code-block:: bash

        salt '*' test.kwarg num=1 txt="two" env='{a: 1, b: "hello"}'
    '''
    return kwargs

def arg(*args, **kwargs):
    '''
    Print out the data passed into the function ``*args`` and ```kwargs``, this
    is used to both test the publication data and cli argument passing, but
    also to display the information available within the publication data.
    Returns {"args": args, "kwargs": kwargs}.

    CLI Example:

    .. code-block:: bash

        salt '*' test.arg 1 "two" 3.1 txt="hello" wow='{a: 1, b: "hello"}'
    '''
    return {"args": args, "kwargs": kwargs}

def arg_type(*args, **kwargs):
    '''
    Print out the types of the args and kwargs. This is used to test the types
    of the args and kwargs passed down to the minion

    CLI Example:

    .. code-block:: bash

           salt '*' test.arg_type 1 'int'
    '''
    ret = {'args': [], 'kwargs': {}}
    # all the args
    for argument in args:
        ret['args'].append(str(type(argument)))

    # all the kwargs
    for key, val in six.iteritems(kwargs):
        ret['kwargs'][key] = str(type(val))

    return ret

def arg_repr(*args, **kwargs):
    '''
    Print out the data passed into the function ``*args`` and ```kwargs``, this
    is used to both test the publication data and cli argument passing, but
    also to display the information available within the publication data.
    Returns {"args": repr(args), "kwargs": repr(kwargs)}.

    CLI Example:

    .. code-block:: bash

        salt '*' test.arg_repr 1 "two" 3.1 txt="hello" wow='{a: 1, b: "hello"}'
    '''
    return {"args": repr(args), "kwargs": repr(kwargs)}

def fib(num):
    '''
    Return the num-th Fibonacci number, and the time it took to compute in
    seconds. Used for performance tests.

    This function is designed to have terrible performance.

    CLI Example:

    .. code-block:: bash

        salt '*' test.fib 3
    '''
    num = int(num)
    if num < 0:
        raise ValueError('Negative number is not allowed!')
    start = time.time()
    if num < 2:
        return num, time.time() - start

    prev = 0
    curr = 1
    i = 1
    while i < num:
        prev, curr = curr, prev + curr
        i += 1

    return curr, time.time() - start

def collatz(start):
    '''
    Execute the collatz conjecture from the passed starting number,
    returns the sequence and the time it took to compute. Used for
    performance tests.

    CLI Example:

    .. code-block:: bash

        salt '*' test.collatz 3
    '''
    start = int(start)
    begin = time.time()
    steps = []
    while start != 1:
        steps.append(start)
        if start > 1:
            if start % 2 == 0:
                start = start / 2
            else:
                start = start * 3 + 1
    return steps, time.time() - begin

def outputter(data):
    '''
    Test the outputter, pass in data to return

    CLI Example:

    .. code-block:: bash

        salt '*' test.outputter foobar
    '''
    return data

def retcode(code=42):
    '''
    Test that the returncode system is functioning correctly

    CLI Example:

    .. code-block:: bash

        salt '*' test.retcode 42
    '''
    __context__['retcode'] = code
    return True

def provider(module):
    '''
    Pass in a function name to discover what provider is being used

    CLI Example:

    .. code-block:: bash

        salt '*' test.provider service
    '''
    func = ''
    for key in __salt__:
        if not key.startswith('{0}.'.format(module)):
            continue
        func = key
        break
    if not func:
        return ''
    pfn = sys.modules[__salt__[func].__module__].__file__
    pfn = os.path.basename(pfn)
    return pfn[:pfn.rindex('.')]

def providers():
    '''
    Return a dict of the provider names and the files that provided them

    CLI Example:

    .. code-block:: bash

        salt '*' test.providers
    '''
    ret = {}
    for funcname in __salt__:
        modname = funcname.split('.')[0]
        if modname not in ret:
            ret[provider(modname)] = modname
    return ret

def not_loaded():
    '''
    List the modules that were not loaded by the salt loader system

    CLI Example:

    .. code-block:: bash

        salt '*' test.not_loaded
    '''
    prov = providers()
    ret = set()
    for mod_dir in salt.loader._module_dirs(__opts__, 'modules', 'module'):
        if not os.path.isabs(mod_dir):
            continue
        if not os.path.isdir(mod_dir):
            continue
        for fn_ in os.listdir(mod_dir):
            if fn_.startswith('_'):
                continue
            name = fn_.split('.')[0]
            if name not in prov:
                ret.add(name)
    return sorted(ret)

def opts_pkg():
    '''
    Return an opts package with the grains and opts for this minion.
    This is primarily used to create the options used for master side
    state compiling routines

    CLI Example:

    .. code-block:: bash

        salt '*' test.opts_pkg
    '''
    ret = {}
    ret.update(__opts__)
    ret['grains'] = __grains__
    return ret

def rand_str(size=9999999999, hash_type=None):
    '''
    Return a random string

        size
            size of the string to generate
        hash_type
            hash type to use

            .. versionadded:: 2015.5.2

    CLI Example:

    .. code-block:: bash

        salt '*' test.rand_str
    '''
    if not hash_type:
        hash_type = __opts__.get('hash_type', 'md5')
    return salt.utils.rand_str(hash_type=hash_type, size=size)

def exception(message='Test Exception'):
    '''
    Raise an exception

    Optionally provide an error message or output the full stack.

    CLI Example:

    .. code-block:: bash

        salt '*' test.exception 'Oh noes!'
    '''
    raise Exception(message)

def stack():
    '''
    Return the current stack trace

    CLI Example:

    .. code-block:: bash

        salt '*' test.stack
    '''
    return ''.join(traceback.format_stack())

def tty(*args, **kwargs):  # pylint: disable=W0613
    '''
    Deprecated! Moved to cmdmod.

    CLI Example:

    .. code-block:: bash

        salt '*' test.tty tty0 'This is a test'
        salt '*' test.tty pts3 'This is a test'
    '''
    return 'ERROR: This function has been moved to cmd.tty'

def try_(module, return_try_exception=False, **kwargs):
    '''
    Try to run a module command. On an exception return None.
    If `return_try_exception` is set True return the exception.
    This can be helpful in templates where running a module might fail as expected.

    CLI Example:

    .. code-block:: bash

        <pre>
        {% for i in range(0,230) %}
            {{ salt['test.try'](module='ipmi.get_users', bmc_host='172.2.2.'+i)|yaml(False) }}
        {% endfor %}
        </pre>
    '''
    try:
        return __salt__[module](**kwargs)
    except Exception as e:
        if return_try_exception:
            return e
    return None

def assertion(assertion):
    '''
    Assert the given argument

    CLI Example:

    .. code-block:: bash

        salt '*' test.assertion False
    '''
    assert assertion

def true_():
    '''
    Always return True

    CLI Example:

    .. code-block:: bash

        salt '*' test.true
    '''
    return True

def false_():
    '''
    Always return False

    CLI Example:

    .. code-block:: bash

        salt '*' test.false
    '''
    return False
<commit_msg>Register try as an alias for try_<commit_after># -*- coding: utf-8 -*-
'''
Module for running arbitrary tests
'''
from __future__ import absolute_import

# Import Python libs
import logging
import os
import sys
import time
import traceback
import random

# Import Salt libs
import salt
import salt.utils
import salt.version
import salt.loader
import salt.ext.six as six
from salt.utils.decorators import depends

__proxyenabled__ = ['*']

# Don't shadow built-in's.
__func_alias__ = {
    'true_': 'true',
    'false_': 'false',
    'try_': 'try',
}

log = logging.getLogger(__name__)

@depends('non_existantmodulename')
def missing_func():
    return 'foo'

def attr_call():
    '''
    Call grains.items via the attribute

    CLI Example:

    .. code-block:: bash

        salt '*' test.attr_call
    '''
    return __salt__.grains.items()

def module_report():
    '''
    Return a dict containing all of the execution modules with a report on
    the overall availability via different references

    CLI Example:

    .. code-block:: bash

        salt '*' test.module_report
    '''
    ret = {'functions': [],
           'function_attrs': [],
           'function_subs': [],
           'modules': [],
           'module_attrs': [],
           'missing_attrs': [],
           'missing_subs': []}
    for ref in __salt__:
        if '.' in ref:
            ret['functions'].append(ref)
        else:
            ret['modules'].append(ref)
            if hasattr(__salt__, ref):
                ret['module_attrs'].append(ref)
            for func in __salt__[ref]:
                full = '{0}.{1}'.format(ref, func)
                if hasattr(getattr(__salt__, ref), func):
                    ret['function_attrs'].append(full)
                if func in __salt__[ref]:
                    ret['function_subs'].append(full)
    for func in ret['functions']:
        if func not in ret['function_attrs']:
            ret['missing_attrs'].append(func)
        if func not in ret['function_subs']:
            ret['missing_subs'].append(func)
    return ret

def echo(text):
    '''
    Return a string - used for testing the connection

    CLI Example:

    .. code-block:: bash

        salt '*' test.echo 'foo bar baz quo qux'
    '''
    return text

def ping():
    '''
    Used to make sure the minion is up and responding. Not an ICMP ping.

    Returns ``True``.

    CLI Example:

    .. code-block:: bash

        salt '*' test.ping
    '''

    if not salt.utils.is_proxy():
        log.debug('test.ping received for minion \'%s\'', __opts__.get('id'))
        return True
    else:
        ping_cmd = __opts__['proxy']['proxytype'] + '.ping'
        if __opts__.get('add_proxymodule_to_opts', False):
            return __opts__['proxymodule'][ping_cmd]()
        else:
            return __proxy__[ping_cmd]()

def sleep(length):
    '''
    Instruct the minion to initiate a process that will sleep for a given
    period of time.

    CLI Example:

    .. code-block:: bash

        salt '*' test.sleep 20
    '''
    time.sleep(int(length))
    return True

def rand_sleep(max=60):
    '''
    Sleep for a random number of seconds, used to test long-running commands
    and minions returning at differing intervals

    CLI Example:

    .. code-block:: bash

        salt '*' test.rand_sleep 60
    '''
    time.sleep(random.randint(0, max))
    return True

def version():
    '''
    Return the version of salt on the minion

    CLI Example:

    .. code-block:: bash

        salt '*' test.version
    '''
    return salt.version.__version__

def versions_information():
    '''
    Report the versions of dependent and system software

    CLI Example:

    .. code-block:: bash

        salt '*' test.versions_information
    '''
    return salt.version.versions_information()

def versions_report():
    '''
    Returns versions of components used by salt

    CLI Example:

    .. code-block:: bash

        salt '*' test.versions_report
    '''
    return '\n'.join(salt.version.versions_report())

versions = salt.utils.alias_function(versions_report, 'versions')

def conf_test():
    '''
    Return the value for test.foo in the minion configuration file, or return
    the default value

    CLI Example:

    .. code-block:: bash

        salt '*' test.conf_test
    '''
    return __salt__['config.option']('test.foo')

def get_opts():
    '''
    Return the configuration options passed to this minion

    CLI Example:

    .. code-block:: bash

        salt '*' test.get_opts
    '''
    return __opts__

def cross_test(func, args=None):
    '''
    Execute a minion function via the __salt__ object in the test
    module, used to verify that the minion functions can be called
    via the __salt__ module.

    CLI Example:

    .. code-block:: bash

        salt '*' test.cross_test file.gid_to_group 0
    '''
    if args is None:
        args = []
    return __salt__[func](*args)

def kwarg(**kwargs):
    '''
    Print out the data passed into the function ``**kwargs``, this is used to
    both test the publication data and cli kwarg passing, but also to display
    the information available within the publication data.

    CLI Example:

    .. code-block:: bash

        salt '*' test.kwarg num=1 txt="two" env='{a: 1, b: "hello"}'
    '''
    return kwargs

def arg(*args, **kwargs):
    '''
    Print out the data passed into the function ``*args`` and ```kwargs``, this
    is used to both test the publication data and cli argument passing, but
    also to display the information available within the publication data.
    Returns {"args": args, "kwargs": kwargs}.

    CLI Example:

    .. code-block:: bash

        salt '*' test.arg 1 "two" 3.1 txt="hello" wow='{a: 1, b: "hello"}'
    '''
    return {"args": args, "kwargs": kwargs}

def arg_type(*args, **kwargs):
    '''
    Print out the types of the args and kwargs. This is used to test the types
    of the args and kwargs passed down to the minion

    CLI Example:

    .. code-block:: bash

           salt '*' test.arg_type 1 'int'
    '''
    ret = {'args': [], 'kwargs': {}}
    # all the args
    for argument in args:
        ret['args'].append(str(type(argument)))

    # all the kwargs
    for key, val in six.iteritems(kwargs):
        ret['kwargs'][key] = str(type(val))

    return ret

def arg_repr(*args, **kwargs):
    '''
    Print out the data passed into the function ``*args`` and ```kwargs``, this
    is used to both test the publication data and cli argument passing, but
    also to display the information available within the publication data.
    Returns {"args": repr(args), "kwargs": repr(kwargs)}.

    CLI Example:

    .. code-block:: bash

        salt '*' test.arg_repr 1 "two" 3.1 txt="hello" wow='{a: 1, b: "hello"}'
    '''
    return {"args": repr(args), "kwargs": repr(kwargs)}

def fib(num):
    '''
    Return the num-th Fibonacci number, and the time it took to compute in
    seconds. Used for performance tests.

    This function is designed to have terrible performance.

    CLI Example:

    .. code-block:: bash

        salt '*' test.fib 3
    '''
    num = int(num)
    if num < 0:
        raise ValueError('Negative number is not allowed!')
    start = time.time()
    if num < 2:
        return num, time.time() - start

    prev = 0
    curr = 1
    i = 1
    while i < num:
        prev, curr = curr, prev + curr
        i += 1

    return curr, time.time() - start

def collatz(start):
    '''
    Execute the collatz conjecture from the passed starting number,
    returns the sequence and the time it took to compute. Used for
    performance tests.

    CLI Example:

    .. code-block:: bash

        salt '*' test.collatz 3
    '''
    start = int(start)
    begin = time.time()
    steps = []
    while start != 1:
        steps.append(start)
        if start > 1:
            if start % 2 == 0:
                start = start / 2
            else:
                start = start * 3 + 1
    return steps, time.time() - begin

def outputter(data):
    '''
    Test the outputter, pass in data to return

    CLI Example:

    .. code-block:: bash

        salt '*' test.outputter foobar
    '''
    return data

def retcode(code=42):
    '''
    Test that the returncode system is functioning correctly

    CLI Example:

    .. code-block:: bash

        salt '*' test.retcode 42
    '''
    __context__['retcode'] = code
    return True

def provider(module):
    '''
    Pass in a function name to discover what provider is being used

    CLI Example:

    .. code-block:: bash

        salt '*' test.provider service
    '''
    func = ''
    for key in __salt__:
        if not key.startswith('{0}.'.format(module)):
            continue
        func = key
        break
    if not func:
        return ''
    pfn = sys.modules[__salt__[func].__module__].__file__
    pfn = os.path.basename(pfn)
    return pfn[:pfn.rindex('.')]

def providers():
    '''
    Return a dict of the provider names and the files that provided them

    CLI Example:

    .. code-block:: bash

        salt '*' test.providers
    '''
    ret = {}
    for funcname in __salt__:
        modname = funcname.split('.')[0]
        if modname not in ret:
            ret[provider(modname)] = modname
    return ret

def not_loaded():
    '''
    List the modules that were not loaded by the salt loader system

    CLI Example:

    .. code-block:: bash

        salt '*' test.not_loaded
    '''
    prov = providers()
    ret = set()
    for mod_dir in salt.loader._module_dirs(__opts__, 'modules', 'module'):
        if not os.path.isabs(mod_dir):
            continue
        if not os.path.isdir(mod_dir):
            continue
        for fn_ in os.listdir(mod_dir):
            if fn_.startswith('_'):
                continue
            name = fn_.split('.')[0]
            if name not in prov:
                ret.add(name)
    return sorted(ret)

def opts_pkg():
    '''
    Return an opts package with the grains and opts for this minion.
    This is primarily used to create the options used for master side
    state compiling routines

    CLI Example:

    .. code-block:: bash

        salt '*' test.opts_pkg
    '''
    ret = {}
    ret.update(__opts__)
    ret['grains'] = __grains__
    return ret

def rand_str(size=9999999999, hash_type=None):
    '''
    Return a random string

        size
            size of the string to generate
        hash_type
            hash type to use

            .. versionadded:: 2015.5.2

    CLI Example:

    .. code-block:: bash

        salt '*' test.rand_str
    '''
    if not hash_type:
        hash_type = __opts__.get('hash_type', 'md5')
    return salt.utils.rand_str(hash_type=hash_type, size=size)

def exception(message='Test Exception'):
    '''
    Raise an exception

    Optionally provide an error message or output the full stack.

    CLI Example:

    .. code-block:: bash

        salt '*' test.exception 'Oh noes!'
    '''
    raise Exception(message)

def stack():
    '''
    Return the current stack trace

    CLI Example:

    .. code-block:: bash

        salt '*' test.stack
    '''
    return ''.join(traceback.format_stack())

def tty(*args, **kwargs):  # pylint: disable=W0613
    '''
    Deprecated! Moved to cmdmod.

    CLI Example:

    .. code-block:: bash

        salt '*' test.tty tty0 'This is a test'
        salt '*' test.tty pts3 'This is a test'
    '''
    return 'ERROR: This function has been moved to cmd.tty'

def try_(module, return_try_exception=False, **kwargs):
    '''
    Try to run a module command. On an exception return None.
    If `return_try_exception` is set True return the exception.
    This can be helpful in templates where running a module might fail as expected.

    CLI Example:

    .. code-block:: bash

        <pre>
        {% for i in range(0,230) %}
            {{ salt['test.try'](module='ipmi.get_users', bmc_host='172.2.2.'+i)|yaml(False) }}
        {% endfor %}
        </pre>
    '''
    try:
        return __salt__[module](**kwargs)
    except Exception as e:
        if return_try_exception:
            return e
    return None

def assertion(assertion):
    '''
    Assert the given argument

    CLI Example:

    .. code-block:: bash

        salt '*' test.assertion False
    '''
    assert assertion

def true_():
    '''
    Always return True

    CLI Example:

    .. code-block:: bash

        salt '*' test.true
    '''
    return True

def false_():
    '''
    Always return False

    CLI Example:

    .. code-block:: bash

        salt '*' test.false
    '''
    return False
<|endoftext|>