fedora-hardware/hw-client __init__.py, NONE, 1.1 capabilities.py, NONE, 1.1 clientCaps.py, NONE, 1.1 config.py, NONE, 1.1 haltree.py, NONE, 1.1 hardware.py, NONE, 1.1 rhnChannel.py, NONE, 1.1 rhnErrata.py, NONE, 1.1 rhnHardware.py, NONE, 1.1 rhnPackageInfo.py, NONE, 1.1 rhncli.py, NONE, 1.1 rhnserver.py, NONE, 1.1 rpcServer.py, NONE, 1.1 rpmUtils.py, NONE, 1.1 sendProfile.py, NONE, 1.1 test.sh, NONE, 1.1 transaction.py, NONE, 1.1 up2dateAuth.py, NONE, 1.1 up2dateErrors.py, NONE, 1.1 up2dateLog.py, NONE, 1.1 up2dateUtils.py, NONE, 1.1

Michael Patrick McGrath (mmcgrath) fedora-extras-commits at redhat.com
Mon Jan 15 18:25:38 UTC 2007


Author: mmcgrath

Update of /cvs/fedora/fedora-hardware/hw-client
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv2555/hw-client

Added Files:
	__init__.py capabilities.py clientCaps.py config.py haltree.py 
	hardware.py rhnChannel.py rhnErrata.py rhnHardware.py 
	rhnPackageInfo.py rhncli.py rhnserver.py rpcServer.py 
	rpmUtils.py sendProfile.py test.sh transaction.py 
	up2dateAuth.py up2dateErrors.py up2dateLog.py up2dateUtils.py 
Log Message:
added client


--- NEW FILE __init__.py ---


--- NEW FILE capabilities.py ---

import UserDict
import config
import up2dateErrors
import string

from rhpl.translate import _

# a dict with "capability name" as the key, and the version
# as the value.
neededCaps = {"caneatCheese": {'version':"21"},
              "supportsAutoUp2dateOption": {'version': "1"},
              "registration.finish_message": {'version': "1"},
              "xmlrpc.packages.extended_profile": {'version':"1"},
              "registration.delta_packages": {'version':"1"},
              "registration.remaining_subscriptions": {'version': '1'},
              "registration.update_contact_info": {'version': "1"}}

def parseCap(capstring):
    value = None
    caps = string.split(capstring, ',')

    capslist = []
    for cap in caps:
        try:
            (key_version, value) = map(string.strip, string.split(cap, "=", 1))
        except ValueError:
            # Bad directive: not in 'a = b' format
            continue
            
        # parse out the version
        # lets give it a shot sans regex's first...
        (key,version) = string.split(key_version, "(", 1)
        
        # just to be paranoid
        if version[-1] != ")":
            print "something broke in parsing the capabilited headers"
        #FIXME: raise an approriate exception here...

        # trim off the trailing paren
        version = version[:-1]
        data = {'version': version, 'value': value}

        capslist.append((key, data))

    return capslist

class Capabilities(UserDict.UserDict):
    def __init__(self):
        UserDict.UserDict.__init__(self)
        self.missingCaps = {}
        #self.populate()
#        self.validate()
        self.neededCaps = neededCaps
        self.cfg = config.initUp2dateConfig()


    def populate(self, headers):
        for key in headers.keys():
            if key == "x-rhn-server-capability":
                capslist = parseCap(headers[key])

                for (cap,data) in capslist:
                    self.data[cap] = data

    def parseCapVersion(self, versionString):
        index = string.find(versionString, '-')
        # version of "-" is bogus, ditto for "1-"
        if index > 0:
            rng = string.split(versionString, "-")
            start = rng[0]
            end = rng[1]
            versions = range(int(start), int(end)+1)
            return versions

        vers = string.split(versionString, ':')
        if len(vers) > 1:
            versions = map(lambda a:int(a), vers)
            return versions

        return [int(versionString)]

    def validateCap(self, cap, capvalue):
        if not self.data.has_key(cap):
            errstr = _("This client requires the server to support %s, which the current " \
                       "server does not support") % cap
            self.missingCaps[cap] = None
        else:
            data = self.data[cap]
            # DOES the server have the version we need
            if int(capvalue['version']) not in self.parseCapVersion(data['version']):
                self.missingCaps[cap] =  self.neededCaps[cap]


    def validate(self):
        for key in self.neededCaps.keys():
            self.validateCap(key, self.neededCaps[key])

        self.workaroundMissingCaps()

    def setConfig(self, key, configItem):
        if self.tmpCaps.has_key(key):
            self.cfg[configItem] = 0
            del self.tmpCaps[key]
        else:
            self.cfg[configItem] = 1

    def workaroundMissingCaps(self):
        # if we have caps that we know we want, but we can
        # can work around, setup config variables here so
        # that we know to do just that
        self.tmpCaps = self.missingCaps

        # this is an example of how to work around it
        key = 'caneatCheese'
        if self.tmpCaps.has_key(key):
            # do whatevers needed to workaround
            del self.tmpCaps[key]
        else:
            # we support this, set a config option to
            # indicate that possibly
            pass

        # dict of key to configItem, and the config item that
        # corresponds with it

        capsConfigMap = {'supportsAutoUp2dateOption': 'supportsAutoUp2dateOption',
                         'registration.finish_message': 'supportsFinishMessage',
                         "registration.remaining_subscriptions" : 'supportsRemainingSubscriptions',
                         "registration.update_contact_info" : 'supportsUpdateContactInfo',
                         "registration.delta_packages" : 'supportsDeltaPackages',
                         "xmlrpc.packages.extended_profile" : 'supportsExtendedPackageProfile'}

        for key in capsConfigMap.keys():
            self.setConfig(key, capsConfigMap[key])

        # if we want to blow up on missing caps we cant eat around
        missingCaps = []
        wrongVersionCaps = []

        if len(self.tmpCaps):
            for cap in self.tmpCaps:
                capInfo = self.tmpCaps[cap]
                if capInfo == None:
                    # it's completly mssing
                    missingCaps.append((cap, capInfo))
                else:
                    wrongVersionCaps.append((cap, capInfo))

        errString = ""
        errorList = []
        if len(wrongVersionCaps):
            for (cap, capInfo) in wrongVersionCaps:
                errString = errString + "Needs %s of version: %s but server has version: %s\n" % (cap,
                                                                                    capInfo['version'],
                                                                                    self.data[cap]['version'])
                errorList.append({"capName":cap, "capInfo":capInfo, "serverVersion":self.data[cap]})

        if len(missingCaps):
            for (cap, capInfo) in missingCaps:
                errString = errString + "Needs %s but server does not support that capability\n" % (cap)
                errorList.append({"capName":cap, "capInfo":capInfo, "serverVersion":""})

        if len(errString):
            raise up2dateErrors.ServerCapabilityError(errString, errorList)

    def hasCapability(self, capability, version=None):
        """Checks if the server supports a capability and optionally a version.
        Returns True or False.
        
        This complements the neededCaps mechanism provided by this module.
        Using hasCapability makes it easier to do something only if the server 
        supports it or to put workaround code in the user of this class. The 
        neededCaps mechanism makes it easier to put workaround code in this
        module, which makes sense if it is to be shared.
        
        'capability' should be a string such as 'registration.foobar'. It can 
        be a capability in 'neededCaps' above or one that isn't there. 'version' 
        can be a string (where isdigit() is True) or an int.
        
        """
        assert version is None or str(version).isdigit()
        
        if not self.data.has_key(capability):
            return False
        if version:
            data = self.data[capability]
            if int(version) not in self.parseCapVersion(data['version']):
                return False
        return True


--- NEW FILE clientCaps.py ---

# a dict with "capability name" as the key, and the version
# as the value.

import UserDict
import glob
import os
import string

import capabilities

class ClientCapabilities(UserDict.UserDict):
    def __init__(self):
        UserDict.UserDict.__init__(self)
        self.populate()

    def populate(self, capsToPopulate=None):
        # FIXME: at some point, this will be
        # intelligently populated...
        localcaps = {
#            "packages.runTransaction":{'version':1, 'value':1},
#            "blippyfoo":{'version':5, 'value':0},
            "caneatCheese":{'version':1, 'value': 1}
            }
        if capsToPopulate:
            localcaps = capsToPopulate
        self.data = localcaps

    def headerFormat(self):
        headerList = []
        for key in self.data.keys():
            headerName = "X-RHN-Client-Capability"
            value = "%s(%s)=%s" % (key,
                                   self.data[key]['version'],
                                   self.data[key]['value'])
            headerList.append((headerName, value))
        return headerList

caps = ClientCapabilities()

def loadLocalCaps():
    capsDir = "/etc/sysconfig/rhn/clientCaps.d"

    capsFiles = glob.glob("%s/*" % capsDir)

    for capsFile in capsFiles:
        if os.path.isdir(capsFile):
            continue
        if not os.access(capsFile, os.R_OK):
            continue

        fd = open(capsFile, "r")
        for line in fd.readlines():
            string.strip(line)
            if line[0] == "#":
                continue
            caplist = capabilities.parseCap(line)

            for (cap,data) in caplist:
                caps.data[cap] = data

#    print caps.data
    
loadLocalCaps()

# register local caps we require.
def registerCap(cap, data):
    caps.data[cap] = data
    

# figure out something pretty here
registerCap("packages.runTransaction", {'version':'1', 'value':'1'})
registerCap("packages.rollBack", {'version':'1', 'value':'1'})
registerCap("packages.verify", {'version':'1', 'value':'1'})
registerCap("packages.verifyAll", {'version':'1', 'value':'1'})
registerCap("packages.extended_profile", {'version':'1', 'value':'1'})
registerCap("reboot.reboot", {'version':'1', 'value':'1'})


***** Error reading new file: [Errno 2] No such file or directory: 'config.py'

--- NEW FILE haltree.py ---

# HalTree Purpose:
#
# HalTree is a way to organize the mess of data you get from hal.  In general,
# if you want to get all the information about every device in the system, you
# end up with a list of dicts, where each dict contains the property name/values
# for a device.  This list isn't very useful as the hal data is actually 
# organized into a tree.  For example, you have the computer as the head, then
# there may be a scsi card plugged in.  That in turn will have scsi channels
# and luns, which scsi devices may be connected to.  So this module will help
# you reorganize your hal data back to the way they were intended.
#
# HalTree Usage:
# 
# The tree gets built one device at a time.  Once you've created a HalTree
# object, devices get added to the tree with HalTree.add(hw_dev_dict).  The
# devices can be added in any particular order, and the tree gets properly
# structured as the devices get added.  But the tree structure isn't likely
# to be ready until all the devices have been added.  Those devices without a
# parent get stuck in the no_parent_yet list.
#
# When a device gets added, it is no longer a plain dict.  It is stored in a
# HalDevice.  The original dict can be found in HalDevice.properties.

