Example #1
0
def main():
    if len(sys.argv) != 2:
        print "FAIL: nodeid not provided!"
        return -1
    
    nodeid = sys.argv[1]
    hm = HenManager()
    if (hm.power(sys.argv[1], "poweroff") < 0):
        print "FAIL: hm.power(%s, \"poweroff\") failed (cause unknown)!"\
                % nodeid
        return -1
    time.sleep(2)
    (sts, output) = hm.powerSilent(sys.argv[1], "status")
    if (sts < 0):
        print "FAIL: hm.power(%s, \"status\") returned: %s" % (nodeid, output)
        return -1
    if (output == "on"):
        print "FAIL: hm.power(%s, \"status\") says the node is still on!" \
                    % nodeid
        return -1
    if (output == "off"):
        print "SUCCESS: hm.power(%s, \"poweroff\") succeeded." % nodeid
        return 0
    print "FAIL: hm.power(%s, \"status\") returned: %s" % (nodeid, output)
    return -1
Example #2
0
def main():
    if len(sys.argv) != 2:
        print "FAIL: nodeid not provided!"
        return -1

    nodeid = sys.argv[1]
    hm = HenManager()
    if (hm.power(sys.argv[1], "poweroff") < 0):
        print "FAIL: hm.power(%s, \"poweroff\") failed (cause unknown)!"\
                % nodeid
        return -1
    time.sleep(2)
    (sts, output) = hm.powerSilent(sys.argv[1], "status")
    if (sts < 0):
        print "FAIL: hm.power(%s, \"status\") returned: %s" % (nodeid, output)
        return -1
    if (output == "on"):
        print "FAIL: hm.power(%s, \"status\") says the node is still on!" \
                    % nodeid
        return -1
    if (output == "off"):
        print "SUCCESS: hm.power(%s, \"poweroff\") succeeded." % nodeid
        return 0
    print "FAIL: hm.power(%s, \"status\") returned: %s" % (nodeid, output)
    return -1
Example #3
0
manager = HenManager()
action = form["action"].value

# Perform power operation
if (action == "status" or action == "poweron" or action == "poweroff"
        or action == "restart"):
    if (not form.has_key("numbernodes")):
        print '</power>'
        sys.exit()

    numberNodes = form["numbernodes"].value

    if (action != "status"):
        for i in range(0, int(numberNodes)):
            nodeID = form["node" + str(i)].value
            manager.powerSilent(nodeID, action)

    for i in range(0, int(numberNodes)):
        nodeID = form["node" + str(i)].value
        (returnCode, status) = manager.powerSilent(nodeID, "status")
        if (returnCode != 0):
            status = "no powerswitch"
        print '\t<node id="' + str(nodeID) + '" status="' + str(
            status) + '" />'

# Get the ids of all nodes that have a power switch
elif (action == "getnodeids"):
    nodes = manager.getNodes("all")
    experiments = manager.getExperiments()

    for nodeTypeDictionary in nodes.values():
Example #4
0
import gc

manager = HenManager()
manager.initLogging()

switches = manager.getNodes("switch", "all")

switch = None
#switch_node = None
for sw in switches.values():
    if sw.getNodeID() == "switch5":
        #switch_node = sw
        switch = sw.getInstance()
while True:

    sn = switch.getSensorReadings()
    print sn,
    print resource.getrusage(resource.RUSAGE_SELF)[2]
    try:
        pnodeid = switch.getPowerNodeID()
        if (pnodeid == "None" or pnodeid == "none"):
            pass
        (st,msg) = manager.powerSilent(switch.getNodeID(), "status", \
                                                    pnodeid)
        print "power status[%S], message[%s]" % (st, msg)
    except:
        pass
    gc.collect()
    #print resource.getrusage(resource.RUSAGE_SELF)[3]
    time.sleep(1)
Example #5
0
###########################################################################################            

# Make sure that the necessary cgi parameters are given and retrieve them
form = cgi.FieldStorage()

if ((not form) or (not form.has_key("numbernodes")) or (not form.has_key("action"))):
    sys.exit()

print "Content-Type: text/xml"
print ""
print ""
print '<experiments>'

manager = HenManager()
action = form["action"].value
numberNodes = form["numbernodes"].value

if (action != "status"):
    for i in range(0, int(numberNodes)):
        nodeID = form["node" + str(i)].value
        manager.powerSilent(nodeID, action)

