MOON
Server: Apache
System: Linux vps.erhabenn.com.br 3.10.0-1160.119.1.el7.tuxcare.els2.x86_64 #1 SMP Mon Jul 15 12:09:18 UTC 2024 x86_64
User: sonne (1011)
PHP: 8.2.31
Disabled: NONE
Upload Files
File: //opt/microsoft/omsconfig/Scripts/2.6x-2.7x/Scripts/nxPackage.py
#!/usr/bin/env python
# ===================================
# Copyright (c) Microsoft Corporation. All rights reserved.
# See license.txt for license information.
# ===================================
from __future__ import print_function
from __future__ import with_statement
from contextlib import contextmanager

import subprocess
import os
import sys
import time
import imp
import urllib2
import copy
import fnmatch
import re
apt = None
rpm = None
try:
    import apt
except:
    pass
if apt is None:
    try:
        import rpm
    except:
        pass
protocol = imp.load_source('protocol', '../protocol.py')
nxDSCLog = imp.load_source('nxDSCLog', '../nxDSCLog.py')
helperlib = imp.load_source('helperlib', '../helperlib.py')
LG = nxDSCLog.DSCLog

# [ClassVersion("1.0.0"),FriendlyName("nxPackage"),SupportsInventory()]
# class MSFT_nxPackageResource : OMI_BaseResource
# {
#   [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure;
#   [write,ValueMap{"Yum", "Apt", "Zypper"},Values{"Yum", "Apt", "Zypper"}] string PackageManager;
#   [Key,InventoryFilter] string Name;
#   [write] string FilePath;
#   [write] Boolean PackageGroup;
#   [write] string Arguments;
#   [write] uint32 ReturnCode;
#   [read] string PackageDescription;
#   [read] string Publisher;
#   [read] string InstalledOn;
#   [read] uint32 Size;
#   [read] string Version;
#   [read] boolean Installed;
#   [read] string Architecture;

# };

cache_file_dir = '/var/opt/microsoft/dsc/cache/nxPackage'
global show_mof
show_mof = False


def init_vars(Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode):
    if Ensure is not None and Ensure != '':
        Ensure = Ensure.encode('ascii', 'ignore').lower()
    else:
        Ensure = 'present'
    if PackageManager is not None:
        PackageManager = PackageManager.encode('ascii', 'ignore').lower()
    else:
        PackageManager = ''
    if Name is not None:
        Name = Name.encode('ascii', 'ignore')
    else:
        Name = ''
    if FilePath is not None:
        FilePath = FilePath.encode('ascii', 'ignore')
    else:
        FilePath = ''
    if PackageGroup is None:
        PackageGroup = False
    if Arguments is not None:
        Arguments = Arguments.encode('ascii', 'ignore')
    else:
        Arguments = ''
    if ReturnCode is None:
        ReturnCode = 0
    return Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode


def Set_Marshall(Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode):
    if helperlib.CONFIG_SYSCONFDIR_DSC == "omsconfig":
        return [-1]
    (Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode) = init_vars(
        Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode)
    retval = Set(Ensure, PackageManager, Name,
                 FilePath, PackageGroup, Arguments, ReturnCode)
    sys.stdin.flush()
    sys.stderr.flush()
    sys.stdout.flush()
    return retval


def Test_Marshall(Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode):
    if helperlib.CONFIG_SYSCONFDIR_DSC == "omsconfig":
        return [-1]
    (Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode) = init_vars(
        Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode)
    retval = Test(Ensure, PackageManager, Name,
                  FilePath, PackageGroup, Arguments, ReturnCode)
    sys.stdin.flush()
    sys.stderr.flush()
    sys.stdout.flush()
    return retval


def Get_Marshall(Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode):
    arg_names = list(locals().keys())
    (Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode) = init_vars(
        Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode)
    retval = 0
    retval, PackageManager, PackageDescription, Publisher, InstalledOn, Size, Version, Installed, Architecture = Get(
        Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode)
    sys.stdin.flush()
    sys.stderr.flush()
    sys.stdout.flush()
    Ensure = protocol.MI_String(Ensure)
    PackageManager = protocol.MI_String(PackageManager)
    Name = protocol.MI_String(Name)
    FilePath = protocol.MI_String(FilePath)
    PackageGroup = protocol.MI_Boolean(PackageGroup)
    Arguments = protocol.MI_String(Arguments)
    ReturnCode = protocol.MI_Uint32(ReturnCode)
    PackageDescription = protocol.MI_String(PackageDescription)
    Publisher = protocol.MI_String(Publisher)
    InstalledOn = protocol.MI_String(InstalledOn)
    Architecture = protocol.MI_String(Architecture)
    Size = protocol.MI_Uint32(int(Size))
    Version = protocol.MI_String(Version)
    Installed = protocol.MI_Boolean(Installed)
    arg_names.append('PackageDescription')
    arg_names.append('Publisher')
    arg_names.append('InstalledOn')
    arg_names.append('Size')
    arg_names.append('Version')
    arg_names.append('Installed')
    arg_names.append('Architecture')
    retd = {}
    ld = locals()
    for k in arg_names:
        retd[k] = ld[k]
    return retval, retd