import types


class HalDevice:
    "An object containing its udi, properties and children"
    def __init__ (self, properties):
        self.udi = properties['info.udi']

        self.properties = properties
        self.children = []
        self.classification = None
        
        if properties.has_key('info.parent'):
            self.parent_udi = properties['info.parent']
        else:
            self.parent_udi = None

        self.parent = None

    def print_properties(self):
        print self.udi, ":"
        for property, value in self.properties.items():
            print "    ", property," ==> ",  value

    
        

class HalTree:
    def __init__ (self):
        self.head = None
        self.no_parent_yet = []


    def add(self, hal_device):
        if hal_device.parent_udi:
            parent = self.__find_node(hal_device.parent_udi)
            if parent:
                parent.children.append(hal_device)
                hal_device.parent = parent
            else:  #parent isn't in the main tree yet, stick it in waiting
                self.no_parent_yet.append(hal_device)
        else: #if it doesn't have a parent, it must be the head 'computer'
            self.head = hal_device
            
        #check to see if there are any children waiting for this dev
        self.__get_lost_children(hal_device)
            

    def __get_lost_children(self, hal_device):
        found_list = []
        indexes = []
        no_parent_yet_copy = self.no_parent_yet[:]
        for dev in no_parent_yet_copy:
            if dev.parent_udi == hal_device.udi:
                dev.parent = hal_device
                hal_device.children.append(dev)
                self.no_parent_yet.remove(dev)

    def __find_node(self, udi):
        """ 
        This takes a node in the HalDevice tree and returns the HalDevice with
        the given udi.
        """
        if self.head:
            node = HalTree.__find_node_worker(self.head, udi)
            if node:
                return node

        for node in self.no_parent_yet:
            found_node = HalTree.__find_node_worker(node, udi)
            if found_node:
                return found_node
        return None

#    @staticmethod
    def __find_node_worker(node, udi):
        if node.udi == udi:
            return node
        for device in node.children:
            res = HalTree.__find_node_worker(device, udi)
            if res:
                return res
        return None
    
    def print_tree(self):
        self.__print_dev_tree(self.head, "")
        
    def __print_dev_tree(self, node, indent):
        print indent, node.udi
        print indent, "CLASS:", node.classification
        for name, property in node.properties.items():
            if (type(property) == types.StringType):
                if property.isdigit():
                    print indent + "    ", "%-20s ==> %s" % (name, hex(int(property)))
                else:
                    print indent + "    ", "%-20s ==> %s" % (name, property)
            elif (type(property) == types.IntType): 
                print indent + "    ", "%-20s ==> %s" % (name, hex(int(property)))
            else:
                print indent + "    ", "%-20s ==> %s" % (name, property)
        print
        for child in node.children:
            self.__print_dev_tree(child, indent + "    ")


--- NEW FILE hardware.py ---
#
# Copyright (c) 1999-2002 Red Hat, Inc.  Distributed under GPL.
#
# Author: Preston Brown <pbrown at redhat.com>
#         Adrian Likins <alikins at redhat.com>
#         Cristian Gafton <gafton at redhat.com>
#
# This thing gets the hardware configuraion out of a system
"""Used to read hardware info from kudzu, /proc, etc"""
from socket import gethostname
from socket import gethostbyname
import socket

import os
import sys
import string
import types

import config

from rhpl import ethtool
from rhpl.translate import _, N_
from haltree import HalTree, HalDevice

import dbus

#PCI DEVICE DEFINES
# These are taken from pci_ids.h in the linux kernel source and used to 
# properly identify the hardware
PCI_BASE_CLASS_STORAGE =        1
PCI_CLASS_STORAGE_SCSI =        0
PCI_CLASS_STORAGE_IDE =         1
PCI_CLASS_STORAGE_FLOPPY =      2
PCI_CLASS_STORAGE_IPI =         3
PCI_CLASS_STORAGE_RAID =        4
PCI_CLASS_STORAGE_OTHER =       80

PCI_BASE_CLASS_NETWORK =        2
PCI_CLASS_NETWORK_ETHERNET =    0
PCI_CLASS_NETWORK_TOKEN_RING =  1
PCI_CLASS_NETWORK_FDDI =        2
PCI_CLASS_NETWORK_ATM =         3
PCI_CLASS_NETWORK_OTHER =       80

PCI_BASE_CLASS_DISPLAY =        3
PCI_CLASS_DISPLAY_VGA =         0
PCI_CLASS_DISPLAY_XGA =         1
PCI_CLASS_DISPLAY_3D =          2
PCI_CLASS_DISPLAY_OTHER =       80

PCI_BASE_CLASS_MULTIMEDIA =     4
PCI_CLASS_MULTIMEDIA_VIDEO =    0
PCI_CLASS_MULTIMEDIA_AUDIO =    1
PCI_CLASS_MULTIMEDIA_PHONE =    2
PCI_CLASS_MULTIMEDIA_OTHER =    80

PCI_BASE_CLASS_BRIDGE =         6
PCI_CLASS_BRIDGE_HOST =         0
PCI_CLASS_BRIDGE_ISA =          1
PCI_CLASS_BRIDGE_EISA =         2
PCI_CLASS_BRIDGE_MC =           3
PCI_CLASS_BRIDGE_PCI =          4
PCI_CLASS_BRIDGE_PCMCIA =       5
PCI_CLASS_BRIDGE_NUBUS =        6
PCI_CLASS_BRIDGE_CARDBUS =      7
PCI_CLASS_BRIDGE_RACEWAY =      8
PCI_CLASS_BRIDGE_OTHER =        80

PCI_BASE_CLASS_COMMUNICATION =  7
PCI_CLASS_COMMUNICATION_SERIAL = 0
PCI_CLASS_COMMUNICATION_PARALLEL = 1
PCI_CLASS_COMMUNICATION_MULTISERIAL = 2
PCI_CLASS_COMMUNICATION_MODEM = 3
PCI_CLASS_COMMUNICATION_OTHER = 80

PCI_BASE_CLASS_INPUT =          9
PCI_CLASS_INPUT_KEYBOARD =      0
PCI_CLASS_INPUT_PEN =           1
PCI_CLASS_INPUT_MOUSE =         2
PCI_CLASS_INPUT_SCANNER =       3
PCI_CLASS_INPUT_GAMEPORT =      4
PCI_CLASS_INPUT_OTHER =         80

PCI_BASE_CLASS_SERIAL =         12
PCI_CLASS_SERIAL_FIREWIRE =     0
PCI_CLASS_SERIAL_ACCESS =       1
PCI_CLASS_SERIAL_SSA =          2
PCI_CLASS_SERIAL_USB =          3
PCI_CLASS_SERIAL_FIBER =        4
PCI_CLASS_SERIAL_SMBUS =        5



# Some systems don't have the _locale module installed
try:
    import locale
except ImportError:
    locale = None


# read_hal()
# 
# This reads in all the properties for each device from HAL, storing the 
# property names & values into a dict.  A list of dicts is returned.
#
# This only works on newer versions of dbus & HAL (as found in RHEL5)
def read_hal():
    ret = []
    bus = dbus.SystemBus()
        
    hal_manager_obj = bus.get_object('org.freedesktop.Hal',
        '/org/freedesktop/Hal/Manager')
    hal_manager = dbus.Interface(hal_manager_obj,
        'org.freedesktop.Hal.Manager')
   
    device_list = hal_manager.GetAllDevices()
    hal_tree = HalTree()
    for udi in device_list:
        device_obj = bus.get_object ('org.freedesktop.Hal', udi)
        device = dbus.Interface(device_obj, 'org.freedesktop.Hal.Device')

        properties = device.GetAllProperties()

        haldev = HalDevice(properties)
        hal_tree.add(haldev)

    kudzu_list = process_hal_nodes(hal_tree.head)
    return kudzu_list
    
    # Recursive function, does all the dirty work for add_hal_hardware
def process_hal_nodes(node):
    kudzu_list = []
    node.classification = classify_hal(node)
    if node.classification:
        parent = node.parent
        dev = {} 
        dev['class'] = node.classification
        #get bus
        dev['bus'] = get_device_bus(node)
        
        #get scsi info
        if dev['bus'] == 'scsi':
            if parent.properties.has_key('scsi.host'):
                dev['prop1'] = parent.properties['scsi.host']
            if parent.properties.has_key('scsi.target'):
                dev['prop2'] = parent.properties['scsi.target']
            if parent.properties.has_key('scsi.bus'):
                dev['prop3'] = parent.properties['scsi.bus']
            if parent.properties.has_key('scsi.lun'):
                dev['prop4'] = parent.properties['scsi.lun']
        
        
        dev['driver'] = get_device_driver(node) 
        
        device_path = get_device_path(node)
        if device_path:
            dev['device'] = device_path

        dev['desc'] = get_device_description(node)

        dev['pciType'] = get_device_pcitype(node)

        dev['detached'] = 0
        kudzu_list.append(dev)

    for child in node.children:
        child_list = process_hal_nodes(child) 
        kudzu_list.extend(child_list)

    return kudzu_list
        
        

