def add_hardware(self, hardware):
        log_debug(4, hardware)
        if not hardware:
            return -1
        if type(hardware) == type({}):
            hardware = UserDictCase(hardware)
        if not isinstance(hardware, UserDictCase):
            log_error("argument type is not  hash: %s" % hardware)
            raise TypeError, "This function requires a hash as an argument"
        # validation is important
        hw_class = hardware.get("class")
        if hw_class is None:
            return -1
        hw_class = string.lower(hw_class)

        class_type = None
        
        if hw_class in ["video", "audio", "audio_hd", "usb", "other", "hd", "floppy",
                        "mouse", "modem", "network", "cdrom", "scsi",
                        "unspec", "scanner", "tape", "capture", "raid",
                        "socket", "keyboard", "printer", "firewire", "ide"]:
            class_type = HardwareDevice
        elif hw_class == "cpu":
            class_type = CPUDevice
        elif hw_class == "netinfo":
            class_type = NetworkInformation
        elif hw_class == "memory":
            class_type = MemoryInformation
        elif hw_class == "dmi":
            class_type = DMIInformation
        elif hw_class == "installinfo":
            class_type = InstallInformation
        elif hw_class == "netinterfaces":
            class_type = NetIfaceInformation
        else:
            log_error("UNKNOWN CLASS TYPE `%s'" % hw_class)
            # Same trick: try-except and raise the exception so that Traceback
            # can send the e-mail
            try:
                raise KeyError, "Unknwon class type `%s' for hardware '%s'" % (
                    hw_class, hardware)
            except:
                Traceback(mail=1)
                return

        # create the new device
        new_dev = class_type(hardware)
        
        if self.__hardware.has_key(class_type):
            _l = self.__hardware[class_type]
        else:
            _l = self.__hardware[class_type] = []
        _l.append(new_dev)
        self.__changed = 1
        return 0
class ServerWrapper(Packages, Hardware, History, SolarisPatches):
    def __init__(self):
        self.server = UserDictCase()
        Packages.__init__(self)
        History.__init__(self)
        Hardware.__init__(self)
        SolarisPatches.__init__(self)

    def __repr__(self):
        return "<%s instance>" % (self.__class__,)
    
    # update a value in self.server
    def set_value(self, name, value):
        if name is None or value is None:
            return -1
        self.server[name] = value
        return 0    

    ###
    ### PACKAGES
    ###
    
    # Wrappers for the similar functions from Packages class that supplementaly
    # require a valid sysid.
    def add_package(self, entry):
        if entry['name'].startswith("patch-solaris"):
            SolarisPatches.add_patch(self, self.server.get("id"), entry)
        return Packages.add_package(self, self.server.get("id"), entry)
    
    def delete_package(self, entry):
        return Packages.delete_package(self, self.server.get("id"), entry)
    
    def dispose_packages(self):
        SolarisPatches.dispose_patched_packages(self, self.server["id"])
        return Packages.dispose_packages(self, self.server["id"])

    # wrapper for the Packages.save_packages_byid() which requires the sysid
    def save_packages(self, schedule=1):
        SolarisPatches.save_patched_packages(self, self.server["id"])
        ret = self.save_packages_byid(self.server["id"], schedule=schedule)
        # this function is primarily called from outside
        # so we have to commit here
        rhnSQL.commit()
        return ret
        # wrapper for the Packages.reload_packages_byid() which requires the
        # sysid
    def reload_packages(self):
        ret = self.reload_packages_byid(self.server["id"])
        return ret

    ###
    ### HARDWARE
    ###
    
    # Wrappers for the similar functions from Hardware class
    def delete_hardware(self):
        return Hardware.delete_hardware(self, self.server.get("id"))
    # wrapper for the Hardware.save_hardware_byid() which requires the sysid
    def save_hardware(self):
        ret = self.save_hardware_byid(self.server["id"])
        # this function is primarily called from outside
        # so we have to commit here
        rhnSQL.commit()
        return ret   
    # wrapper for the Hardware.reload_hardware_byid() which requires the sysid
    def reload_hardware(self):
        ret = self.reload_hardware_byid(self.server["id"])
        return ret

    ###
    ### HISTORY
    ###
    def save_history(self):
        ret = self.save_history_byid(self.server["id"])
        # this function is primarily called from outside
        # so we have to commit here
        rhnSQL.commit()
        return ret