X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Fmanagers%2Faggregate_manager_eucalyptus.py;h=e62381a12470b493aa8db2a36ad27fcd4e0b8ed1;hb=52b4cb21f33f380f55d467709b1b9bc8ba84bd57;hp=5a0cd4555240a8315f8304b4021c4154b0bc55a1;hpb=eda5336d9f85cb811a2434552e7649e08c3e99c7;p=sfa.git diff --git a/sfa/managers/aggregate_manager_eucalyptus.py b/sfa/managers/aggregate_manager_eucalyptus.py index 5a0cd455..e62381a1 100644 --- a/sfa/managers/aggregate_manager_eucalyptus.py +++ b/sfa/managers/aggregate_manager_eucalyptus.py @@ -88,7 +88,7 @@ def init_server(): configParser.read(['/etc/sfa/eucalyptus_aggregate.conf', 'eucalyptus_aggregate.conf']) if len(configParser.sections()) < 1: print >>sys.stderr, 'No cloud defined in the config file' - raise 'Cannot find cloud definition in configuration file.' + raise Exception('Cannot find cloud definition in configuration file.') # Only read the first section. cloudSec = configParser.sections()[0] @@ -173,7 +173,7 @@ class EucaRSpecBuilder(object): # @param cloud A dictionary containing data about a # cloud (ex. clusters, ip) def __init__(self, cloud): - self.eucaRSpec = XMLBuilder() + self.eucaRSpec = XMLBuilder(format = True, tab_step = " ") self.cloudInfo = cloud ## @@ -209,7 +209,9 @@ class EucaRSpecBuilder(object): # @param clusters Clusters information. # def __clustersXML(self, clusters): + cloud = self.cloudInfo xml = self.eucaRSpec + for cluster in clusters: instances = cluster['instances'] with xml.cluster(id=cluster['name']): @@ -230,7 +232,17 @@ class EucaRSpecBuilder(object): xml << str(inst[5]) if inst[0] == 'm1.small': self.__requestXML(1, 'emi-88760F45', 'eki-F26610C6', 'cortex') - + if 'instances' in cloud and inst[0] in cloud['instances']: + existingEucaInstances = cloud['instances'][inst[0]] + with xml.euca_instances: + for eucaInst in existingEucaInstances: + with xml.euca_instance(id=eucaInst['id']): + with xml.state: + xml << eucaInst['state'] + with xml.public_dns: + xml << eucaInst['public_dns'] + with xml.keypair: + xml << eucaInst['key'] ## # Creates the Images stanza. @@ -345,6 +357,41 @@ def get_rspec(api, xrn, origin_hrn): # Key Pairs keyPairs = conn.get_all_key_pairs() cloud['keypairs'] = keyPairs + + if hrn: + instanceId = [] + instances = [] + + # Get the instances that belong to the given slice from sqlite3 + # XXX use getOne() in production because the slice's hrn is supposed + # to be unique. For testing, uniqueness is turned off in the db. + theSlice = list(Slice.select(Slice.q.slice_hrn == hrn))[-1] + for instance in theSlice.instances: + instanceId.append(instance.instance_id) + + # Get the information about those instances using their ids. + if len(instanceId) > 0: + reservations = conn.get_all_instances(instanceId) + else: + reservations = [] + for reservation in reservations: + for instance in reservation.instances: + instances.append(instance) + + # Construct a dictory for the EucaRSpecBuilder + instancesDict = {} + for instance in instances: + instList = instancesDict.setdefault(instance.instance_type, []) + instInfoDict = {} + + instInfoDict['id'] = instance.id + instInfoDict['public_dns'] = instance.public_dns_name + instInfoDict['state'] = instance.state + instInfoDict['key'] = instance.key_name + + instList.append(instInfoDict) + cloud['instances'] = instancesDict + except EC2ResponseError, ec2RespErr: errTree = ET.fromstring(ec2RespErr.body) errMsgE = errTree.find('.//Message') @@ -352,6 +399,11 @@ def get_rspec(api, xrn, origin_hrn): rspec = EucaRSpecBuilder(cloud).toXML() + # Remove the instances records so next time they won't + # show up. + if 'instances' in cloud: + del cloud['instances'] + return rspec """ @@ -366,12 +418,6 @@ def create_slice(api, xrn, xml): print >>sys.stderr, 'Error: Cannot create a connection to Eucalyptus' return False - # Get the slice from db or create one. - # XXX: For testing purposes, I'll just create the slice. - #s = Slice.select(Slice.q.slice_hrn == hrn).getOne(None) - #if s is None: - s = Slice(slice_hrn = hrn) - # Validate RSpec schemaXML = ET.parse(EUCALYPTUS_RSPEC_SCHEMA) rspecValidator = ET.RelaxNG(schemaXML) @@ -379,9 +425,31 @@ def create_slice(api, xrn, xml): if not rspecValidator(rspecXML): error = rspecValidator.error_log.last_error message = '%s (line %s)' % (error.message, error.line) + # XXX: InvalidRSpec is new. Currently, I am not working with Trunk code. + #raise InvalidRSpec(message) raise Exception(message) - # Process the RSpec + # Get the slice from db or create one. + s = Slice.select(Slice.q.slice_hrn == hrn).getOne(None) + if s is None: + s = Slice(slice_hrn = hrn) + + # Process any changes in existing instance allocation + pendingRmInst = [] + for sliceInst in s.instances: + pendingRmInst.append(sliceInst.instance_id) + existingInstGroup = rspecXML.findall('.//euca_instances') + for instGroup in existingInstGroup: + for existingInst in instGroup: + if existingInst.get('id') in pendingRmInst: + pendingRmInst.remove(existingInst.get('id')) + for inst in pendingRmInst: + print >>sys.stderr, 'Instance %s will be terminated' % inst + dbInst = EucaInstance.select(EucaInstance.q.instance_id == inst).getOne(None) + dbInst.destroySelf() + conn.terminate_instances(pendingRmInst) + + # Process new instance requests requests = rspecXML.findall('.//request') for req in requests: vmTypeElement = req.getparent() @@ -418,7 +486,7 @@ def main(): theRSpec = xml.read() create_slice(None, 'planetcloud.pc.test', theRSpec) - #rspec = get_rspec('euca', 'hrn:euca', 'oring_hrn') + #rspec = get_rspec('euca', 'planetcloud.pc.test', 'planetcloud.pc.marcoy') #print rspec if __name__ == "__main__":