def classify_hal(node):
    # NETWORK
    if node.properties.has_key('net.interface'):
        return 'NETWORK'
    
    if node.properties.has_key('info.product') and node.properties.has_key('info.category'):
        if node.properties['info.category'] == 'input':
            # KEYBOARD <-- do this before mouse, some keyboards have built-in mice
            if 'keyboard' in node.properties['info.product'].lower():
                return 'KEYBOARD'
            # MOUSE
            if 'mouse' in node.properties['info.product'].lower():
                return 'MOUSE'
    
    if node.properties.has_key('pci.device_class'):
        #VIDEO
        if node.properties['pci.device_class'] == PCI_BASE_CLASS_DISPLAY:
            return 'VIDEO'
        #USB
        if (node.properties['pci.device_class'] ==  PCI_BASE_CLASS_SERIAL
                and node.properties['pci.device_subclass'] == PCI_CLASS_SERIAL_USB):
            return 'USB'
        
        if node.properties['pci.device_class'] == PCI_BASE_CLASS_STORAGE: 
            #IDE
            if node.properties['pci.device_subclass'] == PCI_CLASS_STORAGE_IDE:
                return 'IDE'
            #SCSI
            if node.properties['pci.device_subclass'] == PCI_CLASS_STORAGE_SCSI:
                return 'SCSI'
            #RAID
            if node.properties['pci.device_subclass'] == PCI_CLASS_STORAGE_RAID:
                return 'RAID'
        #MODEM
        if (node.properties['pci.device_class'] == PCI_BASE_CLASS_COMMUNICATION 
                and node.properties['pci.device_subclass'] == PCI_CLASS_COMMUNICATION_MODEM):
            return 'MODEM'
        #SCANNER 
        if (node.properties['pci.device_class'] == PCI_BASE_CLASS_INPUT 
                and node.properties['pci.device_subclass'] == PCI_CLASS_INPUT_SCANNER):
            return 'SCANNER'
        
        if node.properties['pci.device_class'] == PCI_BASE_CLASS_MULTIMEDIA: 
            #CAPTURE -- video capture card
            if node.properties['pci.device_subclass'] == PCI_CLASS_MULTIMEDIA_VIDEO:
                return 'CAPTURE'
            #AUDIO
            if node.properties['pci.device_subclass'] == PCI_CLASS_MULTIMEDIA_AUDIO:
                return 'AUDIO'

        #FIREWIRE
        if (node.properties['pci.device_class'] == PCI_BASE_CLASS_SERIAL 
                and node.properties['pci.device_subclass'] == PCI_CLASS_SERIAL_FIREWIRE):
            return 'FIREWIRE'
        #SOCKET -- PCMCIA yenta socket stuff
        if (node.properties['pci.device_class'] == PCI_BASE_CLASS_BRIDGE 
                and (node.properties['pci.device_subclass'] == PCI_CLASS_BRIDGE_PCMCIA
                or node.properties['pci.device_subclass'] == PCI_CLASS_BRIDGE_CARDBUS)):
            return 'SOCKET'
    
    if node.properties.has_key('storage.drive_type'):
        #CDROM
        if node.properties['storage.drive_type'] == 'cdrom':
            return 'CDROM'
        #HD
        if node.properties['storage.drive_type'] == 'disk':
            return 'HD'
         #FLOPPY
        if node.properties['storage.drive_type'] == 'floppy':
            return 'FLOPPY'
        #TAPE
        if node.properties['storage.drive_type'] == 'tape':
            return 'TAPE'

    #PRINTER
    if node.properties.has_key('printer.product'):
        return 'PRINTER'

    #Catchall for specific devices, only do this after all the others
    if (node.properties.has_key('pci.product_id') or
            node.properties.has_key('usb.product_id')):
        return 'OTHER'

    # No class found
    return None

def get_device_bus(node):
    if node.properties.has_key('storage.bus'):
        bus = node.properties['storage.bus']
    elif node.properties.has_key('info.bus'):
        if node.properties['info.bus'] == 'platform':
            bus = 'MISC'
        else:
            bus = node.properties['info.bus']
    else:
        bus = 'MISC'
    
    return bus

def get_device_driver(node):
    if node.properties.has_key('info.linux.driver'):
        driver = node.properties['info.linux.driver']
    elif node.properties.has_key('net.linux.driver'):
        driver = node.properties['net.linux.driver']
    else:
        driver = 'unknown'

    return driver

def get_device_path(node):
    """
    Return the device file path.

    As kudzu did not return a string with the /dev/ prefix,
    this function will not, either.
    RHN's DB has a limit of 16 characters for the device path.
    If the path is longer than that, return None.
    If no device path is found, return None.
    """
    dev = None

    if node.properties.has_key('block.device'):
        dev = node.properties['block.device']
    elif node.properties.has_key('linux.device_file'):
        dev = node.properties['linux.device_file']
    elif (node.classification == 'NETWORK' 
            and node.properties.has_key('net.interface')):
        dev = node.properties['net.interface']

    if dev:
        if dev.startswith('/dev/'):
            dev = dev[5:]
        if len(dev) > 16:
            dev = None

    return dev

def get_device_description(node):
    if (node.properties.has_key('info.vendor') 
            and node.properties.has_key('info.product')):
        desc = node.properties['info.vendor'] + '|' +  node.properties['info.product']
    elif (node.properties.has_key('info.vendor')):
        desc = node.properties['info.vendor'] 
    elif node.properties.has_key('info.product'):
        desc =  node.properties['info.product']
    else:
        desc = ""
    
    return desc

def get_device_pcitype(node):
    PCI_TYPE_PCMCIA = 2
    PCI_TYPE_PCI = 1
    PCI_TYPE_NOT_PCI = -1
    
    if (node.properties.has_key('info.bus') 
            and node.properties['info.bus'] == 'pci'):
        parent = node.parent
        if (parent.properties.has_key('pci.device_class') 
                and (parent.properties['pci.device_class'] == 6 
                and (parent.properties['pci.device_subclass'] == 5 
                or parent.properties['pci.device_subclass'] == 7))):
            pcitype = PCI_TYPE_PCMCIA
        else:
            pcitype = PCI_TYPE_PCI
    else:
        pcitype = PCI_TYPE_NOT_PCI

    return pcitype

def read_installinfo():
    if not os.access("/etc/sysconfig/installinfo", os.R_OK):
        return {}
    installinfo = open("/etc/sysconfig/installinfo", "r").readlines()
    installdict = {}
    installdict['class'] = "INSTALLINFO"
    for info in installinfo:
        if not len(info):
            continue
        vals = string.split(info, '=')
        if len(vals) <= 1:
            continue
        strippedstring = string.strip(vals[0])
        vals[0] = strippedstring
        
        installdict[vals[0]] = string.strip(string.join(vals[1:]))
    return installdict
    
        

# This has got to be one of the ugliest fucntions alive
def read_cpuinfo():
    def get_entry(a, entry):
        e = string.lower(entry)
        if not a.has_key(e):
            return ""
        return a[e]

    if not os.access("/proc/cpuinfo", os.R_OK):
        return {}

    # Okay, the kernel likes to give us the information we need in the
    # standard "C" locale.
    if locale:
        # not really needed if you don't plan on using atof()
        locale.setlocale(locale.LC_NUMERIC, "C")

    cpulist = open("/proc/cpuinfo", "r").read()
    uname = string.lower(os.uname()[4])

    # This thing should return a hwdict that has the following
    # members:
    #
    # class, desc (required to identify the hardware device)
    # count, type, model, model_number, model_ver, model_rev
    # bogomips, platform, speed, cache
    
    hwdict = { 'class': "CPU",
               "desc" : "Processor",
               }
    if uname[0] == "i" and uname[-2:] == "86" or (uname == "x86_64"):
        # IA32 compatible enough
        count = 0
        tmpdict = {}
        for cpu in string.split(cpulist, "\n\n"):
            if not len(cpu):
                continue
            count = count + 1
            if count > 1:
                continue # just count the rest
            for cpu_attr in string.split(cpu, "\n"):
                if not len(cpu_attr):
                    continue
                vals = string.split(cpu_attr, ":")
                if len(vals) != 2:
                    # XXX: make at least some effort to recover this data...
                    continue
                name, value = string.strip(vals[0]), string.strip(vals[1])
                tmpdict[string.lower(name)] = value

        if uname == "x86_64":
            hwdict['platform'] = 'x86_64'
        else:
            hwdict['platform']      = "i386"
            
        hwdict['count']         = count
        hwdict['type']          = get_entry(tmpdict, 'vendor_id')
        hwdict['model']         = get_entry(tmpdict, 'model name')
        hwdict['model_number']  = get_entry(tmpdict, 'cpu family')
        hwdict['model_ver']     = get_entry(tmpdict, 'model')
        hwdict['model_rev']     = get_entry(tmpdict, 'stepping')
        hwdict['cache']         = get_entry(tmpdict, 'cache size')
        hwdict['bogomips']      = get_entry(tmpdict, 'bogomips')
        hwdict['other']         = get_entry(tmpdict, 'flags')
        mhz_speed               = get_entry(tmpdict, 'cpu mhz')
        if mhz_speed == "":
            # damn, some machines don't report this
            mhz_speed = "-1"
        try:
            hwdict['speed']         = int(round(float(mhz_speed)) - 1)
        except ValueError:
            hwdict['speed'] = -1

        

    elif uname in["alpha", "alphaev6"]:
        # Treat it as an an Alpha
        tmpdict = {}
        for cpu_attr in string.split(cpulist, "\n"):
            if not len(cpu_attr):
                continue
            vals = string.split(cpu_attr, ":")
            if len(vals) != 2:
                # XXX: make at least some effort to recover this data...
                continue
            name, value = string.strip(vals[0]), string.strip(vals[1])
            tmpdict[string.lower(name)] = string.lower(value)

        hwdict['platform']      = "alpha"
        hwdict['count']         = get_entry(tmpdict, 'cpus detected')
        hwdict['type']          = get_entry(tmpdict, 'cpu')
        hwdict['model']         = get_entry(tmpdict, 'cpu model')
        hwdict['model_number']  = get_entry(tmpdict, 'cpu variation')
        hwdict['model_version'] = "%s/%s" % (get_entry(tmpdict, 'system type'),
                                             get_entry(tmpdict,'system variation'))
        hwdict['model_rev']     = get_entry(tmpdict, 'cpu revision')
        hwdict['cache']         = "" # pitty the kernel doesn't tell us this.
        hwdict['bogomips']      = get_entry(tmpdict, 'bogomips')
        hwdict['other']         = get_entry(tmpdict, 'platform string')
        hz_speed                = get_entry(tmpdict, 'cycle frequency [Hz]')
        # some funky alphas actually report in the form "462375000 est."
        hz_speed = string.split(hz_speed)
        try:
            hwdict['speed']         = int(round(float(hz_speed[0]))) / 1000000
        except ValueError:
            hwdict['speed'] = -1

    elif uname in ["ia64"]:
        tmpdict = {}
        count = 0
        for cpu in string.split(cpulist, "\n\n"):
            if not len(cpu):
                continue
            count = count + 1
            # count the rest
            if count > 1:
                continue
            for cpu_attr in string.split(cpu, "\n"):
                if not len(cpu_attr):
                    continue
                vals = string.split(cpu_attr, ":")  
                if len(vals) != 2:
                    # XXX: make at least some effort to recover this data...
                    continue
                name, value = string.strip(vals[0]), string.strip(vals[1])
                tmpdict[string.lower(name)] = string.lower(value)

        hwdict['platform']      = uname
        hwdict['count']         = count
        hwdict['type']          = get_entry(tmpdict, 'vendor')
        hwdict['model']         = get_entry(tmpdict, 'family')
        hwdict['model_ver']     = get_entry(tmpdict, 'archrev')
        hwdict['model_rev']     = get_entry(tmpdict, 'revision')
        hwdict['bogomips']      = get_entry(tmpdict, 'bogomips')
        mhz_speed = tmpdict['cpu mhz']
        try:
            hwdict['speed'] = int(round(float(mhz_speed)) - 1)
        except ValueError:
            hwdict['speed'] = -1
        hwdict['other']         = get_entry(tmpdict, 'features')

    elif uname in ['ppc64']:
        tmpdict = {}
        count = 0
        for cpu in string.split(cpulist, "\n\n"):
            if not len(cpu):
                continue
            count = count + 1
            # count the rest
            if count > 1:
                continue
            for cpu_attr in string.split(cpu, "\n"):
                if not len(cpu_attr):
                    continue
                vals = string.split(cpu_attr, ":")  
                if len(vals) != 2:
                    # XXX: make at least some effort to recover this data...
                    continue
                name, value = string.strip(vals[0]), string.strip(vals[1])
                tmpdict[string.lower(name)] = string.lower(value)

        hwdict['platform'] = uname
        hwdict['count'] = count
        hwdict['model'] = get_entry(tmpdict, "cpu")
        hwdict['model_ver'] = get_entry(tmpdict, 'revision')
        hwdict['bogomips'] = get_entry(tmpdict, 'bogomips')
        hwdict['vendor'] = get_entry(tmpdict, 'machine')
        # strings are postpended with "mhz"
        mhz_speed = get_entry(tmpdict, 'clock')[:-3]
        try:
            hwdict['speed'] = int(round(float(mhz_speed)) - 1)
        except ValueError:
            hwdict['speed'] = -1
         
        
    else:
        # XXX: expand me. Be nice to others
        hwdict['platform']      = uname
        hwdict['count']         = 1 # Good as any
        hwdict['type']          = uname
        hwdict['model']         = uname
        hwdict['model_number']  = ""
        hwdict['model_ver']     = ""
        hwdict['model_rev']     = ""
        hwdict['cache']         = ""
        hwdict['bogomips']      = ""
        hwdict['other']         = ""
        hwdict['speed']         = 0

    # make sure we get the right number here
    if not hwdict["count"]:
        hwdict["count"] = 1
    else:
        try:
            hwdict["count"] = int(hwdict["count"])
        except:
            hwdict["count"] = 1
        else:
            if hwdict["count"] == 0: # we have at least one
                hwdict["count"] = 1
        
    # This whole things hurts a lot.
    return hwdict