def Inventory_Marshall(Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode):
    retval = 0
    sys.stdin.flush()
    sys.stderr.flush()
    sys.stdout.flush()
    (Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode) = init_vars(
        Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode)
    retval, pkgs = GetAll(Ensure, PackageManager, Name,
                          FilePath, PackageGroup, Arguments, ReturnCode)
    for p in pkgs:
        p['Ensure'] = protocol.MI_String('present')
        p['PackageManager'] = protocol.MI_String(PackageManager)
        p['Name'] = protocol.MI_String(p['Name'])
        p['FilePath'] = protocol.MI_String('')
        p['PackageGroup'] = protocol.MI_Boolean(False)
        p['Arguments'] = protocol.MI_String(Arguments)
        p['ReturnCode'] = protocol.MI_Uint32(0)
        p['PackageDescription'] = protocol.MI_String(p['PackageDescription'])
        p['Publisher'] = protocol.MI_String(p['Publisher'])
        p['InstalledOn'] = protocol.MI_String(p['InstalledOn'])
        p['Architecture'] = protocol.MI_String(p['Architecture'])
        p['Size'] = protocol.MI_Uint32(int(p['Size']))
        p['Version'] = protocol.MI_String(p['Version'])
        p['Installed'] = protocol.MI_Boolean(True)
    Inventory = protocol.MI_InstanceA(pkgs)
    retd = {}
    retd["__Inventory"] = Inventory
    return retval, retd

#
# Begin user defined DSC functions
#


def GetPackageSystem():
    ret = None
    for b in ('dpkg', 'rpm'):
        code, out = RunGetOutput('which ' + b, False, False)
        if code is 0:
            ret = b
            break
    return ret


def GetPackageManager():
    ret = None
    # choose default - almost surely one will match.
    for b in ('apt-get', 'zypper', 'yum'):
        code, out = RunGetOutput('which ' + b, False, False)
        if code is 0:
            ret = b
            if ret == 'apt-get':
                ret = 'apt'
            break
    return ret


def ParseArguments(a):
    program_arg = ''
    cmd_arg = ''
    if len(a) > 1:
        if '|' in a:
            program_arg, cmd_arg = a.split('|')
        else:
            program_arg = a
    return program_arg, cmd_arg


