[haizea-commit] r588 - in branches/TP2.0/src/haizea: cli common core core/frontends core/scheduler core/scheduler/preparation_schedulers
haizea-commit at mailman.cs.uchicago.edu
haizea-commit at mailman.cs.uchicago.edu
Wed Jun 17 11:38:09 CDT 2009
Author: borja
Date: 2009-06-17 11:38:07 -0500 (Wed, 17 Jun 2009)
New Revision: 588
Added:
branches/TP2.0/src/haizea/core/haizea.py
Removed:
branches/TP2.0/src/haizea/core/rm.py
Modified:
branches/TP2.0/src/haizea/cli/commands.py
branches/TP2.0/src/haizea/common/utils.py
branches/TP2.0/src/haizea/core/accounting.py
branches/TP2.0/src/haizea/core/frontends/__init__.py
branches/TP2.0/src/haizea/core/frontends/opennebula.py
branches/TP2.0/src/haizea/core/frontends/rpc.py
branches/TP2.0/src/haizea/core/frontends/tracefile.py
branches/TP2.0/src/haizea/core/log.py
branches/TP2.0/src/haizea/core/rpcserver.py
branches/TP2.0/src/haizea/core/scheduler/lease_scheduler.py
branches/TP2.0/src/haizea/core/scheduler/preparation_schedulers/imagetransfer.py
branches/TP2.0/src/haizea/core/scheduler/vm_scheduler.py
Log:
Change name of "rm" module to "haizea"
Modified: branches/TP2.0/src/haizea/cli/commands.py
===================================================================
--- branches/TP2.0/src/haizea/cli/commands.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/cli/commands.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -16,7 +16,7 @@
# limitations under the License. #
# -------------------------------------------------------------------------- #
-from haizea.core.rm import ResourceManager
+from haizea.core.haizea import Haizea
from haizea.common.utils import generate_config_name, unpickle
from haizea.core.configfile import HaizeaConfig, HaizeaMultiConfig
from haizea.common.config import ConfigException
@@ -108,9 +108,9 @@
daemon = not self.opt.foreground
- rm = ResourceManager(config, daemon, pidfile)
+ haizea = Haizea(config, daemon, pidfile)
- rm.start()
+ haizea.start()
elif self.opt.stop: # Stop Haizea
# Based on code in: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012
try:
Modified: branches/TP2.0/src/haizea/common/utils.py
===================================================================
--- branches/TP2.0/src/haizea/common/utils.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/common/utils.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -116,20 +116,20 @@
def get_config():
- from haizea.core.rm import ResourceManager
- return ResourceManager.get_singleton().config
+ from haizea.core.haizea import Haizea
+ return Haizea.get_singleton().config
def get_accounting():
- from haizea.core.rm import ResourceManager
- return ResourceManager.get_singleton().accounting
+ from haizea.core.haizea import Haizea
+ return Haizea.get_singleton().accounting
def get_clock():
- from haizea.core.rm import ResourceManager
- return ResourceManager.get_singleton().clock
+ from haizea.core.haizea import Haizea
+ return Haizea.get_singleton().clock
def get_policy():
- from haizea.core.rm import ResourceManager
- return ResourceManager.get_singleton().policy
+ from haizea.core.haizea import Haizea
+ return Haizea.get_singleton().policy
class InvalidStateMachineTransition(Exception):
pass
Modified: branches/TP2.0/src/haizea/core/accounting.py
===================================================================
--- branches/TP2.0/src/haizea/core/accounting.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/core/accounting.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -58,9 +58,9 @@
return max([l.end for l in self.leases.values() if isinstance(l, BestEffortLease)])
class AccountingDataCollection(object):
- def __init__(self, rm, datafile):
+ def __init__(self, haizea, datafile):
self.data = AccountingData()
- self.rm = rm
+ self.haizea = haizea
self.datafile = datafile
attrs = get_config().get_attrs()
@@ -172,7 +172,7 @@
raise e
# Add lease data
- leases = self.rm.scheduler.completed_leases.entries
+ leases = self.haizea.scheduler.completed_leases.entries
# Remove some data that won't be necessary in the reporting tools
for l in leases.values():
l.clear_rrs()
Modified: branches/TP2.0/src/haizea/core/frontends/__init__.py
===================================================================
--- branches/TP2.0/src/haizea/core/frontends/__init__.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/core/frontends/__init__.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -19,8 +19,8 @@
from haizea.common.utils import abstract
class RequestFrontend(object):
- def __init__(self, rm):
- self.rm = rm
+ def __init__(self, haizea):
+ self.haizea = haizea
def get_accumulated_requests(self): abstract()
Modified: branches/TP2.0/src/haizea/core/frontends/opennebula.py
===================================================================
--- branches/TP2.0/src/haizea/core/frontends/opennebula.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/core/frontends/opennebula.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -129,8 +129,8 @@
class OpenNebulaFrontend(RequestFrontend):
- def __init__(self, rm):
- self.rm = rm
+ def __init__(self, haizea):
+ self.haizea = haizea
self.processed = []
self.logger = logging.getLogger("ONEREQ")
config = get_config()
Modified: branches/TP2.0/src/haizea/core/frontends/rpc.py
===================================================================
--- branches/TP2.0/src/haizea/core/frontends/rpc.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/core/frontends/rpc.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -28,12 +28,12 @@
HAIZEA_START_BESTEFFORT = "best_effort"
HAIZEA_DURATION_UNLIMITED = "unlimited"
- def __init__(self, rm):
- self.rm = rm
+ def __init__(self, haizea):
+ self.haizea = haizea
self.logger = logging.getLogger("RPCREQ")
self.accumulated = []
config = get_config()
- self.rm.rpc_server.register_rpc(self.create_lease)
+ self.haizea.rpc_server.register_rpc(self.create_lease)
def get_accumulated_requests(self):
acc = self.accumulated
Modified: branches/TP2.0/src/haizea/core/frontends/tracefile.py
===================================================================
--- branches/TP2.0/src/haizea/core/frontends/tracefile.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/core/frontends/tracefile.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -25,10 +25,10 @@
import logging
class TracefileFrontend(RequestFrontend):
- def __init__(self, rm, starttime):
- RequestFrontend.__init__(self, rm)
+ def __init__(self, haizea, starttime):
+ RequestFrontend.__init__(self, haizea)
self.logger = logging.getLogger("TFILE")
- config = rm.config
+ config = haizea.config
tracefile = config.get("tracefile")
injectfile = config.get("injectionfile")
Copied: branches/TP2.0/src/haizea/core/haizea.py (from rev 587, branches/TP2.0/src/haizea/core/rm.py)
===================================================================
--- branches/TP2.0/src/haizea/core/haizea.py (rev 0)
+++ branches/TP2.0/src/haizea/core/haizea.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -0,0 +1,846 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2006-2008, University of Chicago #
+# Copyright 2008, Distributed Systems Architecture Group, Universidad #
+# Complutense de Madrid (dsa-research.org) #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); you may #
+# not use this file except in compliance with the License. You may obtain #
+# a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+# -------------------------------------------------------------------------- #
+
+"""The haizea module is the root of Haizea. If you want to
+see where the ball starts rolling, look at the following two functions:
+
+* haizea.Haizea.__init__()
+* haizea.Haizea.start()
+
+This module provides the following classes:
+
+* Haizea: The resource manager itself. Pretty much everything else
+ is contained in this class.
+* Clock: A base class for the resource manager's clock.
+* SimulatedClock: A clock for simulations.
+* RealClock: A clock that advances in realtime.
+"""
+
+import haizea.core.accounting as accounting
+import haizea.common.constants as constants
+from haizea.core.scheduler.preparation_schedulers.unmanaged import UnmanagedPreparationScheduler
+from haizea.core.scheduler.preparation_schedulers.imagetransfer import ImageTransferPreparationScheduler
+from haizea.core.enact.opennebula import OpenNebulaResourcePoolInfo, OpenNebulaVMEnactment, OpenNebulaDummyDeploymentEnactment
+from haizea.core.enact.simulated import SimulatedResourcePoolInfo, SimulatedVMEnactment, SimulatedDeploymentEnactment
+from haizea.core.frontends.tracefile import TracefileFrontend
+from haizea.core.frontends.opennebula import OpenNebulaFrontend
+from haizea.core.frontends.rpc import RPCFrontend
+from haizea.core.leases import BestEffortLease
+from haizea.core.scheduler import UnrecoverableError
+from haizea.core.scheduler.lease_scheduler import LeaseScheduler
+from haizea.core.scheduler.vm_scheduler import VMScheduler
+from haizea.core.scheduler.slottable import SlotTable
+from haizea.core.scheduler.policy import Policy
+from haizea.core.scheduler.resourcepool import ResourcePool, ResourcePoolWithReusableImages
+from haizea.core.rpcserver import RPCServer
+from haizea.common.utils import abstract, round_datetime, Singleton
+
+import operator
+import logging
+import signal
+import sys, os
+import traceback
+from time import sleep
+from math import ceil
+from mx.DateTime import now, TimeDelta
+
+DAEMON_STDOUT = DAEMON_STDIN = "/dev/null"
+DAEMON_STDERR = "/var/tmp/haizea.err"
+DEFAULT_LOGFILE = "/var/tmp/haizea.log"
+
+class Haizea(Singleton):
+ """Haizea
+
+ This class is the root of Haizea. Pretty much everything else (scheduler,
+ enactment modules, etc.) is contained in this class. The Haizea
+ class is meant to be a singleton.
+
+ """
+
+ def __init__(self, config, daemon=False, pidfile=None):
+ """Initializes the resource manager.
+
+ Argument:
+ config -- a populated instance of haizea.common.config.RMConfig
+ daemon -- True if Haizea must run as a daemon, False if it must
+ run in the foreground
+ pidfile -- When running as a daemon, file to save pid to
+ """
+ self.config = config
+
+ # Create the haizea components
+
+ mode = config.get("mode")
+
+ self.daemon = daemon
+ self.pidfile = pidfile
+
+ if mode == "simulated":
+ self.init_simulated_mode()
+ elif mode == "opennebula":
+ self.init_opennebula_mode()
+
+ # Statistics collection
+ self.accounting = accounting.AccountingDataCollection(self, self.config.get("datafile"))
+
+ self.logger = logging.getLogger("RM")
+
+ def init_simulated_mode(self):
+ """Initializes the resource manager in simulated mode
+
+ """
+
+ # Simulated-time simulations always run in the foreground
+ clock = self.config.get("clock")
+ if clock == constants.CLOCK_SIMULATED:
+ self.daemon = False
+
+ self.init_logging()
+
+ if clock == constants.CLOCK_SIMULATED:
+ starttime = self.config.get("starttime")
+ self.clock = SimulatedClock(self, starttime)
+ self.rpc_server = None
+ elif clock == constants.CLOCK_REAL:
+ wakeup_interval = self.config.get("wakeup-interval")
+ non_sched = self.config.get("non-schedulable-interval")
+ self.clock = RealClock(self, wakeup_interval, non_sched)
+ self.rpc_server = RPCServer(self)
+
+ # Enactment modules
+ info_enact = SimulatedResourcePoolInfo()
+ vm_enact = SimulatedVMEnactment()
+ deploy_enact = SimulatedDeploymentEnactment()
+
+ # Resource pool
+ preparation_type = self.config.get("lease-preparation")
+ if preparation_type == constants.PREPARATION_TRANSFER:
+ if self.config.get("diskimage-reuse") == constants.REUSE_IMAGECACHES:
+ resourcepool = ResourcePoolWithReusableImages(info_enact, vm_enact, deploy_enact)
+ else:
+ resourcepool = ResourcePool(info_enact, vm_enact, deploy_enact)
+ else:
+ resourcepool = ResourcePool(info_enact, vm_enact, deploy_enact)
+
+ # Slot table
+ slottable = SlotTable()
+ for n in resourcepool.get_nodes() + resourcepool.get_aux_nodes():
+ slottable.add_node(n)
+
+ # Preparation scheduler
+ if preparation_type == constants.PREPARATION_UNMANAGED:
+ preparation_scheduler = UnmanagedPreparationScheduler(slottable, resourcepool, deploy_enact)
+ elif preparation_type == constants.PREPARATION_TRANSFER:
+ preparation_scheduler = ImageTransferPreparationScheduler(slottable, resourcepool, deploy_enact)
+
+ # VM Scheduler
+ vm_scheduler = VMScheduler(slottable, resourcepool)
+
+ # Lease Scheduler
+ self.scheduler = LeaseScheduler(vm_scheduler, preparation_scheduler, slottable)
+
+ # Policy engine
+ self.policy = Policy()
+
+ # Lease request frontends
+ if clock == constants.CLOCK_SIMULATED:
+ # In pure simulation, we can only use the tracefile frontend
+ self.frontends = [TracefileFrontend(self, self.clock.get_start_time())]
+ elif clock == constants.CLOCK_REAL:
+ # In simulation with a real clock, only the RPC frontend can be used
+ self.frontends = [RPCFrontend(self)]
+
+ def init_opennebula_mode(self):
+ """Initializes the resource manager in OpenNebula mode
+
+ """
+ self.init_logging()
+
+ # The clock
+ wakeup_interval = self.config.get("wakeup-interval")
+ non_sched = self.config.get("non-schedulable-interval")
+ dry_run = self.config.get("dry-run")
+ fastforward = dry_run
+ self.clock = RealClock(self, wakeup_interval, non_sched, fastforward)
+
+ # RPC server
+ if dry_run:
+ # No need for an RPC server when doing a dry run
+ self.rpc_server = None
+ else:
+ self.rpc_server = RPCServer(self)
+
+ # Enactment modules
+ info_enact = OpenNebulaResourcePoolInfo()
+ vm_enact = OpenNebulaVMEnactment()
+ # No deployment in OpenNebula. Using dummy one for now.
+ deploy_enact = OpenNebulaDummyDeploymentEnactment()
+
+ # Resource pool
+ resourcepool = ResourcePool(info_enact, vm_enact, deploy_enact)
+
+ # Slot table
+ slottable = SlotTable()
+ for n in resourcepool.get_nodes() + resourcepool.get_aux_nodes():
+ slottable.add_node(n)
+
+
+ # Deployment module
+ preparation_scheduler = UnmanagedPreparationScheduler(slottable, resourcepool, deploy_enact)
+
+ # VM Scheduler
+ vm_scheduler = VMScheduler(slottable, resourcepool)
+
+ # Lease Scheduler
+ self.scheduler = LeaseScheduler(vm_scheduler, preparation_scheduler, slottable)
+
+ # Lease request frontends
+ self.frontends = [OpenNebulaFrontend(self)]
+
+
+ def init_logging(self):
+ """Initializes logging
+
+ """
+
+ from haizea.core.log import HaizeaLogger
+ logger = logging.getLogger("")
+ if self.daemon:
+ handler = logging.FileHandler(self.config.get("logfile"))
+ else:
+ handler = logging.StreamHandler()
+ formatter = logging.Formatter('[%(haizeatime)s] %(name)-7s %(message)s')
+ handler.setFormatter(formatter)
+ logger.addHandler(handler)
+ level = logging.getLevelName(self.config.get("loglevel"))
+ logger.setLevel(level)
+ logging.setLoggerClass(HaizeaLogger)
+
+
+ def daemonize(self):
+ """Daemonizes the Haizea process.
+
+ Based on code in: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012
+
+ """
+ # First fork
+ try:
+ pid = os.fork()
+ if pid > 0:
+ # Exit first parent
+ sys.exit(0)
+ except OSError, e:
+ sys.stderr.write("Failed to daemonize Haizea: (%d) %s\n" % (e.errno, e.strerror))
+ sys.exit(1)
+
+ # Decouple from parent environment.
+ os.chdir(".")
+ os.umask(0)
+ os.setsid()
+
+ # Second fork
+ try:
+ pid = os.fork()
+ if pid > 0:
+ # Exit second parent.
+ sys.exit(0)
+ except OSError, e:
+ sys.stderr.write("Failed to daemonize Haizea: (%d) %s\n" % (e.errno, e.strerror))
+ sys.exit(2)
+
+ # Open file descriptors and print start message
+ si = file(DAEMON_STDIN, 'r')
+ so = file(DAEMON_STDOUT, 'a+')
+ se = file(DAEMON_STDERR, 'a+', 0)
+ pid = os.getpid()
+ sys.stderr.write("\nStarted Haizea daemon with pid %i\n\n" % pid)
+ sys.stderr.flush()
+ file(self.pidfile,'w+').write("%i\n" % pid)
+
+ # Redirect standard file descriptors.
+ os.close(sys.stdin.fileno())
+ os.close(sys.stdout.fileno())
+ os.close(sys.stderr.fileno())
+ os.dup2(si.fileno(), sys.stdin.fileno())
+ os.dup2(so.fileno(), sys.stdout.fileno())
+ os.dup2(se.fileno(), sys.stderr.fileno())
+
+ def start(self):
+ """Starts the resource manager"""
+ self.logger.info("Starting resource manager")
+
+ # Create counters to keep track of interesting data.
+ self.accounting.create_counter(constants.COUNTER_ARACCEPTED, constants.AVERAGE_NONE)
+ self.accounting.create_counter(constants.COUNTER_ARREJECTED, constants.AVERAGE_NONE)
+ self.accounting.create_counter(constants.COUNTER_IMACCEPTED, constants.AVERAGE_NONE)
+ self.accounting.create_counter(constants.COUNTER_IMREJECTED, constants.AVERAGE_NONE)
+ self.accounting.create_counter(constants.COUNTER_BESTEFFORTCOMPLETED, constants.AVERAGE_NONE)
+ self.accounting.create_counter(constants.COUNTER_QUEUESIZE, constants.AVERAGE_TIMEWEIGHTED)
+ self.accounting.create_counter(constants.COUNTER_DISKUSAGE, constants.AVERAGE_NONE)
+ self.accounting.create_counter(constants.COUNTER_UTILIZATION, constants.AVERAGE_NONE)
+
+ if self.daemon:
+ self.daemonize()
+ if self.rpc_server:
+ self.rpc_server.start()
+
+ # Start the clock
+ try:
+ self.clock.run()
+ except UnrecoverableError, exc:
+ self.__unrecoverable_error(exc)
+ except Exception, exc:
+ self.__unexpected_exception(exc)
+
+ def stop(self):
+ """Stops the resource manager by stopping the clock"""
+ self.clock.stop()
+
+ def graceful_stop(self):
+ """Stops the resource manager gracefully and exits"""
+
+ self.logger.status("Stopping resource manager gracefully...")
+
+ # Stop collecting data (this finalizes counters)
+ self.accounting.stop()
+
+ # TODO: When gracefully stopping mid-scheduling, we need to figure out what to
+ # do with leases that are still running.
+
+ self.print_status()
+
+ # In debug mode, dump the lease descriptors.
+ for lease in self.scheduler.completed_leases.entries.values():
+ lease.print_contents()
+
+ # Write all collected data to disk
+ self.accounting.save_to_disk()
+
+ # Stop RPC server
+ if self.rpc_server != None:
+ self.rpc_server.stop()
+
+ def process_requests(self, nexttime):
+ """Process any new requests in the request frontend
+
+ Checks the request frontend to see if there are any new requests that
+ have to be processed. AR leases are sent directly to the schedule.
+ Best-effort leases are queued.
+
+ Arguments:
+ nexttime -- The next time at which the scheduler can allocate resources.
+ This is meant to be provided by the clock simply as a sanity
+ measure when running in real time (to avoid scheduling something
+ "now" to actually have "now" be in the past once the scheduling
+ function returns. i.e., nexttime has nothing to do with whether
+ there are resources available at that time or not.
+
+ """
+
+ # Get requests from frontend
+ requests = []
+ for frontend in self.frontends:
+ requests += frontend.get_accumulated_requests()
+ requests.sort(key=operator.attrgetter("submit_time"))
+
+ # Request leases and run the scheduling function.
+ try:
+ self.logger.vdebug("Requesting leases")
+ for req in requests:
+ self.scheduler.request_lease(req)
+
+ self.logger.vdebug("Running scheduling function")
+ self.scheduler.schedule(nexttime)
+ except UnrecoverableError, exc:
+ self.__unrecoverable_error(exc)
+ except Exception, exc:
+ self.__unexpected_exception(exc)
+
+
+ def process_reservations(self, time):
+ """Process reservations starting/stopping at specified time"""
+
+ # The scheduler takes care of this.
+ try:
+ self.scheduler.process_reservations(time)
+ except UnrecoverableError, exc:
+ self.__unrecoverable_error(exc)
+ except Exception, exc:
+ self.__unexpected_exception(exc)
+
+ def notify_event(self, lease_id, event):
+ """Notifies an asynchronous event to Haizea.
+
+ Arguments:
+ lease_id -- ID of lease that is affected by event
+ event -- Event (currently, only the constants.EVENT_END_VM event is supported)
+ """
+ try:
+ lease = self.scheduler.get_lease_by_id(lease_id)
+ self.scheduler.notify_event(lease, event)
+ except UnrecoverableError, exc:
+ self.__unrecoverable_error(exc)
+ except Exception, exc:
+ self.__unexpected_exception(exc)
+
+ def cancel_lease(self, lease_id):
+ """Cancels a lease.
+
+ Arguments:
+ lease_id -- ID of lease to cancel
+ """
+ try:
+ lease = self.scheduler.get_lease_by_id(lease_id)
+ self.scheduler.cancel_lease(lease)
+ except UnrecoverableError, exc:
+ self.__unrecoverable_error(exc)
+ except Exception, exc:
+ self.__unexpected_exception(exc)
+
+ def get_next_changepoint(self):
+ """Return next changepoint in the slot table"""
+ return self.scheduler.slottable.peekNextChangePoint(self.clock.get_time())
+
+ def exists_leases_in_rm(self):
+ """Return True if there are any leases still "in the system" """
+ return self.scheduler.exists_scheduled_leases() or not self.scheduler.is_queue_empty()
+
+ def print_status(self):
+ """Prints status summary."""
+
+ leases = self.scheduler.leases.get_leases()
+ completed_leases = self.scheduler.completed_leases.get_leases()
+ self.logger.status("--- Haizea status summary ---")
+ self.logger.status("Number of leases (not including completed): %i" % len(leases))
+ self.logger.status("Completed leases: %i" % len(completed_leases))
+ self.logger.status("Completed best-effort leases: %i" % self.accounting.data.counters[constants.COUNTER_BESTEFFORTCOMPLETED])
+ self.logger.status("Queue size: %i" % self.accounting.data.counters[constants.COUNTER_QUEUESIZE])
+ self.logger.status("Accepted AR leases: %i" % self.accounting.data.counters[constants.COUNTER_ARACCEPTED])
+ self.logger.status("Rejected AR leases: %i" % self.accounting.data.counters[constants.COUNTER_ARREJECTED])
+ self.logger.status("Accepted IM leases: %i" % self.accounting.data.counters[constants.COUNTER_IMACCEPTED])
+ self.logger.status("Rejected IM leases: %i" % self.accounting.data.counters[constants.COUNTER_IMREJECTED])
+ self.logger.status("---- End summary ----")
+
+ def __unrecoverable_error(self, exc):
+ """Handles an unrecoverable error.
+
+ This method prints information on the unrecoverable error and makes Haizea panic.
+ """
+ self.logger.error("An unrecoverable error has happened.")
+ self.logger.error("Original exception:")
+ self.__print_exception(exc.exc, exc.get_traceback())
+ self.logger.error("Unrecoverable error traceback:")
+ self.__print_exception(exc, sys.exc_traceback)
+ self.__panic()
+
+ def __unexpected_exception(self, exc):
+ """Handles an unrecoverable error.
+
+ This method prints information on the unrecoverable error and makes Haizea panic.
+ """
+ self.logger.error("An unexpected exception has happened.")
+ self.__print_exception(exc, sys.exc_traceback)
+ self.__panic()
+
+ def __print_exception(self, exc, exc_traceback):
+ """Prints an exception's traceback to the log."""
+ tb = traceback.format_tb(exc_traceback)
+ for line in tb:
+ self.logger.error(line)
+ self.logger.error("Message: %s" % exc)
+
+
+ def __panic(self):
+ """Makes Haizea crash and burn in a panicked frenzy"""
+
+ self.logger.status("Panicking...")
+
+ # Stop RPC server
+ if self.rpc_server != None:
+ self.rpc_server.stop()
+
+ # Dump state
+ self.print_status()
+ self.logger.error("Next change point (in slot table): %s" % self.get_next_changepoint())
+
+ # Print lease descriptors
+ leases = self.scheduler.leases.get_leases()
+ if len(leases)>0:
+ self.logger.vdebug("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv")
+ for lease in leases:
+ lease.print_contents()
+ self.logger.vdebug("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^")
+
+ # Exit
+ treatment = self.config.get("lease-failure-handling")
+ if treatment == constants.ONFAILURE_EXIT_RAISE:
+ raise
+ else:
+ exit(1)
+
+
+class Clock(object):
+ """Base class for the resource manager's clock.
+
+ The clock is in charge of periodically waking the resource manager so it
+ will process new requests and handle existing reservations. This is a
+ base class defining abstract methods.
+
+ """
+ def __init__(self, haizea):
+ self.haizea = haizea
+ self.done = False
+
+ def get_time(self):
+ """Return the current time"""
+ return abstract()
+
+ def get_start_time(self):
+ """Return the time at which the clock started ticking"""
+ return abstract()
+
+ def get_next_schedulable_time(self):
+ """Return the next time at which resources could be scheduled.
+
+ The "next schedulable time" server sanity measure when running
+ in real time (to avoid scheduling something "now" to actually
+ have "now" be in the past once the scheduling function returns.
+ i.e., the "next schedulable time" has nothing to do with whether
+ there are resources available at that time or not.
+ """
+ return abstract()
+
+ def run(self):
+ """Start and run the clock. This function is, in effect,
+ the main loop of the resource manager."""
+ return abstract()
+
+ def stop(self):
+ """Stop the clock.
+
+ Stopping the clock makes Haizea exit.
+ """
+ self.done = True
+
+
+class SimulatedClock(Clock):
+ """Simulates the passage of time... really fast.
+
+ The simulated clock steps through time to produce an ideal schedule.
+ See the run() function for a description of how time is incremented
+ exactly in the simulated clock.
+
+ """
+
+ def __init__(self, haizea, starttime):
+ """Initialize the simulated clock, starting at the provided starttime"""
+ Clock.__init__(self, haizea)
+ self.starttime = starttime
+ self.time = starttime
+ self.logger = logging.getLogger("CLOCK")
+ self.statusinterval = self.haizea.config.get("status-message-interval")
+
+ def get_time(self):
+ """See docstring in base Clock class."""
+ return self.time
+
+ def get_start_time(self):
+ """See docstring in base Clock class."""
+ return self.starttime
+
+ def get_next_schedulable_time(self):
+ """See docstring in base Clock class."""
+ return self.time
+
+ def run(self):
+ """Runs the simulated clock through time.
+
+ The clock starts at the provided start time. At each point in time,
+ it wakes up the resource manager and then skips to the next time
+ where "something" is happening (see __get_next_time for a more
+ rigorous description of this).
+
+ The clock stops when there is nothing left to do (no pending or
+ queue requests, and no future reservations)
+
+ The simulated clock can only work in conjunction with the
+ tracefile request frontend.
+ """
+ self.logger.status("Starting simulated clock")
+ self.haizea.accounting.start(self.get_start_time())
+ prevstatustime = self.time
+
+ # Main loop
+ while not self.done:
+ # Check to see if there are any leases which are ending prematurely.
+ # Note that this is unique to simulation.
+ prematureends = self.haizea.scheduler.slottable.getPrematurelyEndingRes(self.time)
+
+ # Notify the resource manager about the premature ends
+ for rr in prematureends:
+ self.haizea.notify_event(rr.lease.id, constants.EVENT_END_VM)
+
+ # Process reservations starting/stopping at the current time and
+ # check if there are any new requests.
+ self.haizea.process_reservations(self.time)
+ self.haizea.process_requests(self.time)
+
+ # Since processing requests may have resulted in new reservations
+ # starting now, we process reservations again.
+ self.haizea.process_reservations(self.time)
+
+ # Print a status message
+ if self.statusinterval != None and (self.time - prevstatustime).minutes >= self.statusinterval:
+ self.haizea.print_status()
+ prevstatustime = self.time
+
+ # Skip to next point in time.
+ self.time, self.done = self.__get_next_time()
+
+ self.logger.status("Simulated clock has stopped")
+
+ # Stop the resource manager
+ self.haizea.graceful_stop()
+
+
+ def __get_next_time(self):
+ """Determines what is the next point in time to skip to.
+
+ At a given point in time, the next time is the earliest of the following:
+ * The arrival of the next lease request
+ * The start or end of a reservation (a "changepoint" in the slot table)
+ * A premature end of a lease
+ """
+
+ # Determine candidate next times
+ tracefrontend = self.__get_trace_frontend()
+ nextchangepoint = self.haizea.get_next_changepoint()
+ nextprematureend = self.haizea.scheduler.slottable.getNextPrematureEnd(self.time)
+ nextreqtime = tracefrontend.get_next_request_time()
+ self.logger.debug("Next change point (in slot table): %s" % nextchangepoint)
+ self.logger.debug("Next request time: %s" % nextreqtime)
+ self.logger.debug("Next premature end: %s" % nextprematureend)
+
+ # The previous time is now
+ prevtime = self.time
+
+ # We initialize the next time to now too, to detect if
+ # we've been unable to determine what the next time is.
+ newtime = self.time
+
+ # Find the earliest of the three, accounting for None values
+ if nextchangepoint != None and nextreqtime == None:
+ newtime = nextchangepoint
+ elif nextchangepoint == None and nextreqtime != None:
+ newtime = nextreqtime
+ elif nextchangepoint != None and nextreqtime != None:
+ newtime = min(nextchangepoint, nextreqtime)
+
+ if nextprematureend != None:
+ newtime = min(nextprematureend, newtime)
+
+ if nextchangepoint == newtime:
+ # Note that, above, we just "peeked" the next changepoint in the slottable.
+ # If it turns out we're skipping to that point in time, then we need to
+ # "get" it (this is because changepoints in the slottable are cached to
+ # minimize access to the slottable. This optimization turned out to
+ # be more trouble than it's worth and will probably be removed sometime
+ # soon.
+ newtime = self.haizea.scheduler.slottable.getNextChangePoint(newtime)
+
+ # If there's no more leases in the system, and no more pending requests,
+ # then we're done.
+ if not self.haizea.exists_leases_in_rm() and not tracefrontend.exists_more_requests():
+ self.done = True
+
+ # We can also be done if we've specified that we want to stop when
+ # the best-effort requests are all done or when they've all been submitted.
+ stopwhen = self.haizea.config.get("stop-when")
+ besteffort = self.haizea.scheduler.leases.get_leases(type = BestEffortLease)
+ pendingbesteffort = [r for r in tracefrontend.requests if isinstance(r, BestEffortLease)]
+ if stopwhen == constants.STOPWHEN_BEDONE:
+ if self.haizea.scheduler.is_queue_empty() and len(besteffort) + len(pendingbesteffort) == 0:
+ self.done = True
+ elif stopwhen == constants.STOPWHEN_BESUBMITTED:
+ if len(pendingbesteffort) == 0:
+ self.done = True
+
+ # If we didn't arrive at a new time, and we're not done, we've fallen into
+ # an infinite loop. This is A Bad Thing(tm).
+ if newtime == prevtime and self.done != True:
+ raise Exception, "Simulated clock has fallen into an infinite loop."
+
+ return newtime, self.done
+
+ def __get_trace_frontend(self):
+ """Gets the tracefile frontend from the resource manager"""
+ frontends = self.haizea.frontends
+ tracef = [f for f in frontends if isinstance(f, TracefileFrontend)]
+ if len(tracef) != 1:
+ raise Exception, "The simulated clock can only work with a tracefile request frontend."
+ else:
+ return tracef[0]
+
+
+class RealClock(Clock):
+ """A realtime clock.
+
+ The real clock wakes up periodically to, in turn, tell the resource manager
+ to wake up. The real clock can also be run in a "fastforward" mode for
+ debugging purposes (however, unlike the simulated clock, the clock will
+ always skip a fixed amount of time into the future).
+ """
+ def __init__(self, haizea, quantum, non_sched, fastforward = False):
+ """Initializes the real clock.
+
+ Arguments:
+ haizea -- the resource manager
+ quantum -- interval between clock wakeups
+ fastforward -- if True, the clock won't actually sleep
+ for the duration of the quantum."""
+ Clock.__init__(self, haizea)
+ self.fastforward = fastforward
+ if not self.fastforward:
+ self.lastwakeup = None
+ else:
+ self.lastwakeup = round_datetime(now())
+ self.logger = logging.getLogger("CLOCK")
+ self.starttime = self.get_time()
+ self.nextschedulable = None
+ self.nextperiodicwakeup = None
+ self.quantum = TimeDelta(seconds=quantum)
+ self.non_sched = TimeDelta(seconds=non_sched)
+
+ def get_time(self):
+ """See docstring in base Clock class."""
+ if not self.fastforward:
+ return now()
+ else:
+ return self.lastwakeup
+
+ def get_start_time(self):
+ """See docstring in base Clock class."""
+ return self.starttime
+
+ def get_next_schedulable_time(self):
+ """See docstring in base Clock class."""
+ return self.nextschedulable
+
+ def run(self):
+ """Runs the real clock through time.
+
+ The clock starts when run() is called. In each iteration of the main loop
+ it will do the following:
+ - Wake up the resource manager
+ - Determine if there will be anything to do before the next
+ time the clock will wake up (after the quantum has passed). Note
+ that this information is readily available on the slot table.
+ If so, set next-wakeup-time to (now + time until slot table
+ event). Otherwise, set it to (now + quantum)
+ - Sleep until next-wake-up-time
+
+ The clock keeps on tickin' until a SIGINT signal (Ctrl-C if running in the
+ foreground) or a SIGTERM signal is received.
+ """
+ self.logger.status("Starting clock")
+ self.haizea.accounting.start(self.get_start_time())
+
+ try:
+ signal.signal(signal.SIGINT, self.signalhandler_gracefulstop)
+ signal.signal(signal.SIGTERM, self.signalhandler_gracefulstop)
+ except ValueError, exc:
+ # This means Haizea is not the main thread, which will happen
+ # when running it as part of a py.test. We simply ignore this
+ # to allow the test to continue.
+ pass
+
+ # Main loop
+ while not self.done:
+ self.logger.status("Waking up to manage resources")
+
+ # Save the waking time. We want to use a consistent time in the
+ # resource manager operations (if we use now(), we'll get a different
+ # time every time)
+ if not self.fastforward:
+ self.lastwakeup = round_datetime(self.get_time())
+ self.logger.status("Wake-up time recorded as %s" % self.lastwakeup)
+
+ # Next schedulable time
+ self.nextschedulable = round_datetime(self.lastwakeup + self.non_sched)
+
+ # Wake up the resource manager
+ self.haizea.process_reservations(self.lastwakeup)
+ # TODO: Compute nextschedulable here, before processing requests
+ self.haizea.process_requests(self.nextschedulable)
+
+ # Next wakeup time
+ time_now = now()
+ if self.lastwakeup + self.quantum <= time_now:
+ quantums = (time_now - self.lastwakeup) / self.quantum
+ quantums = int(ceil(quantums)) * self.quantum
+ self.nextperiodicwakeup = round_datetime(self.lastwakeup + quantums)
+ else:
+ self.nextperiodicwakeup = round_datetime(self.lastwakeup + self.quantum)
+
+ # Determine if there's anything to do before the next wakeup time
+ nextchangepoint = self.haizea.get_next_changepoint()
+ if nextchangepoint != None and nextchangepoint <= self.nextperiodicwakeup:
+ # We need to wake up earlier to handle a slot table event
+ nextwakeup = nextchangepoint
+ self.haizea.scheduler.slottable.getNextChangePoint(self.lastwakeup)
+ self.logger.status("Going back to sleep. Waking up at %s to handle slot table event." % nextwakeup)
+ else:
+ # Nothing to do before waking up
+ nextwakeup = self.nextperiodicwakeup
+ self.logger.status("Going back to sleep. Waking up at %s to see if something interesting has happened by then." % nextwakeup)
+
+ # The only exit condition from the real clock is if the stop_when_no_more_leases
+ # is set to True, and there's no more work left to do.
+ # TODO: This first if is a kludge. Other options should only interact with
+ # options through the configfile's get method. The "stop-when-no-more-leases"
+ # option is currently OpenNebula-specific (while the real clock isn't; it can
+ # be used by both the simulator and the OpenNebula mode). This has to be
+ # fixed.
+ if self.haizea.config._options.has_key("stop-when-no-more-leases"):
+ stop_when_no_more_leases = self.haizea.config.get("stop-when-no-more-leases")
+ if stop_when_no_more_leases and not self.haizea.exists_leases_in_rm():
+ self.done = True
+
+ # Sleep
+ if not self.done:
+ if not self.fastforward:
+ sleep((nextwakeup - now()).seconds)
+ else:
+ self.lastwakeup = nextwakeup
+
+ self.logger.status("Real clock has stopped")
+
+ # Stop the resource manager
+ self.haizea.graceful_stop()
+
+ def signalhandler_gracefulstop(self, signum, frame):
+ """Handler for SIGTERM and SIGINT. Allows Haizea to stop gracefully."""
+
+ sigstr = ""
+ if signum == signal.SIGTERM:
+ sigstr = " (SIGTERM)"
+ elif signum == signal.SIGINT:
+ sigstr = " (SIGINT)"
+ self.logger.status("Received signal %i%s" %(signum, sigstr))
+ self.done = True
+
Property changes on: branches/TP2.0/src/haizea/core/haizea.py
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Modified: branches/TP2.0/src/haizea/core/log.py
===================================================================
--- branches/TP2.0/src/haizea/core/log.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/core/log.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -17,7 +17,7 @@
# -------------------------------------------------------------------------- #
import logging
-from haizea.core.rm import ResourceManager
+from haizea.core.haizea import Haizea
from haizea.common.constants import LOGLEVEL_VDEBUG, LOGLEVEL_STATUS
logging.addLevelName(LOGLEVEL_VDEBUG, "VDEBUG")
@@ -28,7 +28,7 @@
def makeRecord(self, name, lvl, fn, lno, msg, args, exc_info, func, extra):
# Modify "extra" parameter keyword
- haizeatime = ResourceManager.get_singleton().clock.get_time()
+ haizeatime = Haizea.get_singleton().clock.get_time()
extra = { "haizeatime" : haizeatime}
return logging.Logger.makeRecord(self, name, lvl, fn, lno, msg, args, exc_info, func, extra)
Deleted: branches/TP2.0/src/haizea/core/rm.py
===================================================================
--- branches/TP2.0/src/haizea/core/rm.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/core/rm.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -1,846 +0,0 @@
-# -------------------------------------------------------------------------- #
-# Copyright 2006-2008, University of Chicago #
-# Copyright 2008, Distributed Systems Architecture Group, Universidad #
-# Complutense de Madrid (dsa-research.org) #
-# #
-# Licensed under the Apache License, Version 2.0 (the "License"); you may #
-# not use this file except in compliance with the License. You may obtain #
-# a copy of the License at #
-# #
-# http://www.apache.org/licenses/LICENSE-2.0 #
-# #
-# Unless required by applicable law or agreed to in writing, software #
-# distributed under the License is distributed on an "AS IS" BASIS, #
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
-# See the License for the specific language governing permissions and #
-# limitations under the License. #
-# -------------------------------------------------------------------------- #
-
-"""The rm (resource manager) module is the root of Haizea. If you want to
-see where the ball starts rolling, look at the following two functions:
-
-* rm.ResourceManager.__init__()
-* rm.ResourceManager.start()
-
-This module provides the following classes:
-
-* ResourceManager: The resource manager itself. Pretty much everything else
- is contained in this class.
-* Clock: A base class for the resource manager's clock.
-* SimulatedClock: A clock for simulations.
-* RealClock: A clock that advances in realtime.
-"""
-
-import haizea.core.accounting as accounting
-import haizea.common.constants as constants
-from haizea.core.scheduler.preparation_schedulers.unmanaged import UnmanagedPreparationScheduler
-from haizea.core.scheduler.preparation_schedulers.imagetransfer import ImageTransferPreparationScheduler
-from haizea.core.enact.opennebula import OpenNebulaResourcePoolInfo, OpenNebulaVMEnactment, OpenNebulaDummyDeploymentEnactment
-from haizea.core.enact.simulated import SimulatedResourcePoolInfo, SimulatedVMEnactment, SimulatedDeploymentEnactment
-from haizea.core.frontends.tracefile import TracefileFrontend
-from haizea.core.frontends.opennebula import OpenNebulaFrontend
-from haizea.core.frontends.rpc import RPCFrontend
-from haizea.core.leases import BestEffortLease
-from haizea.core.scheduler import UnrecoverableError
-from haizea.core.scheduler.lease_scheduler import LeaseScheduler
-from haizea.core.scheduler.vm_scheduler import VMScheduler
-from haizea.core.scheduler.slottable import SlotTable
-from haizea.core.scheduler.policy import Policy
-from haizea.core.scheduler.resourcepool import ResourcePool, ResourcePoolWithReusableImages
-from haizea.core.rpcserver import RPCServer
-from haizea.common.utils import abstract, round_datetime, Singleton
-
-import operator
-import logging
-import signal
-import sys, os
-import traceback
-from time import sleep
-from math import ceil
-from mx.DateTime import now, TimeDelta
-
-DAEMON_STDOUT = DAEMON_STDIN = "/dev/null"
-DAEMON_STDERR = "/var/tmp/haizea.err"
-DEFAULT_LOGFILE = "/var/tmp/haizea.log"
-
-class ResourceManager(Singleton):
- """The resource manager
-
- This class is the root of Haizea. Pretty much everything else (scheduler,
- enactment modules, etc.) is contained in this class. The ResourceManager
- class is meant to be a singleton.
-
- """
-
- def __init__(self, config, daemon=False, pidfile=None):
- """Initializes the resource manager.
-
- Argument:
- config -- a populated instance of haizea.common.config.RMConfig
- daemon -- True if Haizea must run as a daemon, False if it must
- run in the foreground
- pidfile -- When running as a daemon, file to save pid to
- """
- self.config = config
-
- # Create the RM components
-
- mode = config.get("mode")
-
- self.daemon = daemon
- self.pidfile = pidfile
-
- if mode == "simulated":
- self.init_simulated_mode()
- elif mode == "opennebula":
- self.init_opennebula_mode()
-
- # Statistics collection
- self.accounting = accounting.AccountingDataCollection(self, self.config.get("datafile"))
-
- self.logger = logging.getLogger("RM")
-
- def init_simulated_mode(self):
- """Initializes the resource manager in simulated mode
-
- """
-
- # Simulated-time simulations always run in the foreground
- clock = self.config.get("clock")
- if clock == constants.CLOCK_SIMULATED:
- self.daemon = False
-
- self.init_logging()
-
- if clock == constants.CLOCK_SIMULATED:
- starttime = self.config.get("starttime")
- self.clock = SimulatedClock(self, starttime)
- self.rpc_server = None
- elif clock == constants.CLOCK_REAL:
- wakeup_interval = self.config.get("wakeup-interval")
- non_sched = self.config.get("non-schedulable-interval")
- self.clock = RealClock(self, wakeup_interval, non_sched)
- self.rpc_server = RPCServer(self)
-
- # Enactment modules
- info_enact = SimulatedResourcePoolInfo()
- vm_enact = SimulatedVMEnactment()
- deploy_enact = SimulatedDeploymentEnactment()
-
- # Resource pool
- preparation_type = self.config.get("lease-preparation")
- if preparation_type == constants.PREPARATION_TRANSFER:
- if self.config.get("diskimage-reuse") == constants.REUSE_IMAGECACHES:
- resourcepool = ResourcePoolWithReusableImages(info_enact, vm_enact, deploy_enact)
- else:
- resourcepool = ResourcePool(info_enact, vm_enact, deploy_enact)
- else:
- resourcepool = ResourcePool(info_enact, vm_enact, deploy_enact)
-
- # Slot table
- slottable = SlotTable()
- for n in resourcepool.get_nodes() + resourcepool.get_aux_nodes():
- slottable.add_node(n)
-
- # Preparation scheduler
- if preparation_type == constants.PREPARATION_UNMANAGED:
- preparation_scheduler = UnmanagedPreparationScheduler(slottable, resourcepool, deploy_enact)
- elif preparation_type == constants.PREPARATION_TRANSFER:
- preparation_scheduler = ImageTransferPreparationScheduler(slottable, resourcepool, deploy_enact)
-
- # VM Scheduler
- vm_scheduler = VMScheduler(slottable, resourcepool)
-
- # Lease Scheduler
- self.scheduler = LeaseScheduler(vm_scheduler, preparation_scheduler, slottable)
-
- # Policy engine
- self.policy = Policy()
-
- # Lease request frontends
- if clock == constants.CLOCK_SIMULATED:
- # In pure simulation, we can only use the tracefile frontend
- self.frontends = [TracefileFrontend(self, self.clock.get_start_time())]
- elif clock == constants.CLOCK_REAL:
- # In simulation with a real clock, only the RPC frontend can be used
- self.frontends = [RPCFrontend(self)]
-
- def init_opennebula_mode(self):
- """Initializes the resource manager in OpenNebula mode
-
- """
- self.init_logging()
-
- # The clock
- wakeup_interval = self.config.get("wakeup-interval")
- non_sched = self.config.get("non-schedulable-interval")
- dry_run = self.config.get("dry-run")
- fastforward = dry_run
- self.clock = RealClock(self, wakeup_interval, non_sched, fastforward)
-
- # RPC server
- if dry_run:
- # No need for an RPC server when doing a dry run
- self.rpc_server = None
- else:
- self.rpc_server = RPCServer(self)
-
- # Enactment modules
- info_enact = OpenNebulaResourcePoolInfo()
- vm_enact = OpenNebulaVMEnactment()
- # No deployment in OpenNebula. Using dummy one for now.
- deploy_enact = OpenNebulaDummyDeploymentEnactment()
-
- # Resource pool
- resourcepool = ResourcePool(info_enact, vm_enact, deploy_enact)
-
- # Slot table
- slottable = SlotTable()
- for n in resourcepool.get_nodes() + resourcepool.get_aux_nodes():
- slottable.add_node(n)
-
-
- # Deployment module
- preparation_scheduler = UnmanagedPreparationScheduler(slottable, resourcepool, deploy_enact)
-
- # VM Scheduler
- vm_scheduler = VMScheduler(slottable, resourcepool)
-
- # Lease Scheduler
- self.scheduler = LeaseScheduler(vm_scheduler, preparation_scheduler, slottable)
-
- # Lease request frontends
- self.frontends = [OpenNebulaFrontend(self)]
-
-
- def init_logging(self):
- """Initializes logging
-
- """
-
- from haizea.core.log import HaizeaLogger
- logger = logging.getLogger("")
- if self.daemon:
- handler = logging.FileHandler(self.config.get("logfile"))
- else:
- handler = logging.StreamHandler()
- formatter = logging.Formatter('[%(haizeatime)s] %(name)-7s %(message)s')
- handler.setFormatter(formatter)
- logger.addHandler(handler)
- level = logging.getLevelName(self.config.get("loglevel"))
- logger.setLevel(level)
- logging.setLoggerClass(HaizeaLogger)
-
-
- def daemonize(self):
- """Daemonizes the Haizea process.
-
- Based on code in: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66012
-
- """
- # First fork
- try:
- pid = os.fork()
- if pid > 0:
- # Exit first parent
- sys.exit(0)
- except OSError, e:
- sys.stderr.write("Failed to daemonize Haizea: (%d) %s\n" % (e.errno, e.strerror))
- sys.exit(1)
-
- # Decouple from parent environment.
- os.chdir(".")
- os.umask(0)
- os.setsid()
-
- # Second fork
- try:
- pid = os.fork()
- if pid > 0:
- # Exit second parent.
- sys.exit(0)
- except OSError, e:
- sys.stderr.write("Failed to daemonize Haizea: (%d) %s\n" % (e.errno, e.strerror))
- sys.exit(2)
-
- # Open file descriptors and print start message
- si = file(DAEMON_STDIN, 'r')
- so = file(DAEMON_STDOUT, 'a+')
- se = file(DAEMON_STDERR, 'a+', 0)
- pid = os.getpid()
- sys.stderr.write("\nStarted Haizea daemon with pid %i\n\n" % pid)
- sys.stderr.flush()
- file(self.pidfile,'w+').write("%i\n" % pid)
-
- # Redirect standard file descriptors.
- os.close(sys.stdin.fileno())
- os.close(sys.stdout.fileno())
- os.close(sys.stderr.fileno())
- os.dup2(si.fileno(), sys.stdin.fileno())
- os.dup2(so.fileno(), sys.stdout.fileno())
- os.dup2(se.fileno(), sys.stderr.fileno())
-
- def start(self):
- """Starts the resource manager"""
- self.logger.info("Starting resource manager")
-
- # Create counters to keep track of interesting data.
- self.accounting.create_counter(constants.COUNTER_ARACCEPTED, constants.AVERAGE_NONE)
- self.accounting.create_counter(constants.COUNTER_ARREJECTED, constants.AVERAGE_NONE)
- self.accounting.create_counter(constants.COUNTER_IMACCEPTED, constants.AVERAGE_NONE)
- self.accounting.create_counter(constants.COUNTER_IMREJECTED, constants.AVERAGE_NONE)
- self.accounting.create_counter(constants.COUNTER_BESTEFFORTCOMPLETED, constants.AVERAGE_NONE)
- self.accounting.create_counter(constants.COUNTER_QUEUESIZE, constants.AVERAGE_TIMEWEIGHTED)
- self.accounting.create_counter(constants.COUNTER_DISKUSAGE, constants.AVERAGE_NONE)
- self.accounting.create_counter(constants.COUNTER_UTILIZATION, constants.AVERAGE_NONE)
-
- if self.daemon:
- self.daemonize()
- if self.rpc_server:
- self.rpc_server.start()
-
- # Start the clock
- try:
- self.clock.run()
- except UnrecoverableError, exc:
- self.__unrecoverable_error(exc)
- except Exception, exc:
- self.__unexpected_exception(exc)
-
- def stop(self):
- """Stops the resource manager by stopping the clock"""
- self.clock.stop()
-
- def graceful_stop(self):
- """Stops the resource manager gracefully and exits"""
-
- self.logger.status("Stopping resource manager gracefully...")
-
- # Stop collecting data (this finalizes counters)
- self.accounting.stop()
-
- # TODO: When gracefully stopping mid-scheduling, we need to figure out what to
- # do with leases that are still running.
-
- self.print_status()
-
- # In debug mode, dump the lease descriptors.
- for lease in self.scheduler.completed_leases.entries.values():
- lease.print_contents()
-
- # Write all collected data to disk
- self.accounting.save_to_disk()
-
- # Stop RPC server
- if self.rpc_server != None:
- self.rpc_server.stop()
-
- def process_requests(self, nexttime):
- """Process any new requests in the request frontend
-
- Checks the request frontend to see if there are any new requests that
- have to be processed. AR leases are sent directly to the schedule.
- Best-effort leases are queued.
-
- Arguments:
- nexttime -- The next time at which the scheduler can allocate resources.
- This is meant to be provided by the clock simply as a sanity
- measure when running in real time (to avoid scheduling something
- "now" to actually have "now" be in the past once the scheduling
- function returns. i.e., nexttime has nothing to do with whether
- there are resources available at that time or not.
-
- """
-
- # Get requests from frontend
- requests = []
- for frontend in self.frontends:
- requests += frontend.get_accumulated_requests()
- requests.sort(key=operator.attrgetter("submit_time"))
-
- # Request leases and run the scheduling function.
- try:
- self.logger.vdebug("Requesting leases")
- for req in requests:
- self.scheduler.request_lease(req)
-
- self.logger.vdebug("Running scheduling function")
- self.scheduler.schedule(nexttime)
- except UnrecoverableError, exc:
- self.__unrecoverable_error(exc)
- except Exception, exc:
- self.__unexpected_exception(exc)
-
-
- def process_reservations(self, time):
- """Process reservations starting/stopping at specified time"""
-
- # The scheduler takes care of this.
- try:
- self.scheduler.process_reservations(time)
- except UnrecoverableError, exc:
- self.__unrecoverable_error(exc)
- except Exception, exc:
- self.__unexpected_exception(exc)
-
- def notify_event(self, lease_id, event):
- """Notifies an asynchronous event to Haizea.
-
- Arguments:
- lease_id -- ID of lease that is affected by event
- event -- Event (currently, only the constants.EVENT_END_VM event is supported)
- """
- try:
- lease = self.scheduler.get_lease_by_id(lease_id)
- self.scheduler.notify_event(lease, event)
- except UnrecoverableError, exc:
- self.__unrecoverable_error(exc)
- except Exception, exc:
- self.__unexpected_exception(exc)
-
- def cancel_lease(self, lease_id):
- """Cancels a lease.
-
- Arguments:
- lease_id -- ID of lease to cancel
- """
- try:
- lease = self.scheduler.get_lease_by_id(lease_id)
- self.scheduler.cancel_lease(lease)
- except UnrecoverableError, exc:
- self.__unrecoverable_error(exc)
- except Exception, exc:
- self.__unexpected_exception(exc)
-
- def get_next_changepoint(self):
- """Return next changepoint in the slot table"""
- return self.scheduler.slottable.peekNextChangePoint(self.clock.get_time())
-
- def exists_leases_in_rm(self):
- """Return True if there are any leases still "in the system" """
- return self.scheduler.exists_scheduled_leases() or not self.scheduler.is_queue_empty()
-
- def print_status(self):
- """Prints status summary."""
-
- leases = self.scheduler.leases.get_leases()
- completed_leases = self.scheduler.completed_leases.get_leases()
- self.logger.status("--- Haizea status summary ---")
- self.logger.status("Number of leases (not including completed): %i" % len(leases))
- self.logger.status("Completed leases: %i" % len(completed_leases))
- self.logger.status("Completed best-effort leases: %i" % self.accounting.data.counters[constants.COUNTER_BESTEFFORTCOMPLETED])
- self.logger.status("Queue size: %i" % self.accounting.data.counters[constants.COUNTER_QUEUESIZE])
- self.logger.status("Accepted AR leases: %i" % self.accounting.data.counters[constants.COUNTER_ARACCEPTED])
- self.logger.status("Rejected AR leases: %i" % self.accounting.data.counters[constants.COUNTER_ARREJECTED])
- self.logger.status("Accepted IM leases: %i" % self.accounting.data.counters[constants.COUNTER_IMACCEPTED])
- self.logger.status("Rejected IM leases: %i" % self.accounting.data.counters[constants.COUNTER_IMREJECTED])
- self.logger.status("---- End summary ----")
-
- def __unrecoverable_error(self, exc):
- """Handles an unrecoverable error.
-
- This method prints information on the unrecoverable error and makes Haizea panic.
- """
- self.logger.error("An unrecoverable error has happened.")
- self.logger.error("Original exception:")
- self.__print_exception(exc.exc, exc.get_traceback())
- self.logger.error("Unrecoverable error traceback:")
- self.__print_exception(exc, sys.exc_traceback)
- self.__panic()
-
- def __unexpected_exception(self, exc):
- """Handles an unrecoverable error.
-
- This method prints information on the unrecoverable error and makes Haizea panic.
- """
- self.logger.error("An unexpected exception has happened.")
- self.__print_exception(exc, sys.exc_traceback)
- self.__panic()
-
- def __print_exception(self, exc, exc_traceback):
- """Prints an exception's traceback to the log."""
- tb = traceback.format_tb(exc_traceback)
- for line in tb:
- self.logger.error(line)
- self.logger.error("Message: %s" % exc)
-
-
- def __panic(self):
- """Makes Haizea crash and burn in a panicked frenzy"""
-
- self.logger.status("Panicking...")
-
- # Stop RPC server
- if self.rpc_server != None:
- self.rpc_server.stop()
-
- # Dump state
- self.print_status()
- self.logger.error("Next change point (in slot table): %s" % self.get_next_changepoint())
-
- # Print lease descriptors
- leases = self.scheduler.leases.get_leases()
- if len(leases)>0:
- self.logger.vdebug("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv")
- for lease in leases:
- lease.print_contents()
- self.logger.vdebug("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^")
-
- # Exit
- treatment = self.config.get("lease-failure-handling")
- if treatment == constants.ONFAILURE_EXIT_RAISE:
- raise
- else:
- exit(1)
-
-
-class Clock(object):
- """Base class for the resource manager's clock.
-
- The clock is in charge of periodically waking the resource manager so it
- will process new requests and handle existing reservations. This is a
- base class defining abstract methods.
-
- """
- def __init__(self, rm):
- self.rm = rm
- self.done = False
-
- def get_time(self):
- """Return the current time"""
- return abstract()
-
- def get_start_time(self):
- """Return the time at which the clock started ticking"""
- return abstract()
-
- def get_next_schedulable_time(self):
- """Return the next time at which resources could be scheduled.
-
- The "next schedulable time" server sanity measure when running
- in real time (to avoid scheduling something "now" to actually
- have "now" be in the past once the scheduling function returns.
- i.e., the "next schedulable time" has nothing to do with whether
- there are resources available at that time or not.
- """
- return abstract()
-
- def run(self):
- """Start and run the clock. This function is, in effect,
- the main loop of the resource manager."""
- return abstract()
-
- def stop(self):
- """Stop the clock.
-
- Stopping the clock makes Haizea exit.
- """
- self.done = True
-
-
-class SimulatedClock(Clock):
- """Simulates the passage of time... really fast.
-
- The simulated clock steps through time to produce an ideal schedule.
- See the run() function for a description of how time is incremented
- exactly in the simulated clock.
-
- """
-
- def __init__(self, rm, starttime):
- """Initialize the simulated clock, starting at the provided starttime"""
- Clock.__init__(self, rm)
- self.starttime = starttime
- self.time = starttime
- self.logger = logging.getLogger("CLOCK")
- self.statusinterval = self.rm.config.get("status-message-interval")
-
- def get_time(self):
- """See docstring in base Clock class."""
- return self.time
-
- def get_start_time(self):
- """See docstring in base Clock class."""
- return self.starttime
-
- def get_next_schedulable_time(self):
- """See docstring in base Clock class."""
- return self.time
-
- def run(self):
- """Runs the simulated clock through time.
-
- The clock starts at the provided start time. At each point in time,
- it wakes up the resource manager and then skips to the next time
- where "something" is happening (see __get_next_time for a more
- rigorous description of this).
-
- The clock stops when there is nothing left to do (no pending or
- queue requests, and no future reservations)
-
- The simulated clock can only work in conjunction with the
- tracefile request frontend.
- """
- self.logger.status("Starting simulated clock")
- self.rm.accounting.start(self.get_start_time())
- prevstatustime = self.time
-
- # Main loop
- while not self.done:
- # Check to see if there are any leases which are ending prematurely.
- # Note that this is unique to simulation.
- prematureends = self.rm.scheduler.slottable.getPrematurelyEndingRes(self.time)
-
- # Notify the resource manager about the premature ends
- for rr in prematureends:
- self.rm.notify_event(rr.lease.id, constants.EVENT_END_VM)
-
- # Process reservations starting/stopping at the current time and
- # check if there are any new requests.
- self.rm.process_reservations(self.time)
- self.rm.process_requests(self.time)
-
- # Since processing requests may have resulted in new reservations
- # starting now, we process reservations again.
- self.rm.process_reservations(self.time)
-
- # Print a status message
- if self.statusinterval != None and (self.time - prevstatustime).minutes >= self.statusinterval:
- self.rm.print_status()
- prevstatustime = self.time
-
- # Skip to next point in time.
- self.time, self.done = self.__get_next_time()
-
- self.logger.status("Simulated clock has stopped")
-
- # Stop the resource manager
- self.rm.graceful_stop()
-
-
- def __get_next_time(self):
- """Determines what is the next point in time to skip to.
-
- At a given point in time, the next time is the earliest of the following:
- * The arrival of the next lease request
- * The start or end of a reservation (a "changepoint" in the slot table)
- * A premature end of a lease
- """
-
- # Determine candidate next times
- tracefrontend = self.__get_trace_frontend()
- nextchangepoint = self.rm.get_next_changepoint()
- nextprematureend = self.rm.scheduler.slottable.getNextPrematureEnd(self.time)
- nextreqtime = tracefrontend.get_next_request_time()
- self.logger.debug("Next change point (in slot table): %s" % nextchangepoint)
- self.logger.debug("Next request time: %s" % nextreqtime)
- self.logger.debug("Next premature end: %s" % nextprematureend)
-
- # The previous time is now
- prevtime = self.time
-
- # We initialize the next time to now too, to detect if
- # we've been unable to determine what the next time is.
- newtime = self.time
-
- # Find the earliest of the three, accounting for None values
- if nextchangepoint != None and nextreqtime == None:
- newtime = nextchangepoint
- elif nextchangepoint == None and nextreqtime != None:
- newtime = nextreqtime
- elif nextchangepoint != None and nextreqtime != None:
- newtime = min(nextchangepoint, nextreqtime)
-
- if nextprematureend != None:
- newtime = min(nextprematureend, newtime)
-
- if nextchangepoint == newtime:
- # Note that, above, we just "peeked" the next changepoint in the slottable.
- # If it turns out we're skipping to that point in time, then we need to
- # "get" it (this is because changepoints in the slottable are cached to
- # minimize access to the slottable. This optimization turned out to
- # be more trouble than it's worth and will probably be removed sometime
- # soon.
- newtime = self.rm.scheduler.slottable.getNextChangePoint(newtime)
-
- # If there's no more leases in the system, and no more pending requests,
- # then we're done.
- if not self.rm.exists_leases_in_rm() and not tracefrontend.exists_more_requests():
- self.done = True
-
- # We can also be done if we've specified that we want to stop when
- # the best-effort requests are all done or when they've all been submitted.
- stopwhen = self.rm.config.get("stop-when")
- besteffort = self.rm.scheduler.leases.get_leases(type = BestEffortLease)
- pendingbesteffort = [r for r in tracefrontend.requests if isinstance(r, BestEffortLease)]
- if stopwhen == constants.STOPWHEN_BEDONE:
- if self.rm.scheduler.is_queue_empty() and len(besteffort) + len(pendingbesteffort) == 0:
- self.done = True
- elif stopwhen == constants.STOPWHEN_BESUBMITTED:
- if len(pendingbesteffort) == 0:
- self.done = True
-
- # If we didn't arrive at a new time, and we're not done, we've fallen into
- # an infinite loop. This is A Bad Thing(tm).
- if newtime == prevtime and self.done != True:
- raise Exception, "Simulated clock has fallen into an infinite loop."
-
- return newtime, self.done
-
- def __get_trace_frontend(self):
- """Gets the tracefile frontend from the resource manager"""
- frontends = self.rm.frontends
- tracef = [f for f in frontends if isinstance(f, TracefileFrontend)]
- if len(tracef) != 1:
- raise Exception, "The simulated clock can only work with a tracefile request frontend."
- else:
- return tracef[0]
-
-
-class RealClock(Clock):
- """A realtime clock.
-
- The real clock wakes up periodically to, in turn, tell the resource manager
- to wake up. The real clock can also be run in a "fastforward" mode for
- debugging purposes (however, unlike the simulated clock, the clock will
- always skip a fixed amount of time into the future).
- """
- def __init__(self, rm, quantum, non_sched, fastforward = False):
- """Initializes the real clock.
-
- Arguments:
- rm -- the resource manager
- quantum -- interval between clock wakeups
- fastforward -- if True, the clock won't actually sleep
- for the duration of the quantum."""
- Clock.__init__(self, rm)
- self.fastforward = fastforward
- if not self.fastforward:
- self.lastwakeup = None
- else:
- self.lastwakeup = round_datetime(now())
- self.logger = logging.getLogger("CLOCK")
- self.starttime = self.get_time()
- self.nextschedulable = None
- self.nextperiodicwakeup = None
- self.quantum = TimeDelta(seconds=quantum)
- self.non_sched = TimeDelta(seconds=non_sched)
-
- def get_time(self):
- """See docstring in base Clock class."""
- if not self.fastforward:
- return now()
- else:
- return self.lastwakeup
-
- def get_start_time(self):
- """See docstring in base Clock class."""
- return self.starttime
-
- def get_next_schedulable_time(self):
- """See docstring in base Clock class."""
- return self.nextschedulable
-
- def run(self):
- """Runs the real clock through time.
-
- The clock starts when run() is called. In each iteration of the main loop
- it will do the following:
- - Wake up the resource manager
- - Determine if there will be anything to do before the next
- time the clock will wake up (after the quantum has passed). Note
- that this information is readily available on the slot table.
- If so, set next-wakeup-time to (now + time until slot table
- event). Otherwise, set it to (now + quantum)
- - Sleep until next-wake-up-time
-
- The clock keeps on tickin' until a SIGINT signal (Ctrl-C if running in the
- foreground) or a SIGTERM signal is received.
- """
- self.logger.status("Starting clock")
- self.rm.accounting.start(self.get_start_time())
-
- try:
- signal.signal(signal.SIGINT, self.signalhandler_gracefulstop)
- signal.signal(signal.SIGTERM, self.signalhandler_gracefulstop)
- except ValueError, exc:
- # This means Haizea is not the main thread, which will happen
- # when running it as part of a py.test. We simply ignore this
- # to allow the test to continue.
- pass
-
- # Main loop
- while not self.done:
- self.logger.status("Waking up to manage resources")
-
- # Save the waking time. We want to use a consistent time in the
- # resource manager operations (if we use now(), we'll get a different
- # time every time)
- if not self.fastforward:
- self.lastwakeup = round_datetime(self.get_time())
- self.logger.status("Wake-up time recorded as %s" % self.lastwakeup)
-
- # Next schedulable time
- self.nextschedulable = round_datetime(self.lastwakeup + self.non_sched)
-
- # Wake up the resource manager
- self.rm.process_reservations(self.lastwakeup)
- # TODO: Compute nextschedulable here, before processing requests
- self.rm.process_requests(self.nextschedulable)
-
- # Next wakeup time
- time_now = now()
- if self.lastwakeup + self.quantum <= time_now:
- quantums = (time_now - self.lastwakeup) / self.quantum
- quantums = int(ceil(quantums)) * self.quantum
- self.nextperiodicwakeup = round_datetime(self.lastwakeup + quantums)
- else:
- self.nextperiodicwakeup = round_datetime(self.lastwakeup + self.quantum)
-
- # Determine if there's anything to do before the next wakeup time
- nextchangepoint = self.rm.get_next_changepoint()
- if nextchangepoint != None and nextchangepoint <= self.nextperiodicwakeup:
- # We need to wake up earlier to handle a slot table event
- nextwakeup = nextchangepoint
- self.rm.scheduler.slottable.getNextChangePoint(self.lastwakeup)
- self.logger.status("Going back to sleep. Waking up at %s to handle slot table event." % nextwakeup)
- else:
- # Nothing to do before waking up
- nextwakeup = self.nextperiodicwakeup
- self.logger.status("Going back to sleep. Waking up at %s to see if something interesting has happened by then." % nextwakeup)
-
- # The only exit condition from the real clock is if the stop_when_no_more_leases
- # is set to True, and there's no more work left to do.
- # TODO: This first if is a kludge. Other options should only interact with
- # options through the configfile's get method. The "stop-when-no-more-leases"
- # option is currently OpenNebula-specific (while the real clock isn't; it can
- # be used by both the simulator and the OpenNebula mode). This has to be
- # fixed.
- if self.rm.config._options.has_key("stop-when-no-more-leases"):
- stop_when_no_more_leases = self.rm.config.get("stop-when-no-more-leases")
- if stop_when_no_more_leases and not self.rm.exists_leases_in_rm():
- self.done = True
-
- # Sleep
- if not self.done:
- if not self.fastforward:
- sleep((nextwakeup - now()).seconds)
- else:
- self.lastwakeup = nextwakeup
-
- self.logger.status("Real clock has stopped")
-
- # Stop the resource manager
- self.rm.graceful_stop()
-
- def signalhandler_gracefulstop(self, signum, frame):
- """Handler for SIGTERM and SIGINT. Allows Haizea to stop gracefully."""
-
- sigstr = ""
- if signum == signal.SIGTERM:
- sigstr = " (SIGTERM)"
- elif signum == signal.SIGINT:
- sigstr = " (SIGINT)"
- self.logger.status("Received signal %i%s" %(signum, sigstr))
- self.done = True
-
Modified: branches/TP2.0/src/haizea/core/rpcserver.py
===================================================================
--- branches/TP2.0/src/haizea/core/rpcserver.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/core/rpcserver.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -36,8 +36,8 @@
self.socket.close()
class RPCServer(object):
- def __init__(self, rm):
- self.rm = rm
+ def __init__(self, haizea):
+ self.haizea = haizea
self.logger = logging.getLogger("RPCSERVER")
self.port = DEFAULT_HAIZEA_PORT
self.server = StoppableSimpleXMLRPCServer(("localhost", self.port), allow_none=True)
@@ -71,20 +71,20 @@
return 0
def cancel_lease(self, lease_id):
- self.rm.cancel_lease(lease_id)
+ self.haizea.cancel_lease(lease_id)
return 0
def get_leases(self):
- return [l.xmlrpc_marshall() for l in self.rm.scheduler.leases.get_leases()]
+ return [l.xmlrpc_marshall() for l in self.haizea.scheduler.leases.get_leases()]
def get_lease(self, lease_id):
return 0
def get_queue(self):
- return [l.xmlrpc_marshall() for l in self.rm.scheduler.queue]
+ return [l.xmlrpc_marshall() for l in self.haizea.scheduler.queue]
def get_hosts(self):
- return [h.xmlrpc_marshall() for h in self.rm.scheduler.vm_scheduler.resourcepool.nodes]
+ return [h.xmlrpc_marshall() for h in self.haizea.scheduler.vm_scheduler.resourcepool.nodes]
def notify_event(self, lease_id, enactment_id, event):
pass
\ No newline at end of file
Modified: branches/TP2.0/src/haizea/core/scheduler/lease_scheduler.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/lease_scheduler.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/core/scheduler/lease_scheduler.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -54,7 +54,7 @@
The constructor does little more than create the lease scheduler's
attributes. However, it does expect (in the arguments) a fully-constructed
VMScheduler, PreparationScheduler, and SlotTable (these are currently
- constructed in the ResourceManager's constructor).
+ constructed in the Haizea class constructor).
Arguments:
vm_scheduler -- VM scheduler
@@ -225,7 +225,7 @@
self.fail_lease(lease, exc)
# Other exceptions are not expected, and generally indicate a programming error.
- # Thus, they are propagated upwards to the ResourceManager where they will make
+ # Thus, they are propagated upwards to the Haizea class where they will make
# Haizea crash and burn.
@@ -250,7 +250,7 @@
self.fail_lease(lease, exc)
# Other exceptions are not expected, and generally indicate a programming error.
- # Thus, they are propagated upwards to the ResourceManager where they will make
+ # Thus, they are propagated upwards to the Haizea class where they will make
# Haizea crash and burn.
Modified: branches/TP2.0/src/haizea/core/scheduler/preparation_schedulers/imagetransfer.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/preparation_schedulers/imagetransfer.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/core/scheduler/preparation_schedulers/imagetransfer.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -361,8 +361,7 @@
return newtransfers
def estimate_image_transfer_time(self, lease, bandwidth):
- from haizea.core.rm import ResourceManager
- config = ResourceManager.get_singleton().config
+ config = get_config()
forceTransferTime = config.get("force-imagetransfer-time")
if forceTransferTime != None:
return forceTransferTime
Modified: branches/TP2.0/src/haizea/core/scheduler/vm_scheduler.py
===================================================================
--- branches/TP2.0/src/haizea/core/scheduler/vm_scheduler.py 2009-06-17 16:20:36 UTC (rev 587)
+++ branches/TP2.0/src/haizea/core/scheduler/vm_scheduler.py 2009-06-17 16:38:07 UTC (rev 588)
@@ -759,8 +759,7 @@
vmrr.post_rrs.append(shutdown_rr)
def __schedule_suspension(self, vmrr, suspend_by):
- from haizea.core.rm import ResourceManager
- config = ResourceManager.get_singleton().config
+ config = get_config()
susp_exclusion = config.get("suspendresume-exclusion")
override = get_config().get("override-suspend-time")
rate = config.get("suspend-rate")
@@ -802,8 +801,7 @@
vmrr.post_rrs.append(susprr)
def __schedule_resumption(self, vmrr, resume_at):
- from haizea.core.rm import ResourceManager
- config = ResourceManager.get_singleton().config
+ config = get_config()
resm_exclusion = config.get("suspendresume-exclusion")
override = get_config().get("override-resume-time")
rate = config.get("resume-rate")
@@ -891,8 +889,7 @@
# TODO: Take into account other things like boot overhead, migration overhead, etc.
def __compute_scheduling_threshold(self, lease):
- from haizea.core.rm import ResourceManager
- config = ResourceManager.get_singleton().config
+ config = get_config()
threshold = config.get("force-scheduling-threshold")
if threshold != None:
# If there is a hard-coded threshold, use that
More information about the Haizea-commit
mailing list