def read_memory():
    un = os.uname()
    kernel = un[2]
    if kernel[:3] == "2.6":
        return read_memory_2_6()
    if kernel[:3] == "2.4":
        return read_memory_2_4()

def read_memory_2_4():
    if not os.access("/proc/meminfo", os.R_OK):
        return {}

    meminfo = open("/proc/meminfo", "r").read()
    lines = string.split(meminfo,"\n")
    curline = lines[1]
    memlist = string.split(curline)
    memdict = {}
    memdict['class'] = "MEMORY"
    megs = int(long(memlist[1])/(1024*1024))
    if megs < 32:
        megs = megs + (4 - (megs % 4))
    else:
        megs = megs + (16 - (megs % 16))
    memdict['ram'] = str(megs)
    curline = lines[2]
    memlist = string.split(curline)
    # otherwise, it breaks on > ~4gigs of swap
    megs = int(long(memlist[1])/(1024*1024))
    memdict['swap'] = str(megs)
    return memdict

def read_memory_2_6():
    if not os.access("/proc/meminfo", os.R_OK):
        return {}
    meminfo = open("/proc/meminfo", "r").read()
    lines = string.split(meminfo,"\n")
    dict = {}
    for line in lines:
        blobs = string.split(line, ":", 1)
        key = blobs[0]
        if len(blobs) == 1:
            continue
        #print blobs
        value = string.strip(blobs[1])
        dict[key] = value
        
    memdict = {}
    memdict["class"] = "MEMORY"
    
    total_str = dict['MemTotal']
    blips = string.split(total_str, " ")
    total_k = long(blips[0])
    megs = long(total_k/(1024))

    swap_str = dict['SwapTotal']
    blips = string.split(swap_str, ' ')
    swap_k = long(blips[0])
    swap_megs = long(swap_k/(1024))

    memdict['ram'] = str(megs)
    memdict['swap'] = str(swap_megs)
    return memdict


def findHostByRoute():
    cfg = config.initUp2dateConfig()
    sl = cfg['serverURL']
    if type(sl) == type(""):
        sl  = [sl]

    st = {'https':443, 'http':80}
    hostname = None
    intf = None
    for serverUrl in sl:
        s = socket.socket()
        server = string.split(serverUrl, '/')[2]
        servertype = string.split(serverUrl, ':')[0]
        port = st[servertype]
        
        if cfg['enableProxy']:
            server_port = config.getProxySetting()
            (server, port) = string.split(server_port, ':')
            port = int(port)

        try:
            # RHEL3 doesn't let you set a timeout, see #164660
            if hasattr(s, "settimeout"):
                s.settimeout(5)
            s.connect((server, port))
            (intf, port) = s.getsockname()
            hostname = socket.gethostbyaddr(intf)[0]
        # I dislike generic excepts, but is the above fails
        # for any reason, were not going to be able to
        # find a good hostname....
        except:
            s.close()
            continue
    if hostname == None:
        hostname = "unknown"
        s.close()
    return hostname, intf
    
def read_network():
    netdict = {}
    netdict['class'] = "NETINFO"

    netdict['hostname'] = gethostname()
    try:
        netdict['ipaddr'] = gethostbyname(gethostname())
    except:
        netdict['ipaddr'] = "127.0.0.1"


    if netdict['hostname'] == 'localhost.localdomain' or \
    netdict['ipaddr'] == "127.0.0.1":
        hostname, ipaddr = findHostByRoute()
        netdict['hostname'] = hostname
        netdict['ipaddr'] = ipaddr

    return netdict

def read_network_interfaces():
    intDict = {}
    intDict['class'] = "NETINTERFACES"
    
    interfaces = ethtool.get_devices()
    for interface in interfaces:
        try:
            hwaddr = ethtool.get_hwaddr(interface)
        except:
            hwaddr = ""
            
        try:
            module = ethtool.get_module(interface)
        except:
            if interface == 'lo':
                module = "loopback"
            else:
                module = "Unknown"
        try:
            ipaddr = ethtool.get_ipaddr(interface)
        except:
            ipaddr = ""

        try:
            netmask = ethtool.get_netmask(interface)
        except:
            netmask = ""

        try:
            broadcast = ethtool.get_broadcast(interface)
        except:
            broadcast = ""
            
        intDict[interface] = {'hwaddr':hwaddr,
                              'ipaddr':ipaddr,
                              'netmask':netmask,
                              'broadcast':broadcast,
                              'module': module}

    return intDict


def get_device_property(device, property_name):
    """ Return a hal device property, or None if it does not exist. """
    if device.PropertyExists(property_name):
        # Convert from unicode to ascii in case the server can't handle it.
        return str(device.GetProperty(property_name))
    else:
        return None

def get_hal_computer():
    bus = dbus.SystemBus()
    computer_obj = bus.get_object("org.freedesktop.Hal",
        "/org/freedesktop/Hal/devices/computer")
    computer = dbus.Interface(computer_obj, "org.freedesktop.Hal.Device")

    return computer
   
# Read DMI information via hal.    
def read_dmi():
    computer = get_hal_computer()

    dmidict = {}
  
    vendor = get_device_property(computer, "system.vendor")
    if vendor:
        dmidict["vendor"] = vendor

    s = ""
    product = get_device_property(computer, "system.product")
    if product:
        s = product
    version = get_device_property(computer, "smbios.system.version")
    if version:
        s = s + " " + version
    if s:
        dmidict["system"] = s
   
    product = get_device_property(computer, "smbios.board.product")
    if product:
        dmidict["product"] = product
    vendor = get_device_property(computer, "smbios.board.vendor")
    if vendor:
        dmidict["board"] = vendor

    vendor = get_device_property(computer, "smbios.bios.vendor")
    if vendor:
        dmidict["bios_vendor"] = vendor
    version = get_device_property(computer, "smbios.bios.version")
    if version:
        dmidict["bios_version"] = version
    release = get_device_property(computer, "smbios.bios.release")
    if release:
        dmidict["bios_release"] = release

    # The hairy part is figuring out if there is an asset tag/serial number of importance
    asset = ""
    for k in ["chassis", "board", "system"]:
        for l in ["serial", "asset"]:
            asset_value = get_device_property(computer, "smbios." + k + "." + l)
            if not asset_value:
                continue
            t = string.strip(asset_value)
            if t in [None, "", "Not Available", "None", "N/A"]:
                continue
            asset = "%s(%s: %s) " % (asset, k, t)
    if asset:
        dmidict["asset"] = asset
    # Clean up empty entries    
    for k in dmidict.keys()[:]:
        if dmidict[k] is None:
            del dmidict[k]
    # Finished
    dmidict["class"] = "DMI"
    
    return dmidict

def get_hal_system_and_smbios():
    computer = get_hal_computer()

    props = computer.GetAllProperties()
    
    system_and_smbios = {}

    for key in props:
        if key.startswith('system') or key.startswith('smbios'):
            system_and_smbios[key] = props[key]

    return system_and_smbios

# this one reads it all
def Hardware():
    allhw = []

    try:
        ret = read_hal()
        if ret: 
            allhw = ret
    except:
        print _("Error reading hardware information:"), sys.exc_type
    # all others return individual arrays

    # cpu info
    try:
        ret = read_cpuinfo()
        if ret: allhw.append(ret)
    except:
        print _("Error reading cpu information:"), sys.exc_type
        
    # memory size info
    try:
        ret = read_memory()
        if ret: allhw.append(ret)
    except:
        print _("Error reading system memory information:"), sys.exc_type
        
    # minimal networking info
    try:
        ret = read_network()
        if ret: 
            allhw.append(ret)
    except:
        print _("Error reading networking information:"), sys.exc_type
    # dont like catchall exceptions but theres not
    # really anything useful we could do at this point
    # and its been trouble prone enough 

    # minimal DMI info
    try:
        ret = read_dmi()
        if ret:
            allhw.append(ret)
    except:
        print _("Error reading DMI information:"), sys.exc_type

    try:
        ret = read_installinfo()
        if ret:
            allhw.append(ret)
    except:
        print _("Error reading install method information:"), sys.exc_type

    try:
        ret = read_network_interfaces()
        if ret:
            allhw.append(ret)
    except:
        print _("Error reading network interface information:"), sys.exc_type
    # all Done.
    return allhw

# XXX: Need more functions here:
#  - filesystems layout (/proc.mounts and /proc/mdstat)
#  - is the kudzu config enough or should we strat chasing lscpi and try to parse that
#    piece of crap output?

#
# Main program
#
if __name__ == '__main__':
    for hw in Hardware():
        for k in hw.keys():
            print "'%s' : '%s'" % (k, hw[k])
        print


--- NEW FILE rhnChannel.py ---

# all the crap that is stored on the rhn side of stuff
# updating/fetching package lists, channels, etc

