def __init__(self, lwffile, utilization_length, annotationfile, verbose = False): # Arbitrary start time self.starttime = DateTime(2006,11,25,13) self.workload = LeaseWorkload.from_xml_file(lwffile, self.starttime) self.site = Site.from_lwf_file(lwffile) if utilization_length == None: self.utilization_length = self.workload.get_leases()[-1].submit_time - self.starttime else: self.utilization_length = utilization_length if annotationfile != None: annotations = LeaseAnnotations.from_xml_file(annotationfile) annotations.apply_to_leases(self.workload.get_leases()) self.verbose = verbose
class Manager(object): """The root of Haizea This class is the root of Haizea. Pretty much everything else (scheduler, enactment modules, etc.) is contained in this class. The Manager class is meant to be a singleton. """ __metaclass__ = Singleton def __init__(self, config, daemon=False, pidfile=None, logging_handler=None, site=None): """Initializes the manager. Argument:site 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 self.logging_handler = logging_handler # Create the RM components mode = config.get("mode") self.daemon = daemon self.pidfile = pidfile if mode == "simulated": # Simulated-time simulations always run in the foreground clock = self.config.get("clock") if clock == constants.CLOCK_SIMULATED: self.daemon = False elif mode == "opennebula": clock = constants.CLOCK_REAL 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") if mode == "opennebula": fastforward = self.config.get("dry-run") else: fastforward = False self.clock = RealClock(self, wakeup_interval, non_sched, fastforward) if fastforward: # No need for an RPC server when doing a dry run self.rpc_server = None else: self.rpc_server = RPCServer(self) # Create the RPC singleton client for OpenNebula mode if mode == "opennebula": host = self.config.get("one.host") port = self.config.get("one.port") rv = OpenNebulaXMLRPCClient.get_userpass_from_env() if rv == None: print "ONE_AUTH environment variable is not set" exit(1) else: user, passw = rv[0], rv[1] try: OpenNebulaXMLRPCClientSingleton(host, port, user, passw) except socket.error, e: print "Unable to connect to OpenNebula" print "Reason: %s" % e exit(1) # Enactment modules if mode == "simulated": if not site: resources = self.config.get("simul.resources") if resources == "in-tracefile": tracefile = os.path.expanduser(self.config.get("tracefile")) self.site = Site.from_lwf_file(tracefile) elif resources.startswith("file:"): sitefile = resources.split(":") self.site = Site.from_xml_file(sitefile) else: self.site = Site.from_resources_string(resources) else: self.site = site deploy_bandwidth = config.get("imagetransfer-bandwidth") info_enact = SimulatedResourcePoolInfo(self.site) vm_enact = SimulatedVMEnactment() deploy_enact = SimulatedDeploymentEnactment(deploy_bandwidth) elif mode == "opennebula": # Enactment modules info_enact = OpenNebulaResourcePoolInfo() vm_enact = OpenNebulaVMEnactment() # No deployment in OpenNebula. Using dummy one for now. deploy_enact = OpenNebulaDummyDeploymentEnactment() if mode == "simulated": preparation_type = self.config.get("lease-preparation") elif mode == "opennebula": # No deployment in OpenNebula. preparation_type = constants.PREPARATION_UNMANAGED # Resource pool 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(info_enact.get_resource_types()) for n in resourcepool.get_nodes() + resourcepool.get_aux_nodes(): rt = slottable.create_resource_tuple_from_capacity(n.capacity) slottable.add_node(n.id, rt) # Policy manager admission = self.config.get("policy.admission") admission = admission_class_mappings.get(admission, admission) admission = import_class(admission) admission = admission(slottable) preemption = self.config.get("policy.preemption") preemption = preemption_class_mappings.get(preemption, preemption) preemption = import_class(preemption) preemption = preemption(slottable) host_selection = self.config.get("policy.host-selection") host_selection = host_class_mappings.get(host_selection, host_selection) host_selection = import_class(host_selection) host_selection = host_selection(slottable) matchmaking = self.config.get("policy.matchmaking") matchmaking = matchmaking_class_mappings.get(matchmaking, matchmaking) matchmaking = import_class(matchmaking) matchmaking = matchmaking(slottable) self.policy = PolicyManager(admission, preemption, host_selection, matchmaking) # 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 mapper and scheduler mapper = self.config.get("mapper") mapper = mapper_mappings.get(mapper, mapper) mapper = import_class(mapper) mapper = mapper(slottable, self.policy) # When using backfilling, set the number of leases that can be # scheduled in the future. backfilling = self.config.get("backfilling") if backfilling == constants.BACKFILLING_OFF: max_in_future = 0 elif backfilling == constants.BACKFILLING_AGGRESSIVE: max_in_future = 1 elif backfilling == constants.BACKFILLING_CONSERVATIVE: max_in_future = -1 # Unlimited elif backfilling == constants.BACKFILLING_INTERMEDIATE: max_in_future = self.config.get("backfilling-reservations") vm_scheduler = VMScheduler(slottable, resourcepool, mapper, max_in_future) # Statistics collection attrs = dict([(attr, self.config.get_attr(attr)) for attr in self.config.get_attrs()]) self.accounting = AccountingDataCollection(os.path.expanduser(self.config.get("datafile")), attrs) # Load probes probes = self.config.get("accounting-probes") probes = probes.split() for probe in probes: probe_class = probe_class_mappings.get(probe, probe) probe_class = import_class(probe_class) probe_obj = probe_class(self.accounting) self.accounting.add_probe(probe_obj) # Lease Scheduler self.scheduler = LeaseScheduler(vm_scheduler, preparation_scheduler, slottable, self.accounting) # Lease request frontends if mode == "simulated": if clock == constants.CLOCK_SIMULATED: # In pure simulation, we can only use the tracefile frontend self.frontends = [TracefileFrontend(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()] elif mode == "opennebula": self.frontends = [OpenNebulaFrontend()] persistence_file = self.config.get("persistence-file") if persistence_file == "none": persistence_file = None self.persistence = PersistenceManager(persistence_file) self.logger = logging.getLogger("RM")
def generate(self): lwf = ET.Element("lease-workload") lwf.set("name", self.outfile) description = ET.SubElement(lwf, "description") description.text = "Created with haizea-generate" attributes_elem = ET.SubElement(lwf, "attributes") attributes = self._get_attributes() for name, value in attributes.items(): attr_elem = ET.SubElement(attributes_elem, "attr") attr_elem.set("name", name) attr_elem.set("value", value) site = self.config.get(LWFGenerator.GENERAL_SEC, LWFGenerator.SITE_OPT) if site.startswith("file:"): sitefile = site.split(":") site = Site.from_xml_file(sitefile[1]) else: site = Site.from_resources_string(site) lwf.append(site.to_xml()) time = TimeDelta(seconds=0) requests = ET.SubElement(lwf, "lease-requests") if self.numleases_type == LWFGenerator.NUMLEASES_TYPE_INTERVAL: leases = [] numleases = self.config.getint(LWFGenerator.NUMLEASES_SEC, LWFGenerator.NUMLEASES_OPT) for i in xrange(numleases): leases.append(self.__gen_lease()) for l in leases: interval = TimeDelta(seconds=self._get_interval()) time += interval l.start.requested += time lease_request = ET.SubElement(requests, "lease-request") lease_request.set("arrival", str(time)) lease_request.append(l.to_xml()) elif self.numleases_type == LWFGenerator.NUMLEASES_TYPE_UTILIZATION: utilization = self.config.getfloat(LWFGenerator.NUMLEASES_SEC, LWFGenerator.NUMLEASES_UTILIZATION_OPT) utilization /= 100.0 last_request = self.config.get(LWFGenerator.NUMLEASES_SEC, LWFGenerator.NUMLEASES_LAST_REQUEST_OPT) last_request = Parser.DateTimeDeltaFromString(last_request) max_utilization = 0 for res in site.nodes.get_all_nodes().values(): for i in range(1,res.get_ninstances("CPU") + 1): max_utilization += (res.get_quantity_instance("CPU", i)/100.0) * last_request.seconds target_utilization = int(max_utilization * utilization) accum_utilization = 0 leases = [] while accum_utilization < target_utilization: lease = self.__gen_lease() leases.append(lease) duration = lease.duration.requested.seconds lease_utilization = 0 for res in lease.requested_resources.values(): for i in range(1,res.get_ninstances("CPU") + 1): lease_utilization += (res.get_quantity_instance("CPU", i) / 100.0) * duration accum_utilization += lease_utilization time = TimeDelta(seconds=0) avg_interval = int(last_request.seconds / len(leases)) for l in leases: interval = avg_interval + TimeDelta(seconds=self._get_interval()) time = max(time + interval, TimeDelta(seconds=0)) arrival = max(time - l.start.requested, TimeDelta(seconds=0)) l.start.requested = time lease_request = ET.SubElement(requests, "lease-request") lease_request.set("arrival", str(arrival)) lease_request.append(l.to_xml()) tree = ET.ElementTree(lwf) outfile = open(self.outfile, "w") tree.write(outfile) outfile.close()