for i in range(0, int(numberNodes)):
    nodeID = form["node" + str(i)].value
    (returnCode, status) = manager.powerSilent(nodeID, "status")
    if (returnCode != 0):
        status = "no powerswitch"
    print '\t<node id="' + str(nodeID) + '" status="' + str(status) + '" />'
    
print '</experiments>'
Example #6
0
class ReservationDBManager:
    def __init__(self, filename, rightsFilename, notificationsFilename, dbsRoot, maxNumWeeks=2,debug=False):
        self.__daemonEMail = "*****@*****.**"        
        self.__filename = filename
        self.__rightsFilename = rightsFilename
        self.__notificationsFilename = notificationsFilename
        self.__notifications = {}        
        self.__dbsRoot = dbsRoot
        self.__maxNumWeeks = maxNumWeeks
        self.__reservations = {}
        self.__rights = {}
        self.__nextID = 0
        self.__xmldoc = None
        self.__rightsXmldoc = None
        self.__henManager = HenManager()
        self.__symlinksRoot = "/export/machines/"
        self.__smtpServerName = "smtp.cs.ucl.ac.uk"
        self.__parser = ReservationDBParser(filename, rightsFilename, notificationsFilename, self.__dbsRoot)
        self.__notifier = None        
        self.__debug = debug
        self.mytime = datetime.date.today()
        
        # Start the early notification thread
        self.__notifier = ReservationExpiryNotifier(self.__daemonEMail, \
                                                    self.__smtpServerName, \
                                                    self.__filename, \
                                                    self.__rightsFilename, \
                                                    self.__notificationsFilename, \
                                                    self.__dbsRoot,
                                                    self.__debug)
        if not self.__debug:
            self.__notifier.start()
        
    # used to test email sending
    def getNotifier(self):
        return self.__notifier

    def reloadHenDB(self):
        self.__henManager = HenManager()
        return 0
    
    def startDB(self):
        # First parse reservations database
        (result, self.__xmldoc) = self.__parser.openDB(self.__filename)
        if (result < 0):
            log.info("error while opening database!")
            return -1
        elif (result == 1):
            log.info("warning: no database file found (one will be created when a reservation is made)")
            self.__nextID = 1
        else:
            (result, self.__reservations) = self.__parser.parseDB(self.__xmldoc)
            # ignore -1, this means that there are no 'reservations' tags
            if (result < 0 and result != -1):
                log.info("error while parsing database!")
                return -1
            else:
                self.__nextID = self.__findHighestID() + 1

        self.cleanExpired()

        # Now parse reservation rights database
        (result, self.__rightsXmldoc) = self.__parser.openDB(self.__rightsFilename)
        if (result < 0 or result == 1):
            log.info("error while opening reservation rights database!")
            return -1

        (result, self.__rights) = self.__parser.parseRightsDB(self.__rightsXmldoc)
        if (result < 0):
            log.info("error while parsing rights database!")
            return -1

        return 0

    def release(self, username, reservationID):
        if (not self.__reservations.has_key(username)):
            return "unknown user"

        released = False
        reservationsBackup = self.__reservations
        userReservations = self.__reservations[username]
        for userReservation in userReservations:
            if (str(userReservation.getReservationID()) == str(reservationID)):
                userReservations.remove(userReservation)
                self.__removeNotifications(userReservation.getReservationID())
                released = True
                break

        if (not released):
            return "reservation id not found"
        
        if (self.__parser.writeDBToDisk(self.__reservations) < 0):
            self.__reservations = reservationsBackup
            return "error while writing to database, release failed"            

        self.__nextID = self.__findHighestID() + 1
        return "reservation released"
        
    def releaseDevices(self, username, devices):
        if (not self.__reservations.has_key(username)):
            return "unknown user"
        
        reservationsBackup = self.__reservations
        released = []
        userReservations = self.__reservations[username]
        for userReservation in userReservations:
            for device in userReservation.getDevices():
                if (device in devices):
                    userReservation.getDevices().remove(device)
                    released.append(device)

        # Remove any reservations with no devices in them
        for x in range(len(userReservations) - 1, -1, -1):
            if (len(userReservations[x].getDevices()) == 0):
                del userReservations[x]
        
        if (len(released) == 0):
            return "none of the devices were found in your reservations"
        
        if (self.__parser.writeDBToDisk(self.__reservations) < 0):
            self.__reservations = reservationsBackup
            return "error while writing to database, release failed"

        self.__nextID = self.__findHighestID() + 1
        string = "released: "
        for device in released:
            string += str(device) + ", "
        string = string[:len(string) - 2]
        return string
        
    def renew(self, username, reservationID, endDate):
        # Check for expired reservations first and release them
        self.cleanExpired()
        
        currentDate = self.__getCurrentDate() #datetime.date.today()
        if (endDate <= currentDate):
            return "renewal failed: supplied end date is in the past"

        maxDate = currentDate + timedelta(weeks=self.__getMaxWeeks(username, self.__getReservedDevicesByID(reservationID)))
        trimmedDate = False
        if (endDate > maxDate):
            endDate = maxDate
            trimmedDate = True

        if (self.__reservations.has_key(username)):
            for userReservation in self.__reservations[username]:
                if (int(userReservation.getReservationID()) == int(reservationID)):
                    oldDate = userReservation.getEndDate()
                    userReservation.setEndDate(endDate)
                    self.__removeNotifications(userReservation.getReservationID())
                    if (self.__parser.writeDBToDisk(self.__reservations) < 0):
                        userReservation.setEndDate(oldDate)
                        return "error while writing to database, renew failed"
                    message = "reservation renewed (new end date=" + str(self.__convertDateToString(endDate)) + ")"
                    if (trimmedDate):
                        message += "\nnote: the desired date was ignored because the max allocation period is " + \
                                   str(self.__maxNumWeeks) + " week(s)"
                    return message
                                    
        return "no reservation found for id=" + str(reservationID) + " and username="******"add"):
            for device in devices:
                if (self.__isDeviceInUse(device)):
                    return "reservation failed: " + str(device) + " already reserved"
            
        if (self.__reservations.has_key(username)):
            for userReservation in self.__reservations[username]:
                if (int(userReservation.getReservationID()) == int(reservationID)):
                    
                    oldDevices = userReservation.getEndDate()
                    oldEmail = userReservation.getEmail()
                    if (opType == "add"):
                        userReservation.appendDevices(devices)
                    elif (opType == "remove"):
                        userReservation.removeDevices(devices)
                        
                    if (email != None):
                        userReservation.setEmail(email)
                    if (self.__parser.writeDBToDisk(self.__reservations) < 0):
                        userReservation.setDevices(oldDevices)
                        if (email != None):
                            userReservation.setEmail(oldEmail)
                        return "error while writing to database, update failed"
                    message = "reservation updated"
                    return message
                                    
        return "no reservation found for id=" + str(reservationID) + " and username="******"reservation failed: supplied end date is in the past"
        maxDate = currentDate + timedelta(weeks=self.__getMaxWeeks(username, devices))
        trimmedDate = False
        if (endDate > maxDate):
            endDate = maxDate
            trimmedDate = True
        
        # First make sure that the devices are free
        for device in devices:
            if (self.__isDeviceInUse(device)):
                return "reservation failed: " + str(device) + " already reserved"

        # Add to in-memory db
        reservationID = self.__getNextID()
        if (not self.__reservations.has_key(username)):
            self.__reservations[username] = []
        entry = ReservationEntry(username, email, devices, endDate, reservationID)
        self.__reservations[username].append(entry)
        
        # Write-out to on-disk db
        if (self.__parser.writeDBToDisk(self.__reservations) < 0):
            self.__reservations[username].remove(entry)
            return "reservation failed: could not write database to disk"

        message = "reservation succeeded (id = " + str(reservationID) + ", " + \
                  "end date=" + str(self.__convertDateToString(endDate)) + ")"
        if (trimmedDate):
            message += "\nnote: the desired date was ignored because the max allocation period is " + \
                       str(self.__maxNumWeeks) + " week(s)"

        return message

    def getReservationsInfo(self, username):
        if username == "all":
            info = ""
            for name in self.__reservations:
                for reservation in self.__reservations[name]:
                    info += reservation.getInfoStr() +" "+str(name)+"\n"
            return info
        if (not self.__reservations.has_key(username)):
            return "no info"
        info = ""
        if len(self.__reservations[username]) == 0:
            return "no info"
        for reservation in self.__reservations[username]:
            info += reservation.getInfoStr() + "\n"
        info.rstrip('\n')
        return info
    
    def inUseBy(self, username):
        devices = []
        if (not self.__reservations.has_key(username)):
            return devices
        for reservation in self.__reservations[username]:
            for reservedDevice in reservation.getDevices():
                devices.append(reservedDevice)
        return devices
    
    def getFreeDevices(self):
        allDevices = self.__henManager.getNodes("computer").keys()
        allDevices.extend(self.__henManager.getNodes("virtualcomputer").keys())
        freeDevices = []
        reservedDevices = self.__getReservedDevices()
        for device in allDevices:
            if (device not in reservedDevices):
                freeDevices.append(device)
        return freeDevices

    def cleanExpired(self):
        currentDate = self.__getCurrentDate() #datetime.date.today()
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            for userReservation in userReservations:
                if (userReservation.getEndDate() < currentDate):
                    self.release(username, userReservation.getReservationID())
                    dirListing = self.__listDirectory(userReservation.getDevices())
                    self.__removeNotifications(userReservation.getReservationID())
                    self.__clearSymLinks(userReservation.getDevices())
                    self.__poweroff(userReservation.getDevices())
                    self.__sendEmailExpired(userReservation,dirListing)
                    log.info("cleaned expired reservation: " + str(userReservation))
        return 0
    
    def getOwners(self, devices):
        results = []
        for device in devices:
            owner = self.__getOwner(device)
            results.append((device, owner))
        return results

    def __parseNotifications(self):
        (result, xmldoc) = self.__parser.openDB(self.__notificationsFilename)
        if (result < 0):
            log.info("error while opening notifications database!")
            return -1        
        elif (result == 1):
            log.info("warning, no notifications database file found")
            return 1
        else:
            (result, self.__notifications) = self.__parser.parseNotificationsDB(xmldoc)
            # ignore -1, this means that there are no 'notifications' tags
            if (result < 0 and result != -1):
                log.info("error while parsing notifications database!")
                return -1
        return 0
    
    def __removeNotifications(self, reservationID):
        if (self.__parseNotifications() != 0):
            return
        try:
            del self.__notifications[int(reservationID)]
        except:
            log.info("warning: no notifications to delete for id=" + str(reservationID))
        self.__parser.writeNotificationsDBToDisk(self.__notifications)

    def __getCurrentDate(self):
        if not self.__debug:
            return datetime.date.today()
        else :
            return self.mytime
        
    def __getMaxWeeks(self, username, devices):
        if (not self.__rights.has_key(username) or len(devices) == 0):
            return self.__maxNumWeeks

        minRightWeeks = 99999
        foundDevs = []
        rights = self.__rights[username]        
        for device in devices:
            for right in rights:
                if (device in right.getDevices()):
                    foundDevs.append(device)
                    if (right.getMaxWeeks() < minRightWeeks):
                        minRightWeeks = right.getMaxWeeks()

        if (set(devices) == set(foundDevs)):
            return minRightWeeks
        
        return self.__maxNumWeeks

    def __listDirectory(self, devices):
        dirListing = ""
        for device in devices:
            dirListing += str(device)+" :\n"
            dirListing += commands.getoutput('find ' + self.__symlinksRoot + device + ' -print ')
            dirListing += "\n"
        return dirListing
        
    def __clearSymLinks(self, devices):
        # temp suspend clearing links , adam 12/08/2008
        return
        for device in devices:
            if not self.__debug:
                os.system("rm " + self.__symlinksRoot + device + "/*")
            else:
                print "would run : rm " + self.__symlinksRoot + device + "/*"

    def __poweroff(self, devices):
        # temp suspend poweroff , adam 12/08/2008
        return
        for device in devices:
            if not self.__debug:
                self.__henManager.powerSilent(device, "poweroff")
            else:
                print "would turn off "+str(device)
    
    def __sendEmailExpired(self, reservation,dirListing=None):
        subject = "Your reservation (id = " + str(reservation.getReservationID()) + ") has expired"
        body = "The reservation you had made has expired and has been removed from the system. " + \
               "If you still wish to use the devices you had reserved you will have to create a new " + \
               "reservation by logging on to hen.cs.ucl.ac.uk and running the command 'hm reservation'."
        if dirListing != None:
            body += "The directory listings for your machines were :\n"
            body += dirListing
        if not self.__debug:
            smtpClient = SMTPClient(self.__smtpServerName)
            smtpClient.sendEmail(reservation.getEmail(), self.__daemonEMail, subject, body)
            smtpClient.close()
        else:
            print "would send email."
            print "to :"+str(reservation.getEmail())
            print "subject :"+subject
            print "via :"+self.__smtpServerName
            print "body :"+body
        
    def __findHighestID(self):
        highestID = 0
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            for userReservation in userReservations:        
                if (int(userReservation.getReservationID()) > highestID):
                    highestID = int(userReservation.getReservationID())
        return highestID
    
    def __getNextID(self):
        theID = self.__nextID
        self.__nextID += 1
        return theID
        
    def __isDeviceInUse(self, device):
        return (self.__getOwner(device) != None)
    
    def __getOwner(self, device):
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            for userReservation in userReservations:
                for reservedDevice in userReservation.getDevices():
                    if (reservedDevice == device):
                        return username
        return None
    
    def __getReservedDevices(self):
        reservedDevices = []
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            for userReservation in userReservations:
                for device in userReservation.getDevices():
                    reservedDevices.append(device)
        return reservedDevices

    def __getReservedDevicesByID(self, reservationID):
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            for userReservation in userReservations:
                if (userReservation.getReservationID() == reservationID):
                    return userReservation.getDevices()
        return []
    
    def __printReservations(self):
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            email = userReservations[0].getEmail()
            log.info("\nuser: "******"(" + str(email) + ")" + \
                  "\n---------------------------------")
            for userReservation in userReservations:
                log.info(userReservation.getDateDevStr())

    def __printRights(self):
        for username in self.__rights.keys():
            userRights = self.__rights[username]
            email = userRights[0].getEmail()
            log.info("\nuser: "******"(" + str(email) + ")" + \
                  "\n---------------------------------")
            for userRight in userRights:
                log.info(userRight.getDebugStr())
                
    def __convertDateToString(self, date):
        return str(date.day) + "/" + str(date.month) + "/" + str(date.year)