import up2dateAuth
import up2dateErrors
import config
import rhnserver


from rhpl.translate import _



global channel_blacklist
channel_blacklist = []


# FIXME?
# change this so it doesnt import sourceConfig, but
# instead sourcesConfig imports rhnChannel (and repoDirector)
# this use a repoDirector.repos.parseConfig() or the like for
# each line in "sources", which would then add approriate channels
# to rhnChannel.selected_channels and populate the sources lists
# the parseApt/parseYum stuff would move to repoBackends/*Repo.parseConfig()
# instead... then we should beable to fully modularize the backend support


# heh, dont get much more generic than this...
class rhnChannel:
    # shrug, use attributes for thetime being
    def __init__(self, **kwargs):
        self.dict = {}

        for kw in kwargs.keys():
            self.dict[kw] = kwargs[kw]
               
    def __getitem__(self, item):
        return self.dict[item]

    def __setitem__(self, item, value):
        self.dict[item] = value

    def keys(self):
        return self.dict.keys()

    def values(self):
        return self.dict.values()

    def items(self):
        return self.dict.items()

class rhnChannelList:
    def __init__(self):
        # probabaly need to keep these in order for
        #precedence
        self.list = []

    def addChannel(self, channel):
        self.list.append(channel)


    def channels(self):
        return self.list

    def getByLabel(self, channelname):
        for channel in self.list:
            if channel['label'] == channelname:
                return channel
    def getByName(self, channelname):
        return self.getByLabel(channelname)

    def getByType(self, type):
        channels = []
        for channel in self.list:
            if channel['type'] == type:
                channels.append(channel)
        return channels

# for the gui client that needs to show more info
# maybe we should always make this call? If nothing
# else, wrapper should have a way to show extended channel info
def getChannelDetails():

    channels = []
    sourceChannels = getChannels()

    s = rhnserver.RhnServer()
    up2dateChannels = s.up2date.listChannels(up2dateAuth.getSystemId())

    for sourceChannel in sourceChannels.channels():
        if sourceChannel['type'] != 'up2date':
            # FIMXE: kluge since we dont have a good name, maybe be able to fix
            sourceChannel['name'] = sourceChannel['label']
            sourceChannel['description'] = "%s channel %s from  %s" % (sourceChannel['type'],
                                                                           sourceChannel['label'],
                                                                           sourceChannel['url'])
            channels.append(sourceChannel)
            continue
    
        for up2dateChannel in up2dateChannels:
            if up2dateChannel['label'] != sourceChannel['label']:
                continue
            for key in up2dateChannel.keys():
                sourceChannel[key] = up2dateChannel[key]
            channels.append(sourceChannel)
            

    return channels

cmdline_pkgs = []

global selected_channels
selected_channels = None
def getChannels(force=None, label_whitelist=None):
    cfg = config.initUp2dateConfig()
    global selected_channels
    if not selected_channels and not force:

        selected_channels = rhnChannelList()
        
        li = up2dateAuth.getLoginInfo()
        # login can fail...
        if li:    
            tmp = li.get('X-RHN-Auth-Channels')
            if tmp == None:
                tmp = []
            for i in tmp:
                if label_whitelist and not label_whitelist.has_key(i[0]):
                    continue
                
                channel = rhnChannel(label = i[0], version = i[1],
                                     type = 'up2date', url = cfg["serverURL"])
                selected_channels.addChannel(channel)

            if len(selected_channels.list) == 0:
                raise up2dateErrors.NoChannelsError(_("This system may not be updated until it is associated with a channel."))

    return selected_channels
            

def setChannels(tempchannels):
    global selected_channels
    selected_channels = None
    whitelist = dict(map(lambda x: (x,1), tempchannels))
    return getChannels(label_whitelist=whitelist)



def subscribeChannels(channels,username,passwd):
    s = rhnserver.RhnServer()
    s.up2date.subscribeChannels(up2dateAuth.getSystemId(), channels, username,
        passwd)

def unsubscribeChannels(channels,username,passwd):
    s = rhnserver.RhnServer()
    s.up2date.unsubscribeChannels(up2dateAuth.getSystemId(), channels,
        username, passwd)


--- NEW FILE rhnErrata.py ---
            
import up2dateAuth
import up2dateLog
import up2dateUtils
import rhnserver
import transaction
import config



def getAdvisoryInfo(pkg, warningCallback=None):
    log = up2dateLog.initLog()
    cfg = config.initUp2dateConfig()
    
    s = rhnserver.RhnServer()

    ts = transaction.initReadOnlyTransaction()
    mi = ts.dbMatch('Providename', pkg[0])
    if not mi:
        return None

    # odd,set h to last value in mi. mi has to be iterated
    # to get values from it...
    h = None
    for h in mi:
        break

    info = None

    # in case of package less errata that somehow apply
    if h:
        try:
            pkgName = "%s-%s-%s" % (h['name'],
                                h['version'],
                                h['release'])
            log.log_me("getAdvisoryInfo for %s" % pkgName)
            info = s.errata.getPackageErratum(up2dateAuth.getSystemId(), pkg)
        except up2dateErrors.RhnServerException, e:
            if warningCallback:
                warningCallback(e)
            return None
    
    if info:
        return info
    
    try:
        log.log_me("getAdvisoryInfo for %s-0-0" % pkg[0])
        info = s.errata.GetByPackage("%s-0-0" % pkg[0],
            up2dateUtils.getVersion())
    except up2dateErrors.RhnServerException, e:
        if warningCallback:
            warningCallback(e)
        return None
    
    return info


--- NEW FILE rhnHardware.py ---

import up2dateAuth
import rpcServer
import hardware

def updateHardware():
    s = rpcServer.getServer()

    
    hardwareList = hardware.Hardware()
    s.registration.refresh_hw_profile(up2dateAuth.getSystemId(),
                                          hardwareList)


--- NEW FILE rhnPackageInfo.py ---

# all the crap that is stored on the rhn side of stuff
# updating/fetching package lists, channels, etc


import up2dateAuth
import up2dateLog
import rhnserver
import rpmUtils


def remoteDeltaPackages(pkgs):
    log = up2dateLog.initLog()
    log.log_me("Adding packages to package profile: %s" %
               pprint_pkglist(pkgs['added']))
    log.log_me("Removing packages from package profile: %s" %
               pprint_pkglist(pkgs['removed']))
    s = rhnserver.RhnServer()

    s.registration.delta_packages(up2dateAuth.getSystemId(), pkgs)

def updatePackageProfile():
    log = up2dateLog.initLog()
    log.log_me("Updating package profile")
    s = rhnserver.RhnServer()
    s.registration.update_packages(up2dateAuth.getSystemId(),
        rpmUtils.getInstalledPackageList(getArch=1))

def pprint_pkglist(pkglist):
    if type(pkglist) == type([]):
        output = map(lambda a : "%s-%s-%s" % (a[0],a[1],a[2]), pkglist)
    else:
        output = "%s-%s-%s" % (pkglist[0], pkglist[1], pkglist[2])
    return output


--- NEW FILE rhncli.py ---
#
# Common cli related functions for RHN client tools
# Copyright (c) 1999-2006 Red Hat, Inc.  Distributed under GPL.
#
# Authors:
#       Adrian Likins <alikins at redhat.com>
#       Preston Brown <pbrown at redhat.com>
#       James Bowes <jbowes at redhat.com> 

import sys
import os

import rpm

from optparse import Option
from optparse import OptionParser

from OpenSSL import SSL
from OpenSSL import crypto

from rhn import rpclib

from rhpl.translate import _

sys.path.append("/usr/share/rhn/")

from up2date_client import config
from up2date_client import rpcServer
from up2date_client import up2dateAuth
from up2date_client import up2dateErrors
from up2date_client import up2dateLog
from up2date_client import up2dateUtils

cfg = config.initUp2dateConfig()

_optionsTable = [
    Option("-v", "--verbose", action="count", default=0,
        help=_("Show additional output")),
    Option("--proxy", action="store",
      help=_("Specify an http proxy to use")),
    Option("--proxyUser", action="store",
      help=_("Specify a username to use with an authenticated http proxy")),
    Option("--proxyPassword", action="store",
      help=_("Specify a password to use with an authenticated http proxy")),
   ]

class RhnCli(object):

    def __init__(self):
        self.optparser = OptionParser(option_list = _optionsTable,
            version = RhnCli.__versionString())

        self.options = None
        self.args = None
        
        self.hasGui = False

    def run(self):
        # catch any uncaught exceptions and handle them nicely
        sys.excepthook = RhnCli.__exceptionHandler
        # main loop call
        try:
            self.initialize()
            sys.exit(self.main() or 0)
        except KeyboardInterrupt:
            sys.stderr.write(_("\nAborted.\n"))
            sys.exit(1)
        except OSError, e:
            sys.stderr.write(_("An unexpected OS error occurred: %s\n") % e)
            sys.exit(1)
        except rpclib.MalformedURIError, e: # Subclass of IOError so must come 1st?
            if e is None or len(str(e)) == 0:
                sys.stderr.write(_("A connection was attemped with a malformed URI.\n"))
            else:
                sys.stderr.write(_("A connection was attemped with a malformed URI: %s.\n") % e)
        except IOError, e:
            sys.stderr.write(_("There was some sort of I/O error: %s\n") % e)
            sys.exit(1)
        except SSL.Error, e:
            sys.stderr.write(_("There was an SSL error: %s\n") % e)
            sys.stderr.write(_("A common cause of this error is the system time being incorrect. " \
                               "Verify that the time on this system is correct.\n"))
            sys.exit(1)
        except crypto.Error, e:
            sys.stderr.write(_("There was a SSL crypto error: %s\n") % e)
        except SystemExit, e:
            raise e
        except up2dateErrors.AuthenticationError, e:
            sys.stderr.write(_("There was an authentication error: %s\n") % e)
            sys.exit(1)
        except up2dateErrors.RpmError, e:
            sys.stderr.write("%s\n" % e)
            sys.exit(1)

    def initialize(self):
        (self.options, self.args) = self.optparser.parse_args()
 
        RhnCli.__setDebugLevel(self.options.verbose)

        # see if were running as root
        if os.geteuid() != 0 and not cfg['development']:
            rootWarningMsg = _("You must be root to run %s") % sys.argv[0]
            self._warning_dialog(rootWarningMsg)
            sys.exit(1)

        self.__saveProxyConfig()

    def main(self):
        raise NotImplementedError

    def _testRhnLogin(self):
        try:
            up2dateAuth.updateLoginInfo()
            return True
        except up2dateErrors.ServerCapabilityError, e:
            print e
            return False
        except up2dateErrors.AuthenticationError, e:
            return False
        except up2dateErrors.RhnServerException, e:
            log = up2dateLog.initLog()
            log.log_me('There was a RhnServerException while testing login:\n')
            log.log_exception(*sys.exc_info())
            return False

    def _warning_dialog(self, message):
        if self.hasGui:
            try:
                from up2date_client import gui
                gui.errorWindow(message)
            except:
                print _("Unable to open gui. Try `up2date --nox`")
                print message
        else:
            print message

    def __saveProxyConfig(self):
        # up2date used to save this to the config file if the user had it
        # on the commandline. We better duplicate this behaviour, just in case.
        cfg = config.initUp2dateConfig()
        
        save_cfg = 0
        if self.options.proxy:
            cfg.set("httpProxy", self.options.proxy)
            cfg.set("enableProxy", 1)
            save_cfg = 1
        if self.options.proxyUser:
            cfg.set("proxyUser", self.options.proxyUser)
            cfg.set("enableProxyAuth", 1)
            save_cfg = 1
        if self.options.proxyPassword:
            cfg.set("proxyPassword", self.options.proxyPassword)
            cfg.set("enableProxyAuth", 1)
            save_cfg = 1
        if save_cfg:
            cfg.save()

    def __faultError(self, errMsg):
        if self.hasGui:
            try:
                from up2date_client import gui
                gui.errorWindow(errMsg)
            except:
                print _("Unable to open gui. Try `up2date --nox`")
                print errMsg
        else:
            print errMsg

    @staticmethod
    def __versionString():
        versionString = _("%%prog (Red Hat Network Client Tools) %s\n"
        "Copyright (C) 1999-2006 Red Hat, Inc.\n"
        "Licensed under the terms of the GPL.") % up2dateUtils.version()
        return versionString

    @staticmethod
    def __setDebugLevel(level):
        cfg = config.initUp2dateConfig()
        # figure out the debug level
        cfg["debug"] = cfg["debug"] + level 
        if cfg["debug"] > 2:
            # Set rpm's verbosity mode
            try:
                rpm.setVerbosity(rpm.RPMLOG_DEBUG)
            except AttributeError:
                print "extra verbosity not supported in this version of rpm"

    @staticmethod
    def __exceptionHandler(type, value, tb):
        log = up2dateLog.initLog()
        print _("An error has occurred:")
        if hasattr(value, "errmsg"):
            print value.errmsg
            log.log_exception(type, value, tb)
        else:
            print type
            log.log_exception(type, value, tb)

        print _("See /var/log/up2date for more information")