class Params:

    def __init__(self, Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode):

        if not ("present" in Ensure or "absent" in Ensure):
            print(
                'ERROR: Param Ensure must be "Present" or "Absent".', file=sys.stdout)
            LG().Log(
                'ERROR', 'ERROR: Param Ensure must be "Present" or "Absent".')
            raise Exception('BadParameter')
        if len(PackageManager) > 0:
            if not ("*" in PackageManager or "yum" in PackageManager or "apt" in PackageManager or "zypper" in PackageManager):
                print(
                    'ERROR: Param PackageManager values are "Yum", "Apt", or "Zypper".', file=sys.stdout)
                LG().Log(
                    'ERROR', 'ERROR: Param PackageManager values are "Yum", "Apt", or "Zypper".')
                raise Exception('BadParameter')
            if PackageManager == "*":
                PackageManager = GetPackageManager()
        if len(Name) < 1 and len(FilePath) < 1:
            print(
                'ERROR: Param Name or FilePath must be set.', file=sys.stdout)
            LG().Log('ERROR', 'ERROR: Param Name or FilePath must be set.')
            raise Exception('BadParameter')
        if len(Name) > 0 and len(FilePath) > 0:
            print('Ignoring Name because FilePath is set.', file=sys.stdout)
            LG().Log('DEBUG', 'Ignoring Name because FilePath is set.')
        print('PackageGroup value is ' + repr(PackageGroup), file=sys.stdout)
        LG().Log('DEBUG',  'PackageGroup value is ' + repr(PackageGroup))
        print('PackageGroup type is ' +
              repr(type(PackageGroup)), file=sys.stdout)
        LG().Log('DEBUG', 'PackageGroup type is ' + repr(type(PackageGroup)))
        if not (True is PackageGroup or False is PackageGroup):
            print(
                'ERROR: Param PackageGroup must be true or false.', file=sys.stdout)
            LG().Log(
                'ERROR', 'ERROR: Param PackageGroup must be true or false.')
            raise Exception('BadParameter')

        self.Ensure = Ensure
        self.PackageManager = PackageManager
        self.Name = Name
        self.FilePath = FilePath
        self.PackageGroup = PackageGroup
        self.Arguments, self.CommandArguments = ParseArguments(Arguments)
        self.ReturnCode = ReturnCode
        self.PackageDescription = ''
        self.Publisher = ''
        self.InstalledOn = ''
        self.Size = 0
        self.Version = ''
        self.Installed = ''
        self.Architecture = ''
        self.PackageSystem = ''

        self.PackageSystem = GetPackageSystem()

        if len(self.PackageManager) < 1:
            self.PackageManager = GetPackageManager()

        if len(self.PackageManager) < 1 or len(self.PackageSystem) < 1:
            print(
                "ERROR: Unable to locate any of 'zypper', 'yum', 'apt-get', 'rpm' or 'dpkg' .", file=sys.stdout)
            LG().Log(
                'ERROR', "ERROR: Unable to locate any of 'zypper', 'yum', 'apt-get', 'rpm' or 'dpkg' .")
            raise Exception('BadParameter')
        self.LocalPath = ''
        self.record_delimiter = '@@'
        self.field_delimiter = '#@#'
        self.cmds = {}
        self.cmds['dpkg'] = {}
        self.cmds['rpm'] = {}
        self.cmds['apt'] = {}
        self.cmds['yum'] = {}
        self.cmds['zypper'] = {}
        self.cmds['dpkg'][
            'present'] = 'DEBIAN_FRONTEND=noninteractive dpkg % -i '
        self.cmds['dpkg'][
            'absent'] = 'DEBIAN_FRONTEND=noninteractive dpkg % -r '
        self.cmds['dpkg'][
            'stat'] = "dpkg-query -W -f='${{Description}}{0}${{Maintainer}}{0}'Unknown'{0}${{Installed-Size}}{0}${{Version}}{0}${{Status}}{0}${{Architecture}}\n' ".format(self.field_delimiter)
        self.cmds['dpkg'][
            'stat_all'] = "dpkg-query -W -f='${{Package}}{0}${{Description}}{0}${{Maintainer}}{0}'Unknown'{0}${{Installed-Size}}{0}${{Version}}{0}${{Status}}{0}${{Architecture}}\n{1}' ".format(self.field_delimiter, self.record_delimiter)
        self.cmds['dpkg']['stat_group'] = None
        self.cmds['rpm']['present'] = 'rpm % -i '
        self.cmds['rpm']['absent'] = 'rpm % -e '
        self.cmds['rpm'][
            'stat'] = 'rpm -q --queryformat "%{{SUMMARY}}{0}%{{PACKAGER}}{0}%{{INSTALLTIME}}{0}%{{SIZE}}{0}%{{EPOCH}}:%{{VERSION}}-%{{RELEASE}}{0}installed{0}%{{ARCH}}\n" '.format(self.field_delimiter)
        self.cmds['rpm'][
            'stat_all'] = 'rpm -qa --queryformat "%{{NAME}}{0}%{{SUMMARY}}{0}%{{PACKAGER}}{0}%{{INSTALLTIME}}{0}%{{SIZE}}{0}%{{EPOCH}}:%{{VERSION}}-%{{RELEASE}}{0}installed{0}%{{ARCH}}\n{1}" | sed "s/(none)/0/g" '.format(self.field_delimiter, self.record_delimiter)
        self.cmds['rpm']['stat_group'] = None
        self.cmds['apt'][
            'present'] = 'DEBIAN_FRONTEND=noninteractive apt-get % install ^ --allow-unauthenticated --yes '
        self.cmds['apt'][
            'absent'] = 'DEBIAN_FRONTEND=noninteractive apt-get % remove ^ --allow-unauthenticated --yes '
        self.cmds['apt']['stat'] = self.cmds['dpkg']['stat']
        self.cmds['apt']['stat_all'] = self.cmds['dpkg']['stat_all']
        self.cmds['apt']['stat_group'] = None
        self.cmds['yum']['present'] = 'yum -y % install ^ '
        self.cmds['yum']['absent'] = 'yum -y % remove ^ '
        self.cmds['yum']['grouppresent'] = 'yum -y % groupinstall ^ '
        self.cmds['yum']['groupabsent'] = 'yum -y % groupremove ^ '
        self.cmds['yum'][
            'stat_group'] = 'yum grouplist '  # the group mode is implemented when using YUM only.
        self.cmds['yum']['stat'] = self.cmds['rpm']['stat']
        self.cmds['yum']['stat_all'] = self.cmds['rpm']['stat_all']
        self.cmds['zypper']['present'] = 'zypper --non-interactive % install ^'
        self.cmds['zypper']['absent'] = self.cmds['rpm']['absent']
        self.cmds['zypper']['stat'] = self.cmds['rpm']['stat']
        self.cmds['zypper']['stat_all'] = self.cmds['rpm']['stat_all']
        self.cmds['zypper']['stat_group'] = None
        if self.PackageGroup is True:
            if self.cmds[self.PackageManager]['stat_group'] is None:
                print('ERROR.  PackageGroup is not valid for ' +
                      self.PackageManager, file=sys.stdout)
                LG().Log(
                    'ERROR', 'ERROR.  PackageGroup is not valid for ' + self.PackageManager)
                raise Exception('BadParameter')
            if len(self.FilePath) > 0:
                print(
                    'ERROR.  PackageGroup cannot be True if FilePath is set.', file=sys.stdout)
                LG().Log(
                    'ERROR', 'ERROR.  PackageGroup cannot be True if FilePath is set.')
                raise Exception('BadParameter')


