.. versionchanged:: 2016.3.2
        Return the CPU info for this minion

    .. versionchanged:: 2016.11.4
        Added support for AIX

    .. versionchanged:: 2018.3.0
        Added support for NetBSD and OpenBSD

    CLI Example:

    .. code-block:: bash

        salt '*' status.cpuinfo

def cpuinfo():
    '''
    .. versionchanged:: 2016.3.2
        Return the CPU info for this minion

    .. versionchanged:: 2016.11.4
        Added support for AIX

    .. versionchanged:: 2018.3.0
        Added support for NetBSD and OpenBSD

    CLI Example:

    .. code-block:: bash

        salt '*' status.cpuinfo
    '''
    def linux_cpuinfo():
        '''
        linux specific cpuinfo implementation
        '''
        ret = {}
        try:
            with salt.utils.files.fopen('/proc/cpuinfo', 'r') as fp_:
                stats = salt.utils.stringutils.to_unicode(fp_.read())
        except IOError:
            pass
        else:
            for line in stats.splitlines():
                if not line:
                    continue
                comps = line.split(':')
                comps[0] = comps[0].strip()
                if comps[0] == 'flags':
                    ret[comps[0]] = comps[1].split()
                else:
                    ret[comps[0]] = comps[1].strip()
        return ret

    def bsd_cpuinfo():
        '''
        bsd specific cpuinfo implementation
        '''
        bsd_cmd = 'sysctl hw.model hw.ncpu'
        ret = {}
        if __grains__['kernel'].lower() in ['netbsd', 'openbsd']:
            sep = '='
        else:
            sep = ':'

        for line in __salt__['cmd.run'](bsd_cmd).splitlines():
            if not line:
                continue
            comps = line.split(sep)
            comps[0] = comps[0].strip()
            ret[comps[0]] = comps[1].strip()
        return ret

    def sunos_cpuinfo():
        '''
        sunos specific cpuinfo implementation
        '''
        ret = {}
        ret['isainfo'] = {}
        for line in __salt__['cmd.run']('isainfo -x').splitlines():
            # Note: isainfo is per-system and not per-cpu
            # Output Example:
            #amd64: rdrand f16c vmx avx xsave pclmulqdq aes sse4.2 sse4.1 ssse3 popcnt tscp cx16 sse3 sse2 sse fxsr mmx cmov amd_sysc cx8 tsc fpu
            #i386: rdrand f16c vmx avx xsave pclmulqdq aes sse4.2 sse4.1 ssse3 popcnt tscp ahf cx16 sse3 sse2 sse fxsr mmx cmov sep cx8 tsc fpu
            if not line:
                continue
            comps = line.split(':')
            comps[0] = comps[0].strip()
            ret['isainfo'][comps[0]] = sorted(comps[1].strip().split())
        ret['psrinfo'] = []
        procn = None
        for line in __salt__['cmd.run']('psrinfo -v -p').splitlines():
            # Output Example:
            #The physical processor has 6 cores and 12 virtual processors (0-5 12-17)
            #  The core has 2 virtual processors (0 12)
            #  The core has 2 virtual processors (1 13)
            #  The core has 2 virtual processors (2 14)
            #  The core has 2 virtual processors (3 15)
            #  The core has 2 virtual processors (4 16)
            #  The core has 2 virtual processors (5 17)
            #    x86 (GenuineIntel 306E4 family 6 model 62 step 4 clock 2100 MHz)
            #      Intel(r) Xeon(r) CPU E5-2620 v2 @ 2.10GHz
            #The physical processor has 6 cores and 12 virtual processors (6-11 18-23)
            #  The core has 2 virtual processors (6 18)
            #  The core has 2 virtual processors (7 19)
            #  The core has 2 virtual processors (8 20)
            #  The core has 2 virtual processors (9 21)
            #  The core has 2 virtual processors (10 22)
            #  The core has 2 virtual processors (11 23)
            #    x86 (GenuineIntel 306E4 family 6 model 62 step 4 clock 2100 MHz)
            #      Intel(r) Xeon(r) CPU E5-2620 v2 @ 2.10GHz
            #
            # Output Example 2:
            #The physical processor has 4 virtual processors (0-3)
            #  x86 (GenuineIntel 406D8 family 6 model 77 step 8 clock 2400 MHz)
            #        Intel(r) Atom(tm) CPU  C2558  @ 2.40GHz
            if not line:
                continue
            if line.startswith('The physical processor'):
                procn = len(ret['psrinfo'])
                line = line.split()
                ret['psrinfo'].append({})
                if 'cores' in line:
                    ret['psrinfo'][procn]['topology'] = {}
                    ret['psrinfo'][procn]['topology']['cores'] = _number(line[4])
                    ret['psrinfo'][procn]['topology']['threads'] = _number(line[7])
                elif 'virtual' in line:
                    ret['psrinfo'][procn]['topology'] = {}
                    ret['psrinfo'][procn]['topology']['threads'] = _number(line[4])
            elif line.startswith(' ' * 6):  # 3x2 space indent
                ret['psrinfo'][procn]['name'] = line.strip()
            elif line.startswith(' ' * 4):  # 2x2 space indent
                line = line.strip().split()
                ret['psrinfo'][procn]['vendor'] = line[1][1:]
                ret['psrinfo'][procn]['family'] = _number(line[4])
                ret['psrinfo'][procn]['model'] = _number(line[6])
                ret['psrinfo'][procn]['step'] = _number(line[8])
                ret['psrinfo'][procn]['clock'] = "{0} {1}".format(line[10], line[11][:-1])
        return ret

    def aix_cpuinfo():
        '''
        AIX  specific cpuinfo implementation
        '''
        ret = {}
        ret['prtconf'] = []
        ret['lparstat'] = []
        procn = None
        for line in __salt__['cmd.run']('prtconf | grep -i "Processor"', python_shell=True).splitlines():
            # Note: prtconf is per-system and not per-cpu
            # Output Example:
            #prtconf | grep -i "Processor"
            #Processor Type: PowerPC_POWER7
            #Processor Implementation Mode: POWER 7
            #Processor Version: PV_7_Compat
            #Number Of Processors: 2
            #Processor Clock Speed: 3000 MHz
            #  Model Implementation: Multiple Processor, PCI bus
            #  + proc0                                                           Processor
            #  + proc4                                                           Processor
            if not line:
                continue
            procn = len(ret['prtconf'])
            if line.startswith('Processor') or line.startswith('Number'):
                ret['prtconf'].append({})
                comps = line.split(':')
                comps[0] = comps[0].rstrip()
                ret['prtconf'][procn][comps[0]] = comps[1]
            else:
                continue

        for line in __salt__['cmd.run']('prtconf | grep "CPU"', python_shell=True).splitlines():
            # Note: prtconf is per-system and not per-cpu
            # Output Example:
            #CPU Type: 64-bit
            if not line:
                continue
            procn = len(ret['prtconf'])
            if line.startswith('CPU'):
                ret['prtconf'].append({})
                comps = line.split(':')
                comps[0] = comps[0].rstrip()
                ret['prtconf'][procn][comps[0]] = comps[1]
            else:
                continue

        for line in __salt__['cmd.run']('lparstat -i | grep CPU', python_shell=True).splitlines():
            # Note: lparstat is per-system and not per-cpu
            # Output Example:
            #Online Virtual CPUs                        : 2
            #Maximum Virtual CPUs                       : 2
            #Minimum Virtual CPUs                       : 1
            #Maximum Physical CPUs in system            : 32
            #Active Physical CPUs in system             : 32
            #Active CPUs in Pool                        : 32
            #Shared Physical CPUs in system             : 32
            #Physical CPU Percentage                    : 25.00%
            #Desired Virtual CPUs                       : 2
            if not line:
                continue

            procn = len(ret['lparstat'])
            ret['lparstat'].append({})
            comps = line.split(':')
            comps[0] = comps[0].rstrip()
            ret['lparstat'][procn][comps[0]] = comps[1]

        return ret

    # dict that returns a function that does the right thing per platform
    get_version = {
        'Linux': linux_cpuinfo,
        'FreeBSD': bsd_cpuinfo,
        'NetBSD': bsd_cpuinfo,
        'OpenBSD': bsd_cpuinfo,
        'SunOS': sunos_cpuinfo,
        'AIX': aix_cpuinfo,
    }

    errmsg = 'This method is unsupported on the current operating system!'
    return get_version.get(__grains__['kernel'], lambda: errmsg)()