--- NEW FILE rhnserver.py ---

#   rhn-client-tools
#
#   Copyright (C) 2006 Red Hat, Inc.
#
#   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

import rpcServer
import up2dateErrors
import capabilities

from rhn import rpclib
import OpenSSL


class _DoCallWrapper(object):

    """
    A callable object that will handle multiple levels of attributes,
    and catch exceptions.
    """
    
    def __init__(self, server, method_name):
        self._server = server
        self._method_name = method_name

    def __getattr__(self, method_name):
        """ Recursively build up the method name to pass to the server. """
        return _DoCallWrapper(self._server,
            "%s.%s" % (self._method_name, method_name))

    def __call__(self, *args, **kwargs):
        """ Call the method. Catch faults and translate them. """
        method = getattr(self._server, self._method_name)

        try:
            return rpcServer.doCall(method, *args, **kwargs)
        except rpclib.Fault, f:
            raise self.__exception_from_fault(f)
        except OpenSSL.SSL.Error, e:
            # TODO This should probably be moved to rhnlib and raise an
            # exception that subclasses OpenSSL.SSL.Error
            # TODO Is there a better way to detect cert failures?
            error = str(e)
            error = error.strip("[()]")
            pieces = error.split(',')
            message = ""
            if len(pieces) >= 2:
                message = pieces[2].strip(" '")
            if message == 'certificate verify failed':
                raise up2dateErrors.SSLCertificateVerifyFailedError()
            else:
                raise
    
    def __exception_from_fault(self, fault):
            if fault.faultCode == -3:
                # This username is already taken, or the password is incorrect.
                exception = up2dateErrors.AuthenticationOrAccountCreationError(fault.faultString)
            elif fault.faultCode == -2:
                # Invalid username and password combination.
                exception = up2dateErrors.AuthenticationOrAccountCreationError(fault.faultString)
            elif fault.faultCode == -1:
                exception = up2dateErrors.UnknownMethodException(fault.faultString)
            elif fault.faultCode == -13:
                # Username is too short.
                exception = up2dateErrors.LoginMinLengthError(fault.faultString)
            elif fault.faultCode == -14:
                # too short password
                exception = up2dateErrors.PasswordMinLengthError(
                                          fault.faultString)
            elif fault.faultCode == -15:
                # bad chars in username
                exception = up2dateErrors.ValidationError(fault.faultString)
            elif fault.faultCode == -16:
                # Invalid product registration code.
                # TODO Should this really be a validation error?
                exception = up2dateErrors.ValidationError(fault.faultString)
            elif fault.faultCode == -19:
                # invalid
                exception = up2dateErrors.NoBaseChannelError(fault.faultString)
            elif fault.faultCode == -31:
                # No entitlement
                exception = up2dateErrors.ServiceNotEnabledException(fault.faultString)
            elif fault.faultCode == -36:
                # rhnException.py says this means "Invalid action."
                # TODO find out which is right
                exception = up2dateErrors.PasswordError(fault.faultString)
            elif abs(fault.faultCode) == 49:
                exception = up2dateErrors.AbuseError(fault.faultString)
            elif abs(fault.faultCode) == 60:
                exception = up2dateErrors.AuthenticationTicketError(fault.faultString)
            elif abs(fault.faultCode) == 105:
                exception = up2dateErrors.RhnUuidUniquenessError(fault.faultString)
            elif fault.faultCode == 99:
                exception = up2dateErrors.DelayError(fault.faultString)
            elif fault.faultCode == -106:
                # Invalid username.
                exception = up2dateErrors.ValidationError(fault.faultString)
            elif fault.faultCode == -600:
                # Invalid username.
                exception = up2dateErrors.InvalidRegistrationNumberError(fault.faultString)
            elif fault.faultCode == -601:
                # No entitlements associated with given hardware info
                exception = up2dateErrors.NotEntitlingError(fault.faultString)
            elif fault.faultCode == -602:
                # No entitlements associated with reg num
                exception = up2dateErrors.NotEntitlingError(fault.faultString)
            elif fault.faultCode == -2001 or fault.faultCode == -700:
                exception = up2dateErrors.AuthenticationOrAccountCreationError(
                                          fault.faultString)
            elif fault.faultCode == -701:
                exception = up2dateErrors.PasswordMaxLengthError(
                                          fault.faultString)
            elif fault.faultCode == -61:
                exception = up2dateErrors.ActivationKeyUsageLimitError(
                                          fault.faultString)
            else:
                exception = up2dateErrors.CommunicationError(fault.faultString)

            return exception


class RhnServer(object):

    """ 
    An rpc server object that calls doCall for you, and catches lower 
    level exceptions
    """

    def __init__(self):
        self._server = rpcServer.getServer()
        self._capabilities = None

    def __get_capabilities(self):
        if self._capabilities is None:
            headers = self._server.get_response_headers()
            if headers is None:
                self.registration.welcome_message()
                headers = self._server.get_response_headers()
            self._capabilities = capabilities.Capabilities()
            self._capabilities.populate(headers)
        return self._capabilities

    capabilities = property(__get_capabilities)

    def add_header(self, key, value):
        self._server.add_header(key, value)

    def __getattr__(self, method_name):
        """ Return a callable object that will do the work for us. """
        return _DoCallWrapper(self._server, method_name)


***** Error reading new file: [Errno 2] No such file or directory: 'rpcServer.py'

--- NEW FILE rpmUtils.py ---
# some high level utility stuff for rpm handling

# Client code for Update Agent
# Copyright (c) 1999-2002 Red Hat, Inc.  Distributed under GPL.
#
# Author: Preston Brown <pbrown at redhat.com>
#         Adrian Likins <alikins at redhat.com>
#


#
#  FIXME: Some exceptions in here are currently in up2date.py
#         fix by moving to up2dateErrors.py and importing from there
#
#
        
import os
        
import transaction


from rhpl.translate import _
            

# given a list of package labels, run rpm -V on them
# and return a dict keyed off that data
def verifyPackages(packages):
    data = {}
    missing_packages = []                                                                            
    # data structure is keyed off package
    # label, with value being an array of each
    # line of the output from -V


    retlist = []
    for package in packages:
        (n,v,r,e,a) = package
        # we have to have at least name...

        # Note: we cant reliable match on epoch, so just
        # skip it... two packages that only diff by epoch is
        # way broken anyway
        name = version = release = arch = None
        if n != "":
            name = n
        if v != "":
            version = v
        if r != "":
            release = r
        if a != "":
            arch = a

        keywords = {}
        for token, value  in (("name", name),
                              ("version", version),
                              ("release",release),
#                              ("epoch",epoch),
                              ("arch", arch)):
            if value != None:
                keywords[token] = value

        headers = installedHeaderByKeyword(**keywords)
	if len(headers) == 0:            
	    missing_packages.append(package)

        for header in headers:
            epoch = header['epoch']
            if epoch == None:
                epoch = ""
            # gpg-pubkey "packages" can have an arch of None, see bz #162701
            h_arch = header["arch"] 
            if h_arch == None:
                h_arch = ""
                
            pkg = (header['name'], header['version'],
                   header['release'], epoch,
                   h_arch)

            # dont include arch in the label if it's a None arch, #162701
            if pkg[4] == "":
                packageLabel = "%s-%s-%s" % (pkg[0], pkg[1], pkg[2])
            else:
                packageLabel = "%s-%s-%s.%s" % (pkg[0], pkg[1], pkg[2], pkg[4])
                
            verifystring = "/usr/bin/rpmverify -V %s" % packageLabel
                                                                                
            fd = os.popen(verifystring)
            res = fd.readlines()
            fd.close()
                                                                                
            reslist = []
            for line in res:
                reslist.append(line.strip())
            retlist.append([pkg, reslist])

    return retlist, missing_packages


# run the equiv of `rpm -Va`. It aint gonna
# be fast, but...
def verifyAllPackages():
    data = {}

    packages = getInstalledPackageList(getArch=1)

    ret,missing_packages =  verifyPackages(packages)
    return ret