def SetShowMof(a):
    global show_mof
    show_mof = a


def ShowMof(op, Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode):
    if not show_mof:
        return
    mof = '\n'
    mof += op + ' nxPackage MyPackage \n'
    mof += '{\n'
    mof += '    Name = "' + Name + '"\n'
    mof += '    Ensure = "' + Ensure + '"\n'
    mof += '    PackageManager = "' + PackageManager + '"\n'
    mof += '    FilePath = "' + FilePath + '"\n'
    mof += '    PackageGroup = "' + str(PackageGroup) + '"\n'
    mof += '    Arguments = "' + Arguments + '"\n'
    mof += '    ReturnCode = ' + str(ReturnCode) + '\n'
    mof += '}\n'
    f = open('./test_mofs.log', 'a')
    print(mof, file=f)
    f.close()


def IsPackageInstalled(p):
    out = ''
    if p is None:
        return False, out
    if len(p.FilePath) > 0 and '://' in p.FilePath:  # its a remote - try to file get name from cache
        if ReadCacheInfo(p) is False:
            return False, out
    elif len(p.FilePath) > 0 and os.path.exists(p.FilePath) is True:  # FilePath
        if apt is not None and os.path.splitext(p.FilePath)[-1] == '.deb':
            from apt.debfile import DebPackage
            pkg = DebPackage(p.FilePath)
            p.Name = pkg.pkgname
        elif rpm is not None and os.path.splitext(p.FilePath)[-1] == '.rpm':
            with open(p.FilePath, 'r') as F:
                ts = rpm.TransactionSet()
                ts.setVSFlags(-1)
                try:
                    pkg = ts.hdrFromFdno(F.fileno())
                except rpm.error, e:
                    print(repr(e))
                    LG().Log('ERROR', repr(e))
                    pkg = None
            if pkg is None:
                return False, out
            p.Name = pkg.dsOfHeader().N()
    if len(p.Name) < 1:
        return False, out

    if p.PackageGroup is True:
        if p.cmds[p.PackageManager]['stat_group'] is not None:
            cmd = p.cmds[p.PackageManager]['stat_group'] + '"' + p.Name + '"'
        else:
            print('ERROR.  PackageGroup is not valid for ' +
                  p.PackageManager, file=sys.stdout)
            LG().Log(
                'ERROR', 'ERROR.  PackageGroup is not valid for ' + p.PackageManager)
            return False, out
    else:
        cmd = 'LANG=en_US.UTF8 ' + p.cmds[p.PackageManager]['stat'] + p.Name
    code, out = RunGetOutput(cmd, False)
    if p.PackageGroup is True:  # implemented for YUM only.
        if 'Installed' in out:
            return True, out
        else:
            return False, out
    # regular packages
    print('check installed:' + out)
    LG().Log('INFO',  'check installed:' + out)
    if code is 0:
        if 'deinstall' in out or 'not-installed' in out:
            code = 1
    if code is not int(p.ReturnCode):
        return False, out
    return True, out


