#
#   dmi.py - class to wrap DMI Table information
#
#   Copyright 2009 - 2013   Clark Williams <williams@redhat.com>
#   Copyright 2009 - 2013   David Sommerseth <davids@redhat.com>
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License along
#   with this program; if not, write to the Free Software Foundation, Inc.,
#   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#   For the avoidance of doubt the "preferred form" of this code is one which
#   is in an open unpatent encumbered format. Where cryptographic key signing
#   forms part of the process of creating an executable the information
#   including keys needed to generate an equivalently functional executable
#   are deemed to be part of the source code.
#

import sys, os
import libxml2, lxml.etree
from rteval.Log import Log
from rteval import xmlout
from rteval import rtevalConfig

try:
    import dmidecode
    dmidecode_loaded = True
except:
    dmidecode_loaded = False
    pass

def ProcessWarnings():

    if not hasattr(dmidecode, 'get_warnings'):
        return

    warnings = dmidecode.get_warnings()
    if warnings == None:
        return

    for warnline in warnings.split('\n'):
        # Ignore these warnings, as they are "valid" if not running as root
        if warnline == '/dev/mem: Permission denied':
            continue
        if warnline == 'No SMBIOS nor DMI entry point found, sorry.':
            continue

        # All other warnings will be printed
        if len(warnline) > 0:
            print("** DMI WARNING ** %s" % warnline)

    dmidecode.clear_warnings()


class DMIinfo(object):
    '''class used to obtain DMI info via python-dmidecode'''

    def __init__(self, config, logger):
        self.__version = '0.5'

        if not dmidecode_loaded:
            logger.log(Log.DEBUG|Log.WARN, "No dmidecode module found, ignoring DMI tables")
            self.__fake = True
            return

        self.__fake = False
        self.__dmixml = dmidecode.dmidecodeXML()

        self.__xsltparser = self.__load_xslt('rteval_dmi.xsl')


    def __load_xslt(self, fname):
        xsltfile = None
        if os.path.exists(fname):
            xsltfile = open(fname, "r")
        elif rtevalConfig.default_config_search([fname], os.path.isfile):
            xsltfile = open(rtevalConfig.default_config_search([fname], os.path.isfile), "r")

        if xsltfile:
            xsltdoc = lxml.etree.parse(xsltfile)
            ret = lxml.etree.XSLT(xsltdoc)
            xsltfile.close()
            return ret

        raise RuntimeError('Could not locate XSLT template for DMI data (%s)' % (self.sharedir + '/' + fname))


    def MakeReport(self):
        rep_n = libxml2.newNode("DMIinfo")
        rep_n.newProp("version", self.__version)
        if self.__fake:
            rep_n.addContent("No DMI tables available")
            rep_n.newProp("not_available", "1")
        else:
            self.__dmixml.SetResultType(dmidecode.DMIXML_DOC)
            dmiqry = xmlout.convert_libxml2_to_lxml_doc(self.__dmixml.QuerySection('all'))
            resdoc = self.__xsltparser(dmiqry)
            dmi_n = xmlout.convert_lxml_to_libxml2_nodes(resdoc.getroot())
            rep_n.addChild(dmi_n)
        return rep_n



def unit_test(rootdir):
    from pprint import pprint

    class unittest_ConfigDummy(object):
        def __init__(self, rootdir):
            self.config = {'installdir': '/usr/share/rteval'}
            self.__update_vars()

        def __update_vars(self):
            for k in list(self.config.keys()):
                self.__dict__[k] = self.config[k]

    try:
        ProcessWarnings()
        if os.getuid() != 0:
            print("** ERROR **  Must be root to run this unit_test()")
            return 1

        log = Log()
        log.SetLogVerbosity(Log.DEBUG|Log.INFO)
        cfg = unittest_ConfigDummy(rootdir)
        d = DMIinfo(cfg, log)
        dx = d.MakeReport()
        x = libxml2.newDoc("1.0")
        x.setRootElement(dx)
        x.saveFormatFileEnc("-", "UTF-8", 1)
        return 0
    except Exception as e:
        print("** EXCEPTION: %s" % str(e))
        return 1

if __name__ == '__main__':
    sys.exit(unit_test('.'))