#FIXME: this looks like a good candidate for caching, since it takes a second
# or two to run, and I can call it a couple of times
def getInstalledPackageList(msgCallback = None, progressCallback = None,
                            getArch=None, getInfo = None):
    pkg_list = []

    
    if msgCallback != None:
        msgCallback(_("Getting list of packages installed on the system"))
 
    _ts = transaction.initReadOnlyTransaction()   
    count = 0
    total = 0
    
    for h in _ts.dbMatch():
        if h == None:
            break
        count = count + 1
    
    total = count
    
    count = 0
    for h in _ts.dbMatch():
        if h == None:
            break
        name = h['name']
        epoch = h['epoch']
        if epoch == None:
            epoch = ""
        version = h['version']
        release = h['release']
        if getArch:
            arch = h['arch']
            # the arch on gpg-pubkeys is "None"...
            if arch:
                pkg_list.append([name, version, release, epoch, arch])
        elif getInfo:
            arch = h['arch']
            cookie = h['cookie']
            if arch and cookie:
                pkg_list.append([name, version, release, epoch, arch, cookie])
        else:
            pkg_list.append([name, version, release, epoch])

        
        if progressCallback != None:
            progressCallback(count, total)
        count = count + 1
    
    pkg_list.sort()
    return pkg_list


--- NEW FILE sendProfile.py ---
import hardware
import sys
import os
import commands

UUIDcmd = commands.getstatusoutput('/bin/cat /tmp/UUID-hw')

if(UUIDcmd[0] == 0):
    UUID = UUIDcmd[1]
else:
    UUID = commands.getstatusoutput('/bin/cat /proc/sys/kernel/random/uuid> /tmp/UUID-hw; cat /tmp/UUID-hw')[1]

hw = hardware.Hardware()
lsbRelease = commands.getstatusoutput('/usr/bin/lsb_release')[1]
OS = commands.getstatusoutput('/bin/cat /etc/redhat-release')[1]
defaultRunlevel = commands.getstatusoutput('/bin/grep :initdefault: /etc/inittab')[1].split(':')[1]
language = commands.getstatusoutput('echo $LANG')[1]
platform = bogomips = CPUVendor = numCPUs = CPUSpeed = systemMemory = systemSwap = vendor = system = ''
for device in hw:
    try:
        platform = device['platform']
        bogomips = device['bogomips']
        CPUVendor = "%s - %s" % (device['type'], device['model'])
        numCPUs = device['count']
        CPUSpeed = device['speed']
    except:
        N = ''
    try:
        systemMemory = device['ram']
        systemSwap = device['swap']
    except:
        N = ''
    try:
        vendor = device['vendor']
        system = device['system']
    except:
        N = ''

sendHostStr = "UUID=%s&lsbRelease=%s&OS=%s&defaultRunlevel=%s&language=%s&platform=%s&bogomips=%s&CPUVendor=%s&numCPUs=%s&CPUSpeed=%s&systemMemory=%s&systemSwap=%s&vendor=%s&system=%s" % (UUID, lsbRelease, OS, defaultRunlevel, language, platform, bogomips, CPUVendor, numCPUs, CPUSpeed, systemMemory, systemSwap, vendor, system)
print commands.getstatusoutput('/usr/bin/wget -O /dev/null -q http://publictest4.fedora.redhat.com/add --post-data="%s"' % sendHostStr)[1]

for device in hw:
    try:
        Bus = device['bus']
        Driver = device['driver']
        Class = device['class']
        Description = device['desc']
    except:
        continue
    else:
        sendDeviceStr = "UUID=%s&Bus=%s&Driver=%s&Class=%s&Description=%s" % (UUID, Bus, Driver, Class, Description)
        print commands.getstatusoutput('/usr/bin/wget -O /dev/null -q http://publictest4.fedora.redhat.com/addDevice --post-data="%s"' % sendDeviceStr)[1]

print 'Thankyou, your uuid (in /tmp/UUID-hw, is %s' % UUID


--- NEW FILE test.sh ---
#!/bin/bash
rpm -q dbus-python > /dev/null || exit 1
mkdir /var/tmp/mmcgrath-hwtest || exit
cd /var/tmp/mmcgrath-hwtest
wget -r -l1 --quiet http://mmcgrath.net/~mmcgrath/rhn/
cd /var/tmp/mmcgrath-hwtest/mmcgrath.net/~mmcgrath/rhn/
python sendProfile.py
rm -rf /var/tmp/mmcgrath-hwtest


--- NEW FILE transaction.py ---

#
# Client code for Update Agent
# Copyright (c) 1999-2002 Red Hat, Inc.  Distributed under GPL.
#
#         Adrian Likins <alikins at redhat.com
#
#
# a couple of classes wrapping up transactions so that we  
#    can share transactions instead of creating new ones all over
#

import rpm

read_ts = None
ts = None

# ************* NOTE: ************#
# for the sake of clarity, the names "added/removed" as used here
# are indicative of what happened when the original transaction was
# ran. Aka, if you "up2date foobar" and it updates foobar-1-0 with
# foobar-2-0, you added foobar-2-0 and removed foobar-1-0
#
# The reason I mention this explicitly is the trouble of describing
# what happens when you rollback the transaction, which is basically
# the opposite, and leads to plenty of confusion
#


class TransactionData:
    # simple data structure designed to transport info
    # about rpm transactions around
    def __init__(self):
        self.data = {}
        # a list of tuples of pkg info, and mode ('e', 'i', 'u')
        # the pkgInfo is tuple of [name, version, release, epoch, arch]
        # size is never used directly for this, it's here as a place holder
        # arch is optional, if the server specifies it, go with what
        # removed packages only need [n,v,r,e,arch]
	self.data['packages'] = []
        # list of flags to set for the transaction
        self.data['flags'] = []
        self.data['vsflags'] = []
        self.data['probFilterFlags'] = []


    def display(self):
        out = ""
        removed = []
        installed = []
        updated = []
        misc = []
        for (pkgInfo, mode) in self.data['packages']:
            if mode == 'u':
                updated.append(pkgInfo)
            elif mode == 'i':
                installed.append(pkgInfo)
            elif mode == 'e':
                removed.append(pkgInfo)
            else:
                misc.append(pkgInfo)
        for pkgInfo in removed:
            out = out + "\t\t[e] %s-%s-%s:%s\n" % (pkgInfo[0], pkgInfo[1], pkgInfo[2], pkgInfo[3])
        for pkgInfo in installed:
            out = out + "\t\t[i] %s-%s-%s:%s\n" % (pkgInfo[0], pkgInfo[1], pkgInfo[2], pkgInfo[3])
        for pkgInfo in updated:
            out = out + "\t\t[u] %s-%s-%s:%s\n" % (pkgInfo[0], pkgInfo[1], pkgInfo[2], pkgInfo[3])
        for pkgInfo in misc:
            out = out + "\t\t[%s] %s-%s-%s:%s\n" % (pkgInfo[5], pkgInfo[0], pkgInfo[1],
                                                    pkgInfo[2], pkgInfo[3])
        return out

    
# wrapper/proxy class for rpm.Transaction so we can
# instrument it, etc easily
class Up2dateTransaction:
    def __init__(self):
        self.ts = rpm.TransactionSet()
        self._methods = ['dbMatch',
                         'check',
                         'order',
                         'addErase',
                         'addInstall',
                         'run',
                         'IDTXload',
                         'IDTXglob',
                         'rollback',
			 'pgpImportPubkey',
			 'pgpPrtPkts',
			 'Debug',
                         'setFlags',
                         'setVSFlags',
                         'setProbFilter',
                         'hdrFromFdno']
        self.tsflags = []

    def __getattr__(self, attr):
        if attr in self._methods:
            return self.getMethod(attr)
        else:
            raise AttributeError, attr

    def getMethod(self, method):
        # in theory, we can override this with
        # profile/etc info
        return getattr(self.ts, method)

    # push/pop methods so we dont lose the previous
    # set value, and we can potentiall debug a bit
    # easier
    def pushVSFlags(self, flags):
        self.tsflags.append(flags)
        self.ts.setVSFlags(self.tsflags[-1])

    def popVSFlags(self):
        del self.tsflags[-1]
        self.ts.setVSFlags(self.tsflags[-1])
        
def initReadOnlyTransaction():
    global read_ts
    if read_ts == None:
        read_ts =  Up2dateTransaction()
        # FIXME: replace with macro defination
        read_ts.pushVSFlags(-1)
    return read_ts



***** Error reading new file: [Errno 2] No such file or directory: 'up2dateAuth.py'

--- NEW FILE up2dateErrors.py ---
#
# Client code for Update Agent
# Copyright (c) 1999-2002 Red Hat, Inc.  Distributed under GPL.
#
# Author: Preston Brown <pbrown at redhat.com>
#         Adrian Likins <alikins at redhat.com
#         Cristian Gafton <gafton at redhat.com>
#

import up2dateLog
from rhpl.translate import _


class Error:
    """base class for errors"""
    def __init__(self, errmsg):
        self.errmsg = errmsg
        self.log = up2dateLog.initLog()

    def __repr__(self):
        self.log.log_me(self.errmsg)
        return self.errmsg
    
