def __init__(self, resourceSpec, configurationManager, stats): self.initialization(resourceSpec,configurationManager) self.connectToCloud() if self.instancesFileExists(): self.loadInstancesFromFile(self.runningInstancesFile) self.profiler.mark("wait_for_all_instances_to_get_running") # Run this specific image self.runInstances(configurationManager.getKeyPairFile()) self.profiler.elapsed("wait_for_all_instances_to_get_running") self.calcNumOfComputingUnits() print "NUMBER OF INSTANCES=",len(self.vmInstances.values()) self.resourceSelectionPolicy = SequentialResourceSelectionPolicy(self.vmInstances.values()) # self.resourceSelectionPolicy = LoadBalancingResourceSelectionPolicy(self.vmInstances.values()) # self.resourceSelectionPolicy = PredictiveResourceSelectionPolicy(self.instances) print "Using policy " + self.resourceSelectionPolicy.getName() self.stats = stats
class ResourceManager: #=============================================================================== # BIG: c1.xlarge, c1.medium, m1.large, m1.xlarge # # IMAGE ami-36ff1a5f # ec2-public-images/fedora-core6-base-x86_64.manifest.xml amazon # available public x86_64 machine # # # non-64 bit: m1.small # # IMAGE ami-2bb65342 ec2-public-images/getting-started.manifest.xml # amazon available public i386 machine #=============================================================================== INSTANCE_FILE_NAME = './instances.in' def __init__(self, resourceSpec, configurationManager, stats): self.initialization(resourceSpec,configurationManager) self.connectToCloud() if self.instancesFileExists(): self.loadInstancesFromFile(self.runningInstancesFile) self.profiler.mark("wait_for_all_instances_to_get_running") # Run this specific image self.runInstances(configurationManager.getKeyPairFile()) self.profiler.elapsed("wait_for_all_instances_to_get_running") self.calcNumOfComputingUnits() print "NUMBER OF INSTANCES=",len(self.vmInstances.values()) self.resourceSelectionPolicy = SequentialResourceSelectionPolicy(self.vmInstances.values()) # self.resourceSelectionPolicy = LoadBalancingResourceSelectionPolicy(self.vmInstances.values()) # self.resourceSelectionPolicy = PredictiveResourceSelectionPolicy(self.instances) print "Using policy " + self.resourceSelectionPolicy.getName() self.stats = stats def initialization(self,resourceSpec,configurationManager): self.profiler = Timing.timeprofile() self.profiler.mark("resource_mng_connect") self.configurationManager = configurationManager self.keyPairFile = configurationManager.getKeyPairFile() self.VmInstanceUser = configurationManager.getVmInstanceUser() logging.debug("Private key file is %s" % self.keyPairFile) self.buildResourceSpec(resourceSpec) # Connect to Amazon EC2 self.AWS_ACCESS_KEY_ID = configurationManager.getEC2AccessKeyId() self.AWS_SECRET_ACCESS_KEY = configurationManager.getEC2SecretAccessKey() logging.debug("Checking validity of private key %s." % self.keyPairFile) key= paramiko.RSAKey(None, None,self.keyPairFile,'', None, None) self.instances = [] self.vmInstancesList = [] self.vmInstances = {} self.runningInstancesDic = { 'm1.small':0, 'c1.medium':0,'m1.large':0,'m1.xlarge':0,'c1.xlarge':0 } self.runningInstancesFile = configurationManager.getRunningInstancesFile() self.instanceWriteCount = 1 def instancesFileExists(self): if self.runningInstancesFile is None: return False if not os.path.exists(self.runningInstancesFile): return False return True def calcNumOfComputingUnits(self): self._totalComputingUnits = 0 for vm in self.vmInstances.values(): self._totalComputingUnits += vm.getNumberOfComputingUnits() def getNumberOfComputingUnits(self): return self._totalComputingUnits def connectToCloud(self): cloudName = self.configurationManager.getCloudName() if cloudName == 'Amazon': self.connectToAmazonEC2() elif cloudName == "Eucalyptus": self.connectToEucalyptus() elif cloudName == "OpenNebula": self.connectToOpenNebula() else: print "ERROR: Wrong Cloud name: {0}".format(cloudName) self.profiler.elapsed("resource_mng_connect") self.profiler.mark("resource_mng_change_region") self.profiler.mark("resource_mng_get_images") def connectToAmazonEC2(self): print "Connecting to Amazon EC2:" self.EC2Connection = boto.ec2.connect_to_region(self.configurationManager.getCloudRegion(), aws_access_key_id=self.AWS_ACCESS_KEY_ID, aws_secret_access_key=self.AWS_SECRET_ACCESS_KEY) def connectToEucalyptus(self): region=boto.ec2.regioninfo.RegionInfo(name=self.configurationManager.getCloudRegion(),endpoint=self.configurationManager.getCloudUrl()) print "Connecting to Eucalyptus Cloud: " self.EC2Connection = EC2Connection(aws_access_key_id=self.AWS_ACCESS_KEY_ID, aws_secret_access_key=self.AWS_SECRET_ACCESS_KEY, is_secure=False, region=region, port=self.configurationManager.getCloudPort(), path="/services/Eucalyptus") def connectToOpenNebula(self): self.EC2Connection = xmlrpclib.ServerProxy('http://localhost:2633/RPC2') ########################################### # Construct specification of resources, based on a # comma-separated list of "attribute=value" ########################################### def buildResourceSpec(self, resSpecString): listOfStrings = resSpecString.split(',') self.resourceList = [] for rspec in listOfStrings: instanceType, instanceCount = rspec.split('=') self.resourceList.append((instanceType,int(instanceCount))) ########################################## # Build a DICTIONARY (not a list) of all the # available images on Amazon EC2 ########################################### def buildAmiDict(self): """ Build a dictionary of all the available images on EC2 """ print "\tRetrieving all available images..." images = self.EC2Connection.get_all_images() self.profiler.elapsed("resource_mng_get_images") amiDict={} for image in images: if image.id.count("emi") > 0 or image.id.count("ami") > 0: amiDict[image.id] = image return amiDict[self.configurationManager.getVMImage()] ########################################### # Run "image" on all the resources that # are described in the resource list ########################################### def runInstances(self, keypair): cloudName = self.configurationManager.getCloudName() keypairBase = self.getKeypairBasename(keypair) if cloudName == 'Amazon' or cloudName == "Eucalyptus": self.runEC2Instances(keypairBase) elif cloudName == "OpenNebula": self.runOneInstances() self.waitUntilAllInstancesAreRunning() self.constructInstancesByDNSNameDict() def constructInstancesByDNSNameDict(self): for instance in self.vmInstancesList: print "Adding INSTANCE:",instance.getDNSName() self.vmInstances[instance.getDNSName()] = instance def getKeypairBasename(self,keypair): # keep only the basename, remove absolute path keypairBasename=os.path.basename(keypair) if '.priv' in keypairBasename or '.pem' in keypairBasename: keypairBasename=keypairBasename.split('.')[0] return keypairBasename def runEC2Instances(self, keypair_base): image = self.buildAmiDict() self.reservations = [] for instanceType,instanceCount in self.resourceList: if instanceCount > self.runningInstancesDic[instanceType]: instanceCount -= self.runningInstancesDic[instanceType] if instanceCount > 0: print "\tRunning image ",image," on ", instanceCount," instances of type ",instanceType instancesReserved = image.run(instanceCount, instanceCount, key_name = keypair_base, instance_type=instanceType) self.instances += instancesReserved.instances # merge all instances into self.instances self.reservations.append(instancesReserved) for instance in self.instances: vmInstance = VMInstance.EC2Instance(instance, self.configurationManager) self.vmInstancesList.append(vmInstance) def runOneInstances(self): image = self.configurationManager.getVMImage() for instanceType,instanceCount in self.resourceList: if instanceCount > self.runningInstancesDic[instanceType]: instanceCount -= self.runningInstancesDic[instanceType] if instanceCount > 0: print "\tRunning image ",image," on ", instanceCount," instances of type ",instanceType for i in range(instanceCount): vmInstance = VMInstance.OneInstance(self.configurationManager,self.EC2Connection) vmInstance.run(image) self.vmInstancesList.append(vmInstance) def waitUntilAllInstancesAreRunning(self): print "\tWaiting for instances to boot:" sshOverhead = self.connectToInstances() print "\tDone booting" self.profiler.timedict["wait_for_all_instances_to_get_running_ssh_overhead"]= sshOverhead def connectToInstances(self): connected = [False for i in range(len(self.vmInstancesList))] sshOverhead = 0 while True: instanceList = self.vmInstancesList for i in range(len(instanceList)): if connected[i] is True: continue start = time.time() connected[i] = instanceList[i].connect() end = time.time() sshOverhead += (end-start) if reduce(operator.and_, connected) is True: break return sshOverhead def terminateAllInstances(self): self.profiler.mark("wait_for_all_instances_to_get_terminated") print "!STATUS: Terminating all instances...", for resv in self.reservations: resv.stop_all() self.waitUntilAllInstancesAreStopped() print "DONE" self.profiler.elapsed("wait_for_all_instances_to_get_terminated") def waitUntilAllInstancesAreStopped(self): allInstances = len(self.instances) boolList = [] # holds the flags whether the instances are running for i in range(allInstances): boolList.append(False) while True: for j in range(allInstances): instance = self.instances[j] if instance.state != 'terminated': instance.update() time.sleep(0.2) else: # running boolList[j] = True if self.allTrue(boolList) == True: break def loadInstancesFromFile(self,fileName): instanceFileReader = ConfigurationManager.InstanceFileReader(self.configurationManager) vmInstances = instanceFileReader.getVMInstancesFromFile(fileName) for instance in vmInstances: self.runningInstancesDic[instance.getType()] += 1 self.instances.append(instance.toEC2Instance()) self.vmInstancesList.append(instance) print "Created {0} instances from file...".format(len(self.vmInstancesList)) def dumpAllInstances(self): allReservations = self.EC2Connection.get_all_instances() for reservation in allReservations: for instance in reservation.instances: print instance.id + " -> " +instance.state def getNextAvailableInstance(self): # return (nextInstance.dns_name, nextInstance.id) return self.resourceSelectionPolicy.getNextResource() def getIdleInstance(self): for instance in self.vmInstances.values(): print "Number of jobs in instance {0} : {1}".format(instance.getID(),instance.getNumExecutingJobs()) if instance.getNumExecutingJobs() == 0: return instance return None def decreaseAwaitingJobs(self,instanceDNS): instance = self.vmInstances[instanceDNS] instance.decreaseNumExecutingJobs() return instance.getNumExecutingJobs() def updateResourcePolicyStatus(self, instanceId, status): try: self.resourceSelectionPolicy.updateResourceState(instanceId,status) except: #The updateResourcePolicyStatus is not made available with the chosen ResourcePolicy pass def submitStatistics(self): self.stats.addToTotalResourceManagerConnectTime(self.profiler.getValue('resource_mng_connect')) self.stats.addToTotalResourceManagerGetListOfImagesTime(self.profiler.getValue('resource_mng_get_images')) self.stats.addToTotalResourceReservationTime(self.profiler.getValue('wait_for_all_instances_to_get_running')) self.stats.addTotalSshOverheadWhilePollingIfResourcesAreRunning(self.profiler.getValue('wait_for_all_instances_to_get_running_ssh_overhead')) # self.stats.addToTotalResourceReleaseTime(self.profiler.getValue('wait_for_all_instances_to_get_terminated')) def writeInstancesToFile(self): fileName = self.runningInstancesFile if fileName is None: fileName = ResourceManager.INSTANCE_FILE_NAME inFile = open(fileName,'w') for instance in self.vmInstances.values(): self.writeInstance(instance,inFile) inFile.close() def writeInstance(self,instance,file): file.write("[Instance{0}]\n".format(self.instanceWriteCount)) file.write("ip_address = {0}\n".format(instance.getIPAddress())) file.write("dns_name = {0}\n".format(instance.getDNSName())) file.write("id = {0}\n".format(instance.getID())) file.write("image_id = {0}\n".format(instance.getImageID())) file.write("type = {0}\n\n".format(instance.getType())) self.instanceWriteCount += 1