def ParseInfo(p, info):
    p.PackageDescription = ''
    p.Publisher = ''
    p.InstalledOn = ''
    p.Size = '0'
    p.Version = ''
    p.Installed = False
    p.Architecture = ''
    if len(info) > 1:
        f = re.split(p.field_delimiter, info)
        if len(f) is 7:
            p.PackageDescription = f[0]
            p.Publisher = f[1]
            p.InstalledOn = f[2]
            if not p.InstalledOn.isalnum():
                p.InstalledOn = time.gmtime(int(p.InstalledOn))
            if len(f[3]) > 0:
                p.Size = f[3]
            p.Version = f[4]
            p.Installed = ('install' in f[5])
            p.Architecture = f[6]

        if len(f) is not 7:
            print(
                'ERROR in ParseInfo.  Output was ' + info, file=sys.stdout)
            LG().Log(
                'ERROR', 'ERROR in ParseInfo.  Output was ' + info)


def ParseAllInfo(info, p):
    pkg_list = []
    d = {}
    if len(info) < 1 or p.record_delimiter not in info:
        return pkg_list
    for pkg in re.split(p.record_delimiter, info):
        d['Name'] = ''
        d['PackageDescription'] = ''
        d['Publisher'] = ''
        d['InstalledOn'] = ''
        d['Size'] = '0'
        d['Version'] = ''
        d['Installed'] = False
        d['Architecture'] = ''
        if len(pkg) > 1:
                pkg = pkg.strip()
                f = re.split(p.field_delimiter, pkg)
                if len(f) is 8:
                    d['Name'] = f[0]
                    if len(p.Name) and not fnmatch.fnmatch(d['Name'], p.Name):
                        continue
                    d['PackageDescription'] = f[1]
                    d['Publisher'] = f[2]
                    d['InstalledOn'] = f[3]
                    if not d['InstalledOn'].isalnum():
                        d['InstalledOn'] = time.gmtime(int(d['InstalledOn']))
                    if len(f[4]) > 0:
                        d['Size'] = f[4]
                    d['Version'] = f[5]
                    d['Installed'] = ('install' in f[6])
                    d['Architecture'] = f[7]
                if len(f) is not 8:
                    print(
                        'ERROR in ParseAllInfo.  Output was ' + info, file=sys.stdout)
                    LG().Log(
                        'ERROR', 'ERROR in ParseAllInfo.  Output was ' + info)
                    return pkg_list         
                pkg_list.append(copy.deepcopy(d))
    return pkg_list


def DoEnableDisable(p):
    # if the path is set, use the path and self.PackageSystem
    cmd = ""
    if len(p.FilePath) > 1 and 'present' in p.Ensure:  # don't use the path unless installing
        if '://' in p.FilePath and p.LocalPath == '':  # its a remote file
            ret = 0
            ret = GetRemoteFile(p)
            if ret is not 0:
                p.LocalPath = ""
                raise Exception(
                    'Unable to retrieve remote resource ' + p.FilePath + ' Error is ' + str(ret))
            else:
                p.FilePath = p.LocalPath

        if not os.path.isfile(p.FilePath):
            print('ERROR.   File ' + p.FilePath +
                  ' not found.', file=sys.stdout)
            LG().Log('ERROR', 'ERROR.   File ' + p.FilePath + ' not found.')
            return False, ""
        cmd = p.cmds[p.PackageSystem][p.Ensure] + ' ' + p.FilePath
        cmd = cmd.replace('%', p.Arguments)
    elif p.PackageGroup is True:
        if p.cmds[p.PackageManager].has_key('group' + p.Ensure):
            cmd = p.cmds[p.PackageManager][
                'group' + p.Ensure] + '"' + p.Name + '"'
        else:
            print('Error: Group mode not implemented for ' +
                  p.PackageManager, file=sys.stdout)
            LG().Log(
                'ERROR', 'Error: Group mode not implemented for ' + p.PackageManager)
            return False, 'Error: Group mode not implemented for ' + p.PackageManager
    else:
        cmd = 'LANG=en_US.UTF8 ' + \
            p.cmds[p.PackageManager][p.Ensure] + ' ' + p.Name
    cmd = cmd.replace('%', p.Arguments)
    cmd = cmd.replace('^', p.CommandArguments)
    code, out = RunGetOutput(cmd, False)
    if len(p.LocalPath) > 1:  # create cache entry and remove the tmp file
        WriteCacheInfo(p)
        RemoveFile(p.LocalPath)
    if p.PackageManager == 'yum' and ('No Match for argument: ' + p.Name in out or 'Nothing to do' in out):  # yum returns 0 on unknown package
        return False, out
    if p.PackageManager == 'zypper' and "package '" + p.Name + "' not found" in out:  # zypper returns 0 on unknown package
        return False, out
    if code is not int(p.ReturnCode):
        return False, out
    return True, out