Example #7
0
manager = HenManager()
manager.initLogging()

switches = manager.getNodes("switch","all")

switch = None
#switch_node = None
for sw in switches.values():
    if sw.getNodeID() == "switch5":
        #switch_node = sw
        switch = sw.getInstance()
while True:
    
    sn = switch.getSensorReadings()
    print sn,
    print resource.getrusage(resource.RUSAGE_SELF)[2]
    try:
        pnodeid = switch.getPowerNodeID()
        if (pnodeid == "None" or pnodeid == "none"):
            pass
        (st,msg) = manager.powerSilent(switch.getNodeID(), "status", \
                                                    pnodeid)
        print "power status[%S], message[%s]" % (st,msg)
    except:
        pass
    gc.collect()
    #print resource.getrusage(resource.RUSAGE_SELF)[3]
    time.sleep(1)    
    
    
Example #8
0
class ReservationDBManager:
    def __init__(self,
                 filename,
                 rightsFilename,
                 notificationsFilename,
                 dbsRoot,
                 maxNumWeeks=2,
                 debug=False):
        self.__daemonEMail = "*****@*****.**"
        self.__filename = filename
        self.__rightsFilename = rightsFilename
        self.__notificationsFilename = notificationsFilename
        self.__notifications = {}
        self.__dbsRoot = dbsRoot
        self.__maxNumWeeks = maxNumWeeks
        self.__reservations = {}
        self.__rights = {}
        self.__nextID = 0
        self.__xmldoc = None
        self.__rightsXmldoc = None
        self.__henManager = HenManager()
        self.__symlinksRoot = "/export/machines/"
        self.__smtpServerName = "smtp.cs.ucl.ac.uk"
        self.__parser = ReservationDBParser(filename, rightsFilename,
                                            notificationsFilename,
                                            self.__dbsRoot)
        self.__notifier = None
        self.__debug = debug
        self.mytime = datetime.date.today()

        # Start the early notification thread
        self.__notifier = ReservationExpiryNotifier(self.__daemonEMail, \
                                                    self.__smtpServerName, \
                                                    self.__filename, \
                                                    self.__rightsFilename, \
                                                    self.__notificationsFilename, \
                                                    self.__dbsRoot,
                                                    self.__debug)
        if not self.__debug:
            self.__notifier.start()

    # used to test email sending
    def getNotifier(self):
        return self.__notifier

    def reloadHenDB(self):
        self.__henManager = HenManager()
        return 0

    def startDB(self):
        # First parse reservations database
        (result, self.__xmldoc) = self.__parser.openDB(self.__filename)
        if (result < 0):
            log.info("error while opening database!")
            return -1
        elif (result == 1):
            log.info(
                "warning: no database file found (one will be created when a reservation is made)"
            )
            self.__nextID = 1
        else:
            (result,
             self.__reservations) = self.__parser.parseDB(self.__xmldoc)
            # ignore -1, this means that there are no 'reservations' tags
            if (result < 0 and result != -1):
                log.info("error while parsing database!")
                return -1
            else:
                self.__nextID = self.__findHighestID() + 1

        self.cleanExpired()

        # Now parse reservation rights database
        (result,
         self.__rightsXmldoc) = self.__parser.openDB(self.__rightsFilename)
        if (result < 0 or result == 1):
            log.info("error while opening reservation rights database!")
            return -1

        (result,
         self.__rights) = self.__parser.parseRightsDB(self.__rightsXmldoc)
        if (result < 0):
            log.info("error while parsing rights database!")
            return -1

        return 0

    def release(self, username, reservationID):
        if (not self.__reservations.has_key(username)):
            return "unknown user"

        released = False
        reservationsBackup = self.__reservations
        userReservations = self.__reservations[username]
        for userReservation in userReservations:
            if (str(userReservation.getReservationID()) == str(reservationID)):
                userReservations.remove(userReservation)
                self.__removeNotifications(userReservation.getReservationID())
                released = True
                break

        if (not released):
            return "reservation id not found"

        if (self.__parser.writeDBToDisk(self.__reservations) < 0):
            self.__reservations = reservationsBackup
            return "error while writing to database, release failed"

        self.__nextID = self.__findHighestID() + 1
        return "reservation released"

    def releaseDevices(self, username, devices):
        if (not self.__reservations.has_key(username)):
            return "unknown user"

        reservationsBackup = self.__reservations
        released = []
        userReservations = self.__reservations[username]
        for userReservation in userReservations:
            for device in userReservation.getDevices():
                if (device in devices):
                    userReservation.getDevices().remove(device)
                    released.append(device)

        # Remove any reservations with no devices in them
        for x in range(len(userReservations) - 1, -1, -1):
            if (len(userReservations[x].getDevices()) == 0):
                del userReservations[x]

        if (len(released) == 0):
            return "none of the devices were found in your reservations"

        if (self.__parser.writeDBToDisk(self.__reservations) < 0):
            self.__reservations = reservationsBackup
            return "error while writing to database, release failed"

        self.__nextID = self.__findHighestID() + 1
        string = "released: "
        for device in released:
            string += str(device) + ", "
        string = string[:len(string) - 2]
        return string

    def renew(self, username, reservationID, endDate):
        # Check for expired reservations first and release them
        self.cleanExpired()

        currentDate = self.__getCurrentDate()  #datetime.date.today()
        if (endDate <= currentDate):
            return "renewal failed: supplied end date is in the past"

        maxDate = currentDate + timedelta(weeks=self.__getMaxWeeks(
            username, self.__getReservedDevicesByID(reservationID)))
        trimmedDate = False
        if (endDate > maxDate):
            endDate = maxDate
            trimmedDate = True

        if (self.__reservations.has_key(username)):
            for userReservation in self.__reservations[username]:
                if (int(userReservation.getReservationID()) == int(
                        reservationID)):
                    oldDate = userReservation.getEndDate()
                    userReservation.setEndDate(endDate)
                    self.__removeNotifications(
                        userReservation.getReservationID())
                    if (self.__parser.writeDBToDisk(self.__reservations) < 0):
                        userReservation.setEndDate(oldDate)
                        return "error while writing to database, renew failed"
                    message = "reservation renewed (new end date=" + str(
                        self.__convertDateToString(endDate)) + ")"
                    if (trimmedDate):
                        message += "\nnote: the desired date was ignored because the max allocation period is " + \
                                   str(self.__maxNumWeeks) + " week(s)"
                    return message

        return "no reservation found for id=" + str(
            reservationID) + " and username="******"add"):
            for device in devices:
                if (self.__isDeviceInUse(device)):
                    return "reservation failed: " + str(
                        device) + " already reserved"

        if (self.__reservations.has_key(username)):
            for userReservation in self.__reservations[username]:
                if (int(userReservation.getReservationID()) == int(
                        reservationID)):

                    oldDevices = userReservation.getEndDate()
                    oldEmail = userReservation.getEmail()
                    if (opType == "add"):
                        userReservation.appendDevices(devices)
                    elif (opType == "remove"):
                        userReservation.removeDevices(devices)

                    if (email != None):
                        userReservation.setEmail(email)
                    if (self.__parser.writeDBToDisk(self.__reservations) < 0):
                        userReservation.setDevices(oldDevices)
                        if (email != None):
                            userReservation.setEmail(oldEmail)
                        return "error while writing to database, update failed"
                    message = "reservation updated"
                    return message

        return "no reservation found for id=" + str(
            reservationID) + " and username="******"reservation failed: supplied end date is in the past"
        maxDate = currentDate + timedelta(
            weeks=self.__getMaxWeeks(username, devices))
        trimmedDate = False
        if (endDate > maxDate):
            endDate = maxDate
            trimmedDate = True

        # First make sure that the devices are free
        for device in devices:
            if (self.__isDeviceInUse(device)):
                return "reservation failed: " + str(
                    device) + " already reserved"

        # Add to in-memory db
        reservationID = self.__getNextID()
        if (not self.__reservations.has_key(username)):
            self.__reservations[username] = []
        entry = ReservationEntry(username, email, devices, endDate,
                                 reservationID)
        self.__reservations[username].append(entry)

        # Write-out to on-disk db
        if (self.__parser.writeDBToDisk(self.__reservations) < 0):
            self.__reservations[username].remove(entry)
            return "reservation failed: could not write database to disk"

        message = "reservation succeeded (id = " + str(reservationID) + ", " + \
                  "end date=" + str(self.__convertDateToString(endDate)) + ")"
        if (trimmedDate):
            message += "\nnote: the desired date was ignored because the max allocation period is " + \
                       str(self.__maxNumWeeks) + " week(s)"

        return message

    def getReservationsInfo(self, username):
        if username == "all":
            info = ""
            for name in self.__reservations:
                for reservation in self.__reservations[name]:
                    info += reservation.getInfoStr() + " " + str(name) + "\n"
            return info
        if (not self.__reservations.has_key(username)):
            return "no info"
        info = ""
        if len(self.__reservations[username]) == 0:
            return "no info"
        for reservation in self.__reservations[username]:
            info += reservation.getInfoStr() + "\n"
        info.rstrip('\n')
        return info

    def inUseBy(self, username):
        devices = []
        if (not self.__reservations.has_key(username)):
            return devices
        for reservation in self.__reservations[username]:
            for reservedDevice in reservation.getDevices():
                devices.append(reservedDevice)
        return devices

    def getFreeDevices(self):
        allDevices = self.__henManager.getNodes("computer").keys()
        allDevices.extend(self.__henManager.getNodes("virtualcomputer").keys())
        freeDevices = []
        reservedDevices = self.__getReservedDevices()
        for device in allDevices:
            if (device not in reservedDevices):
                freeDevices.append(device)
        return freeDevices

    def cleanExpired(self):
        currentDate = self.__getCurrentDate()  #datetime.date.today()
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            for userReservation in userReservations:
                if (userReservation.getEndDate() < currentDate):
                    self.release(username, userReservation.getReservationID())
                    dirListing = self.__listDirectory(
                        userReservation.getDevices())
                    self.__removeNotifications(
                        userReservation.getReservationID())
                    self.__clearSymLinks(userReservation.getDevices())
                    self.__poweroff(userReservation.getDevices())
                    self.__sendEmailExpired(userReservation, dirListing)
                    log.info("cleaned expired reservation: " +
                             str(userReservation))
        return 0

    def getOwners(self, devices):
        results = []
        for device in devices:
            owner = self.__getOwner(device)
            results.append((device, owner))
        return results

    def __parseNotifications(self):
        (result, xmldoc) = self.__parser.openDB(self.__notificationsFilename)
        if (result < 0):
            log.info("error while opening notifications database!")
            return -1
        elif (result == 1):
            log.info("warning, no notifications database file found")
            return 1
        else:
            (result,
             self.__notifications) = self.__parser.parseNotificationsDB(xmldoc)
            # ignore -1, this means that there are no 'notifications' tags
            if (result < 0 and result != -1):
                log.info("error while parsing notifications database!")
                return -1
        return 0

    def __removeNotifications(self, reservationID):
        if (self.__parseNotifications() != 0):
            return
        try:
            del self.__notifications[int(reservationID)]
        except:
            log.info("warning: no notifications to delete for id=" +
                     str(reservationID))
        self.__parser.writeNotificationsDBToDisk(self.__notifications)

    def __getCurrentDate(self):
        if not self.__debug:
            return datetime.date.today()
        else:
            return self.mytime

    def __getMaxWeeks(self, username, devices):
        if (not self.__rights.has_key(username) or len(devices) == 0):
            return self.__maxNumWeeks

        minRightWeeks = 99999
        foundDevs = []
        rights = self.__rights[username]
        for device in devices:
            for right in rights:
                if (device in right.getDevices()):
                    foundDevs.append(device)
                    if (right.getMaxWeeks() < minRightWeeks):
                        minRightWeeks = right.getMaxWeeks()

        if (set(devices) == set(foundDevs)):
            return minRightWeeks

        return self.__maxNumWeeks

    def __listDirectory(self, devices):
        dirListing = ""
        for device in devices:
            dirListing += str(device) + " :\n"
            dirListing += commands.getoutput('find ' + self.__symlinksRoot +
                                             device + ' -print ')
            dirListing += "\n"
        return dirListing

    def __clearSymLinks(self, devices):
        # temp suspend clearing links , adam 12/08/2008
        return
        for device in devices:
            if not self.__debug:
                os.system("rm " + self.__symlinksRoot + device + "/*")
            else:
                print "would run : rm " + self.__symlinksRoot + device + "/*"

    def __poweroff(self, devices):
        # temp suspend poweroff , adam 12/08/2008
        return
        for device in devices:
            if not self.__debug:
                self.__henManager.powerSilent(device, "poweroff")
            else:
                print "would turn off " + str(device)

    def __sendEmailExpired(self, reservation, dirListing=None):
        subject = "Your reservation (id = " + str(
            reservation.getReservationID()) + ") has expired"
        body = "The reservation you had made has expired and has been removed from the system. " + \
               "If you still wish to use the devices you had reserved you will have to create a new " + \
               "reservation by logging on to hen.cs.ucl.ac.uk and running the command 'hm reservation'."
        if dirListing != None:
            body += "The directory listings for your machines were :\n"
            body += dirListing
        if not self.__debug:
            smtpClient = SMTPClient(self.__smtpServerName)
            smtpClient.sendEmail(reservation.getEmail(), self.__daemonEMail,
                                 subject, body)
            smtpClient.close()
        else:
            print "would send email."
            print "to :" + str(reservation.getEmail())
            print "subject :" + subject
            print "via :" + self.__smtpServerName
            print "body :" + body

    def __findHighestID(self):
        highestID = 0
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            for userReservation in userReservations:
                if (int(userReservation.getReservationID()) > highestID):
                    highestID = int(userReservation.getReservationID())
        return highestID

    def __getNextID(self):
        theID = self.__nextID
        self.__nextID += 1
        return theID

    def __isDeviceInUse(self, device):
        return (self.__getOwner(device) != None)

    def __getOwner(self, device):
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            for userReservation in userReservations:
                for reservedDevice in userReservation.getDevices():
                    if (reservedDevice == device):
                        return username
        return None

    def __getReservedDevices(self):
        reservedDevices = []
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            for userReservation in userReservations:
                for device in userReservation.getDevices():
                    reservedDevices.append(device)
        return reservedDevices

    def __getReservedDevicesByID(self, reservationID):
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            for userReservation in userReservations:
                if (userReservation.getReservationID() == reservationID):
                    return userReservation.getDevices()
        return []

    def __printReservations(self):
        for username in self.__reservations.keys():
            userReservations = self.__reservations[username]
            email = userReservations[0].getEmail()
            log.info("\nuser: "******"(" + str(email) + ")" + \
                  "\n---------------------------------")
            for userReservation in userReservations:
                log.info(userReservation.getDateDevStr())

    def __printRights(self):
        for username in self.__rights.keys():
            userRights = self.__rights[username]
            email = userRights[0].getEmail()
            log.info("\nuser: "******"(" + str(email) + ")" + \
                  "\n---------------------------------")
            for userRight in userRights:
                log.info(userRight.getDebugStr())

    def __convertDateToString(self, date):
        return str(date.day) + "/" + str(date.month) + "/" + str(date.year)