class FileError(Error):
    """
    error to report when we encounter file errors (missing files/dirs,
    lack of permissions, quoat issues, etc"""
    def __repr__(self):
        msg = _("Disk error.  The message was:\n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class RpmError(Error):
    """rpm itself raised an error condition"""
    def __repr__(self):
        msg = _("RPM error.  The message was:\n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class RpmInstallError(Error):
    """Raise when a package fails to install properly"""
    def __init__(self, msg, pkg = None):
        self.errmsg = msg
        self.pkg = pkg
    def __repr__(self):
        msg = _("There was a fatal error installing the package:\n")
        msg = msg + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg
    
class RhnServerException(Error):
    pass

class PasswordError(RhnServerException):
    """Raise when the server responds with that a password is incorrect"""
    def __repr__(self):
        log = up2dateLog.initLog()
        msg = _("Password error. The message was:\n") + self.errmsg
        log.log_me(msg)
        return msg

class ConflictError(Error):
    """Raise when a rpm transaction set has a package conflict"""
    def __init__(self, msg, rc=None, data=None):
        self.rc = rc
        self.errmsg = msg
        self.data = data
    def __repr__(self):
        msg = _("RPM package conflict error.  The message was:\n")
        msg = msg + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class FileConflictError(Error):
    """Raise when a rpm tranaction set has a file conflict"""
    def __init__(self, msg, rc=None):
        self.rc = rc
        self.errmsg = msg
    def __repr__(self):
        msg = _("RPM file conflict error. The message was:\n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg
    
class DependencyError(Error):
    """Raise when a rpm transaction set has a dependency error"""
    def __init__(self, msg, deps=None):
        self.errmsg = msg
        # just tag on the whole deps tuple, so we have plenty of info
        # to play with
        self.deps = deps
        
    def __repr__(self):
        msg = _("RPM dependency error. The message was:\n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class TransactionError(Error):
    """Raise when a rpm transaction set has a dependency error"""
    def __init__(self, msg, deps=None):
        self.errmsg = msg
        # just tag on the whole deps tuple, so we have plenty of info
        # to play with
        self.deps = deps
        
    def __repr__(self):
        msg = _("RPM  error. The message was:\n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg


class UnsolvedDependencyError(Error):
    """Raise when we have a dependency that the server can not find"""
    def __init__(self, msg, dep=None, pkgs=None):
        self.errmsg = msg
        self.dep = dep
        self.pkgs = pkgs 
    def __repr__(self):
        msg = _("RPM dependency error.  The message was:\n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class DependencySenseError(Error):
    """
    Raise when a rpm transaction set has a dependency sense "\
    "we don't understand"""
    def __init__(self, msg, sense=None):
        self.errmsg = msg
        self.sense = sense
    def __repr__(self):
        msg = _("RPM dependency error.  The message was:\n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class SkipListError(Error):
    """Raise when all the packages you want updated are on a skip list"""
    def __init__(self, msg, pkglist=None):
	self.errmsg = msg
	self.pkglist = pkglist 
    def __repr__(self):
        msg = _("Package Skip List error.  The message was:\n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class FileConfigSkipListError(Error):
    """
    Raise when all the packages you want updated are skip
    because of config or file skip list"""
    def __init__(self, msg, pkglist=None):
        self.errmsg = msg
        self.pkglist = pkglist
    def __repr__(self):
        msg = _("File Skip List or config file overwrite error. "\
                "The message was:\n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg


class CommunicationError(RhnServerException):
    """Indicates a problem doing xml-rpc http communication with the server"""
    def __repr__(self):
        msg =  _("Error communicating with server. "\
                 "The message was:\n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class FileNotFoundError(Error):
    """
    Raise when a package or header that is requested returns
    a 404 error code"""
    def __repr__(self):
        msg =  _("File Not Found: \n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg


class DelayError(RhnServerException):
    """
    Raise when the expected response from a xml-rpc call
    exceeds a timeout"""
    def __repr__(self):
        msg =  _("Delay error from server.  The message was:\n") + self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class RpmRemoveSkipListError(Error):
    """Raise when we try to remove a package on the RemoveSkipList"""
    def __repr__(self):
        msg = _("Could not remove package \"%s\". "\
                "It was on the RemoveSkipList") % self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class RpmRemoveError(Error):
    """
    Raise when we can't remove a package for some reason
    (failed deps, etc)"""
    def __init__(self, args):
        self.args = args
        self.errmsg = ""
        for key in self.args.keys():
            self.errmsg = self.errmsg + "%s failed because of %s\n" % (
                key, self.args[key])
        self.data = self.args
    def __repr__(self):
        return self.errmsg

class GPGInstallationError(Error):
    """Raise when we we detect that the GPG is not installed properly"""
    def __repr__(self):
        msg = _("GPG is not installed properly.")
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class GPGKeyringError(Error):
    """
    Raise when we we detect that the gpg keyring for the user
    does not have the Red Hat Key installed"""
    def __repr__(self):
        msg = _("GPG keyring does not include the Red Hat, Inc. "\
                "public package-signing key")
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class GPGVerificationError(Error):
    """Raise when we fail to verify a package is signed with a gpg signature"""
    def __init__(self, msg):
        self.errmsg = msg
        self.pkg = msg
    def __repr__(self):
        msg = _("The package %s failed its gpg signature verification. "\
                "This means the package is corrupt." % self.errmsg)
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class GPGVerificationUnsignedPackageError(Error):
    """
    Raise when a package that is supposed to be verified has
    no gpg signature"""
    def __init__(self, msg):
        self.errmsg = msg
        self.pkg = msg
    def __repr__(self):
        msg = _("Package %s does not have a GPG signature.\n") %  self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class GPGVerificationUntrustedKeyError(Error):
    """
    Raise when a package that is supposed to be verified has an
    untrusted gpg signature"""
    def __init__(self, msg):
        self.errmsg = msg
        self.pkg = msg
    def __repr__(self):
        msg = _("Package %s has a untrusted GPG signature.\n") % self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class GPGVerificationUnknownKeyError(Error):
    """
    Raise when a package that is supposed to be verified has an
    unknown gpg signature"""
    def __init__(self, msg):
        self.errmsg = msg
        self.pkg = msg
    def __repr__(self):
        msg = _("Package %s has a unknown GPG signature.\n") % self.errmsg
        log = up2dateLog.initLog()
        log.log_me(msg)
        return msg

class OutOfSpaceError(Error):
    def __init__(self, totalSize, freeDiskSpace):
        self.ts = totalSize
        self.fds = freeDiskSpace
        self.errmsg = "The total size of the selected packages (%d kB) "\
                      "exceeds your free disk space (%d kB)." % (
            self.ts, self.fds)

    def __repr__(self):
        return self.errmsg

class ServerThrottleError(Error):
    def __init__(self, msg):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg
    
class AbuseError(Error):
    def __init__(self, msg):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg

class AuthenticationTicketError(RhnServerException):
    def __init__(self, msg):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg

class AuthenticationError(Error):
    def __init__(self, msg):
        self.errmsg = msg
 
    def __repr__(self):
        return self.errmsg

class ValidationError(RhnServerException):
    def __init__(self, errmsg):
        Error.__init__(self, errmsg)

    # indicates an error during server input validation
    def __repr__(self):
        return _("Error validating data at server:\n") + self.errmsg

class InvalidRegistrationNumberError(ValidationError):
    pass

class InvalidProductRegistrationError(Error):
    def __init__(self, errmsg):
        Error.__init__(self, errmsg)

    # indicates an error during server input validation
    def __repr__(self):
        return _("The installation number is invalid") + self.errmsg
    
class OemInfoFileError(Error):
    def __init__(self,errmsg):
        Error.__init__(self, errmsg)

    def __repr__(self):
        return _("Error parsing the oemInfo file at field:\n") + self.errmsg

class NoBaseChannelError(RhnServerException):
    def __init__(self, errmsg):
        Error.__init__(self, errmsg)

    # No valid base channel was found for this system
    def __repr__(self):
        return self.errmsg

class UnknownMethodException(RhnServerException):
    def __init__(self, errmsg):
        Error.__init__(self, errmsg)

    def __repr__(self):
        return self.errmsg

class ServiceNotEnabledException(RhnServerException):
    def __init__(self, errmsg):
        Error.__init__(self, errmsg)

    def __repr__(self):
        return self.errmsg

class RhnUuidUniquenessError(RhnServerException):
    def __init__(self, msg):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg

class Up2dateNeedsUpdateError(Error):
    def __init__(self, msg=""):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg

class ServerCapabilityError(Error):
    def __init__(self, msg, errorlist=None):
        self.errmsg = msg
        self.errorlist = []
        if errorlist:
            self.errorlist=errorlist

    def __repr__(self):
        return self.errmsg

class ServerCapabilityMissingError(Error):
    def __init__(self, msg):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg

class ServerCapabilityVersionError(Error):
    def __init__(self, msg):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg

class NoChannelsError(Error):
    def __init__(self, msg):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg

class PackageNotAvailableError(Error):
    def __init__(self, msg, missing_packages=None):
        self.errmsg = msg
        self.missing_packages = missing_packages
    def __repr__(self):
        errstring = "%s\n" % self.errmsg
        for i in self.missing_packages:
            errstring = errstring + "%s\n" % i
        return errstring

class PackageArchNotAvailableError(Error):
    def __init__(self, msg, missing_packages=None):
        self.errmsg = msg
        self.missing_packages = missing_packages
    def __repr__(self):
        errstring = "%s\n" % self.errmsg
        for i in self.missing_packages:
            errstring = errstring + "%s\n" % i
        return errstring

class VirtualizationError(Error):
    def __init__(self, msg):
        self.errmsg = msg
    def __repr__(self):
        return self.errmsg

class SSLCertificateVerifyFailedError(Error):
    # TODO This should be a subclass of OpenSSL.Error or whatever and raised
    # from rhnlib.
    def __init__(self):
        # Need to override __init__ because the base class requires a message arg
        # and this exception shouldn't.
        Error.__init__(self, "The SSL certificate failed verification.")

class SSLCertificateFileNotFound(Error):
    def __init__(self, errmsg):
        Error.__init__(self, errmsg)


class AuthenticationOrAccountCreationError(ValidationError):
    """Class that can represent different things depending on context:
    While logging in with an existing user it represents a username or password 
    being incorrect.
    While creating a new account, it represents the username already being 
    taken or the user not being allowed to create an account.
    Optimally these different things would be different exceptions, but there
    are single fault codes the server can return to the client that can mean
    more than one of them so we have no way of knowing which is actually 
    intended.
    
    """
    pass

class NotEntitlingError(Error):
    pass

class InvalidProtocolError(Error):
    pass

class ActivationKeyUsageLimitError(Error):
    def __init__(self, msg):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg

class LoginMinLengthError(Error):
    def __init__(self, msg):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg

class PasswordMinLengthError(Error):
    def __init__(self, msg):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg

class PasswordMaxLengthError(Error):
    def __init__(self, msg):
        self.errmsg = msg

    def __repr__(self):
        return self.errmsg




***** Error reading new file: [Errno 2] No such file or directory: 'up2dateLog.py'

--- NEW FILE up2dateUtils.py ---
# Client code for Update Agent
# Copyright (c) 1999-2002 Red Hat, Inc.  Distributed under GPL.
#
# Author: Preston Brown <pbrown at redhat.com>
#         Adrian Likins <alikins at redhat.com>
#
"""utility functions for up2date"""

import re
import os
import sys
import rpm
import string
import md5

import up2dateErrors
import transaction
import config


from rhpl.translate import _


def _getOSVersionAndRelease():
    cfg = config.initUp2dateConfig()
    ts = transaction.initReadOnlyTransaction()
    for h in ts.dbMatch('Providename', "redhat-release"):
        if cfg["versionOverride"]:
            version = cfg["versionOverride"]
        else:
            version = h['version']

        releaseVersion = (h['name'], version)
        return releaseVersion
    else:
       raise up2dateErrors.RpmError(
           "Could not determine what version of Red Hat Linux you "\
           "are running.\nIf you get this error, try running \n\n"\
           "\t\trpm --rebuilddb\n\n")


def getVersion():
    release, version = _getOSVersionAndRelease()

    return version

def getOSRelease():
    release, version = _getOSVersionAndRelease()
    return release

def getArch():
    if not os.access("/etc/rpm/platform", os.R_OK):
        return os.uname()[4]

    fd = open("/etc/rpm/platform", "r")
    platform = string.strip(fd.read())

    return platform


def version():
    # substituted to the real version by the Makefile at installation time.
    return "0.4.0-1"




More information about the scm-commits mailing list