def WriteCacheInfo(p):
    if not os.path.isdir(cache_file_dir):
        if MakeDirs(cache_file_dir) is not None:
            return False
    if len(p.LocalPath) < 1:
        return False
    if apt is not None and os.path.splitext(p.LocalPath)[-1] == '.deb':
        from apt.debfile import DebPackage
        try:
            pkg = DebPackage(p.LocalPath)
        except:
            print("Exception opening file " + p.LocalPath, file=sys.stderr)
            LG().Log('ERROR',  "Exception opening file " + p.LocalPath)
            return False
        p.Name = pkg.pkgname
    elif rpm is not None and os.path.splitext(p.LocalPath)[-1] == '.rpm':
            with opened_w_error(p.LocalPath, 'r') as (F, error):
                if error:
                    print(
                        "Exception opening file " + p.LocalPath, file=sys.stderr)
                    LG().Log('ERROR',  "Exception opening file " + p.LocalPath)
                    return False
                ts = rpm.TransactionSet()
                ts.setVSFlags(-1)
                try:
                    pkg = ts.hdrFromFdno(F.fileno())
                except rpm.error, e:
                    print(repr(e))
                    LG().Log('ERROR',  repr(e))
                    pkg = None
            if pkg is None:
                return False
            p.Name = pkg.dsOfHeader().N()
    if len(p.Name) < 1:
        return False
    cache_file_path = cache_file_dir + '/' + os.path.basename(p.LocalPath)
    with opened_w_error(cache_file_path, 'w+') as (F, error):
        if error:
            print("Exception creating cache file " + cache_file_path + " Error Code: " +
                  str(error.errno) + " Error: " + error.message + error.strerror, file=sys.stderr)
            LG().Log('ERROR',  "Exception creating cache file " + cache_file_path +
                     " Error Code: " + str(error.errno) + " Error: " + error.message + error.strerror)
            return False
        F.write(p.Name + '\n')
        F.close()
    return True


def ReadCacheInfo(p):
    cache_file_path = cache_file_dir + '/' + os.path.basename(p.FilePath)
    if not os.path.isfile(cache_file_path):
        return False
    with opened_w_error(cache_file_path, 'r') as (F, error):
        if error:
            print("Exception opening cache file " + cache_file_path + " Error Code: " +
                  str(error.errno) + " Error: " + error.message + error.strerror, file=sys.stderr)
            LG().Log('ERROR',  "Exception creating cache file " + cache_file_path +
                     " Error Code: " + str(error.errno) + " Error: " + error.message + error.strerror)
            return False
        t = F.read()
        F.close()
        if len(t) < 2:
            return False
        p.Name = t.strip()
    return True


def Set(Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode):
    ShowMof('SET', Ensure, PackageManager, Name,
            FilePath, PackageGroup, Arguments, ReturnCode)
    try:
        p = Params(Ensure, PackageManager, Name,
                   FilePath, PackageGroup, Arguments, ReturnCode)
    except Exception, e:
        print('ERROR - Unable to initialize nxPackageProvider.  ' +
              e.message, file=sys.stdout)
        LG().Log(
            'ERROR', 'ERROR - Unable to initialize nxPackageProvider. ' + e.message)
        return [-1]
    installed, out = IsPackageInstalled(p)
    if (installed and Ensure == 'present') or (not installed and Ensure == 'absent'):  # Nothing to do
        return [0]

    result, out = DoEnableDisable(p)
    if result is False:
        op = ''
        if Ensure == 'present':
            op = 'Install'
        else:
            op = 'Un-install'
        print('Failed to ' + op + ' ' + p.Name +
              ' output for command was: ' + out)
        LG().Log('ERROR', 'Failed to ' + op + ' ' +
                 p.Name + ' output for command was: ' + out)
        return [-1]
    return [0]


def Test(Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode):
    ShowMof('TEST', Ensure, PackageManager, Name,
            FilePath, PackageGroup, Arguments, ReturnCode)
    try:
        p = Params(Ensure, PackageManager, Name,
                   FilePath, PackageGroup, Arguments, ReturnCode)
    except Exception, e:
        print('ERROR - Unable to initialize nxPackageProvider.  ' +
              e.message, file=sys.stdout)
        LG().Log(
            'ERROR', 'ERROR - Unable to initialize nxPackageProvider. ' + e.message)
        return [-1]
    installed, out = IsPackageInstalled(p)
    if (installed and Ensure == 'present') or (not installed and Ensure == 'absent'):
        return [0]
    return [-1]


def Get(Ensure, PackageManager, Name, FilePath, PackageGroup, Arguments, ReturnCode):
    retval = -1
    installed = False
    ShowMof('GET', Ensure, PackageManager, Name,
            FilePath, PackageGroup, Arguments, ReturnCode)
    try:
        p = Params(Ensure, PackageManager, Name,
                   FilePath, PackageGroup, Arguments, ReturnCode)
    except Exception, e:
        print('ERROR - Unable to initialize nxPackageProvider.  ' +
              e.message, file=sys.stdout)
        LG().Log(
            'ERROR', 'ERROR - Unable to initialize nxPackageProvider. ' + e.message)
        return [retval, p.PackageDescription, p.Publisher, p.InstalledOn, p.Size, p.Version, installed]
    installed, out = IsPackageInstalled(p)
    out = out.replace('(none)','0') # for rpm EPOCH. 
    ParseInfo(p, out)
    return [0, p.PackageManager, p.PackageDescription, p.Publisher, p.InstalledOn, p.Size, p.Version, installed, p.Architecture]


def GetAll(Ensure, PackageManager, Name,
           FilePath, PackageGroup, Arguments, ReturnCode):
    pkgs = None
    try:
        p = Params(Ensure, PackageManager, Name,
                   FilePath, PackageGroup, Arguments, ReturnCode)
    except Exception, e:
        print('ERROR - Unable to initialize nxPackageProvider.  ' +
              e.message, file=sys.stdout)
        LG().Log(
            'ERROR', 'ERROR - Unable to initialize nxPackageProvider. ' + e.message)
        return [-1, ]
    cmd = 'LANG=en_US.UTF8 ' + p.cmds[p.PackageManager]['stat_all']
    code, out = RunGetOutput(cmd, False)
    pkgs = ParseAllInfo(out, p)
    return [0, pkgs]


@contextmanager
def opened_w_error(filename, mode="r"):
    """
    This context ensures the file is closed.
    """
    try:
        f = open(filename, mode)
    except IOError, err:
        yield None, err
    else:
        try:
            yield f, None
        finally:
            f.close()


def RunGetOutput(cmd, no_output, chk_err=True):
    """
    Wrapper for subprocess.check_output.
    Execute 'cmd'.  Returns return code and STDOUT, trapping expected exceptions.
    Reports exceptions to Error if chk_err parameter is True
    Kill inactivite subprocess and children if 6 second interval is exceeded.
    """
    def check_output(no_output, *popenargs, **kwargs):
        """
        Backport from subprocess module from python 2.7
        """
        if 'stdout' in kwargs:
            raise ValueError(
                'stdout argument not allowed, it will be overridden.')
        if no_output:
            out_file = None
        else:
            out_file = subprocess.PIPE
        process = subprocess.Popen(stdout=out_file, *popenargs, **kwargs)
        output, unused_err = process.communicate()
        retcode = process.poll()
        if retcode:
            cmd = kwargs.get("args")
            if cmd is None:
                cmd = popenargs[0]
            raise CalledProcessError(retcode, cmd, output=output)
        return output

    # Exception classes used by this module.
    class CalledProcessError(Exception):

        def __init__(self, returncode, cmd, output=None):
            self.returncode = returncode
            self.cmd = cmd
            self.output = output

        def __str__(self):
            return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)

    def noop():
        pass

    try:
        output = check_output(no_output, cmd, stderr=subprocess.STDOUT, shell=True)
    except CalledProcessError, e:
        if chk_err:
            print("CalledProcessError.  Error Code is " +
                  str(e.returncode), file=sys.stdout)
            print(
                "CalledProcessError.  Command string was " + e.cmd, file=sys.stdout)
            print("CalledProcessError.  Command result was " + (e.output[:-1]).decode(
                'utf8', 'ignore').encode("ascii", "ignore"), file=sys.stdout)
        if no_output:
            return e.returncode, None
        else:
            return e.returncode, e.output.decode('utf8', 'ignore').encode('ascii', 'ignore')
    if no_output:
        return 0, None
    else:
        return 0, output.decode('utf8', 'ignore').encode('ascii', 'ignore')


def GetTimeFromString(s):
    if s is None or len(s) is 0:
        return None
    fmt = []
    fmt.append('%a, %d %b %Y %H:%M:%S %Z')
    st = None
    for f in fmt:
        try:
            st = time.strptime(s, f)
        except ValueError:
            continue
    return st


def RemoveFile(path):
    error = None
    try:
        os.remove(path)
    except OSError, error:
        print("Exception removing file" + path + " Error Code: " + str(error.errno)
              + " Error: " + error.message + error.strerror, file=sys.stderr)
        LG().Log('ERROR', "Exception removing file" + path + " Error Code: " +
                 str(error.errno) + " Error: " + error.message + error.strerror)
    except IOError, error:
        print("Exception removing file" + path + " Error Code: " + str(error.errno)
              + " Error: " + error.message + error.strerror, file=sys.stderr)
        LG().Log('ERROR', "Exception removing file" + path + " Error Code: " +
                 str(error.errno) + " Error: " + error.message + error.strerror)
    return error


def LStatFile(path):
    """
    LStat the file.  Do not follow the symlink.
    """
    d = None
    error = None
    try:
        d = os.lstat(path)
    except OSError, error:
        print("Exception lstating file " + path + " Error Code: " + str(error.errno)
              + " Error: " + error.message + error.strerror, file=sys.stderr)
        LG().Log('ERROR', "Exception lstating file " + path + " Error Code: " +
                 str(error.errno) + " Error: " + error.message + error.strerror)
    except IOError, error:
        print("Exception lstating file " + path + " Error Code: " + str(error.errno)
              + " Error: " + error.message + error.strerror, file=sys.stderr)
        LG().Log('ERROR', "Exception lstating file " + path + " Error Code: " +
                 str(error.errno) + " Error: " + error.message + error.strerror)
    return d


def MakeDirs(path):
    error = None
    try:
        os.makedirs(path)
    except OSError, error:
        print("Exception making dir" + path + " Error Code: " + str(error.errno)
              + " Error: " + error.message + error.strerror, file=sys.stderr)
        LG().Log('ERROR',  "Exception making dir" + path + " Error Code: " +
                 str(error.errno) + " Error: " + error.message + error.strerror)
    except IOError, error:
        print("Exception making dir" + path + " Error Code: " + str(error.errno)
              + " Error: " + error.message + error.strerror, file=sys.stderr)
        LG().Log('ERROR',  "Exception making dir" + path + " Error Code: " +
                 str(error.errno) + " Error: " + error.message + error.strerror)
    return error

def SetProxyFromConf():
    """
    Check for PROXY definition in dsc.conf.
    All we must do is set the appropriate value in the environment.
    HTTP_PROXY
    HTTPS_PROXY
    """
    path = helperlib.CONFIG_SYSCONFDIR+ '/' + helperlib.CONFIG_SYSCONFDIR_DSC + '/dsc.conf'
    txt, error = ReadFile(path)
    if error :
        return
    for l in txt.splitlines():
        if l.startswith('PROXY'):
            info = l.split('=')[1].strip()
            if 'https' in info:
                os.environ['HTTPS_PROXY'] = info
            if 'http:' in info:
                os.environ['HTTP_PROXY'] = info
    return
        
def ReadFile(path):
    """
    Safely attempt to read a file,
    ensuring file is always closed at exit.
    Return the data and the exception object.
    The data is None if an error occurred.
    The error is None if the data was read.
    Log results to stderr.
    """
    d = None
    error = None
    with opened_w_error(path, 'r') as (F, error):
        if error:
            print("Exception opening file " + path + " Error Code: " + str(error.errno) + " Error: " + error.message + error.strerror, file=sys.stderr)
            LG().Log('ERROR', "Exception opening file " + path + " Error Code: " + str(error.errno) + " Error: " + error.message + error.strerror)
        else:
            d = F.read()
    return d, error

def GetRemoteFile(p):
    SetProxyFromConf()
    req = urllib2.Request(p.FilePath)
    try:
        resp = urllib2.urlopen(req)
    except urllib2.URLError, e:
        print(repr(e))
        LG().Log('ERROR',  repr(e))
        return 1
    p.LocalPath = '/tmp/' + os.path.basename(p.FilePath)
    h = resp.info()
    lm = h.getheader('last-modified')
    lm_mtime = GetTimeFromString(lm)
    dst_mtime = None
    dst_st = None
    data = None
    if os.path.exists(p.LocalPath):
        dst_st = LStatFile(p.LocalPath)
    if dst_st is not None:
        dst_mtime = time.gmtime(dst_st.st_mtime)
    if lm_mtime is not None and dst_mtime is not None and dst_mtime >= lm_mtime:
        data = ''  # skip download, the file is the same
    else:
        data = b'keep going'
        with (open(p.LocalPath, 'wb+')) as F:
            try:
                while data:
                    data = resp.read(1048576)
                    if data is not None and len(data) > 0:
                        F.write(data)
            except Exception, e:
                F.close()
                os.unlink(p.LocalPath)
                print(repr(e))
                LG().Log('ERROR', repr(e))
                return 1
    return 0