def create_VMInstance( self, vmdiracInstanceID, runningPodRequirements ): """ This creates a VM instance for the given boot image and creates a context script, taken the given parameters. Successful creation returns instance VM Boots a new node on the OpenStack server defined by self.endpointConfig. The 'personality' of the node is done by self.imageConfig. Both variables are defined on initialization phase. The node name has the following format: <bootImageName><contextMethod><time> It boots the node. If IPpool is defined on the imageConfiguration, a floating IP is created and assigned to the node. :return: S_OK( ( nodeID, publicIP ) ) | S_ERROR """ # Common Image Attributes bootImageName = self.imageConfig[ 'bootImageName' ] flavorName = self.imageConfig[ 'flavorName' ] contextMethod = self.imageConfig[ 'contextMethod' ] cloudDriver = self.endpointConfig[ 'cloudDriver' ] vmPolicy = self.endpointConfig[ 'vmPolicy' ] vmStopPolicy = self.endpointConfig[ 'vmStopPolicy' ] siteName = self.endpointConfig[ 'siteName' ] # Optional node contextualization parameters userdata = self.imageConfig[ 'contextConfig' ].get( 'ex_userdata', None ) metadata = self.imageConfig[ 'contextConfig' ].get( 'ex_metadata', {} ) secGroup = self.imageConfig[ 'contextConfig' ].get( 'ex_security_groups', None ) keyname = self.imageConfig[ 'contextConfig' ].get( 'ex_keyname' , None ) pubkeyPath = self.imageConfig[ 'contextConfig' ].get( 'ex_pubkey_path' , None ) if userdata is not None: with open( userdata, 'r' ) as userDataFile: userdata = ''.join( userDataFile.readlines() ) bootImage = self.get_image( bootImageName ) if not bootImage[ 'OK' ]: self.log.error( bootImage[ 'Message' ] ) return bootImage bootImage = bootImage[ 'Value' ] flavor = self.get_flavor( flavorName ) if not flavor[ 'OK' ]: self.log.error( flavor[ 'Message' ] ) return flavor flavor = flavor[ 'Value' ] secGroupRes = self.get_security_groups( secGroup ) if not secGroupRes[ 'OK' ]: self.log.error( secGroupRes[ 'Message' ] ) return secGroupRes secGroup = secGroupRes[ 'Value' ] vm_name = 'DIRAC' + contextMethod + str( time.time() )[0:10] # keypair management is not available in libcloud openstack, jet. # https://issues.apache.org/jira/browse/LIBCLOUD-392 # open pull request(10/09/2013): https://github.com/apache/libcloud/pull/145 # this was the equivalent with nova client: #if pubkeyPath: # try: # with open(os.path.expanduser(pubkeyPath)) as f: # pub_key = f.read() # except Exception, errmsg: # return S_ERROR( errmsg ) # keypairs = pynovaclient.keypairs.list() # existkey = False # for keypair in keypairs: # if keypair.name == ex_keyname: # self.log.info( "ex_keyname exist, do nothing for keypairs" ) # existkey = True # # if existkey == False: # keypair = self.__pynovaclient.keypairs.create(keyname,pub_key) # from here, keyname has to be previouslly created to be injected in the /root/.ssh/authorized_keys of the VM self.log.info( "Creating node" ) self.log.verbose( "name : %s" % vm_name ) self.log.verbose( "image : %s" % bootImage ) self.log.verbose( "size : %s" % flavor ) # mandatory for amiconfig, checked at Context.py self.log.verbose( "ex_userdata : %s" % userdata ) self.log.verbose( "ex_metadata : %s" % metadata ) # mandatory for ssh, checked at Context.py self.log.verbose( "ex_keyname : %s" % keyname ) self.log.verbose( "ex_pubkey_path : %s" % pubkeyPath ) try: if contextMethod == 'cloudinit': cloudinitScript = BuildCloudinitScript(); result = cloudinitScript.buildCloudinitScript(self.imageConfig, self.endpointConfig, runningPodRequirements = runningPodRequirements) if not result[ 'OK' ]: return result composedUserdataPath = result[ 'Value' ] self.log.info( "cloudinitScript : %s" % composedUserdataPath ) with open( composedUserdataPath, 'r' ) as userDataFile: userdata = ''.join( userDataFile.readlines() ) vmNode = self.__driver.create_node( name = vm_name, image = bootImage, size = flavor, ex_userdata = userdata, ex_security_groups = secGroup) elif contextMethod == 'amiconfig': vmNode = self.__driver.create_node( name = vm_name, image = bootImage, size = flavor, ex_keyname = keyname, ex_userdata = userdata, ex_security_groups = secGroup, ex_metadata = metadata ) else: # contextMethod ssh or adhoc vmNode = self.__driver.create_node( name = vm_name, image = bootImage, size = flavor ) # the libcloud library, throws Exception. Nothing to do. except Exception, errmsg: return S_ERROR( errmsg )
def create_VMInstance(self, cpuTime = None, submitPool = None, runningPodRequirements = None, instanceID = None): """ This creates a VM instance for the given boot image if context method is adhoc then boot image is create to be in Submitted status if context method is ssh then boot image is created to be in Wait_ssh_context (for contextualization agent) if context method is occi_opennebula context is in hdc image, and also de OCCI context on-the-fly image, taken the given parameters Successful creation returns instance id and the IP BTM: submitPool is not used, since rOCCI only has ssh contextualization, then used at this point. It is here by compatibility with OCCI 0.8 call """ # TODO: cpuTime is here to implement HEPiX when ready with rOCCI #Comming from running pod specific: #self.__strCpuTime = str(cpuTime) #DIRAC image context: # bootImageName is in current rOCCI driver the OS template osTemplateName = self.imageConfig[ 'bootImageName' ] flavorName = self.imageConfig[ 'flavorName' ] contextMethod = self.imageConfig[ 'contextMethod' ] if not ( contextMethod == 'ssh' or contextMethod == 'cloudinit'): self.__errorStatus = "Current rOcci DIRAC driver suports cotextMethod: ssh, cloudinit " self.log.error( self.__errorStatus ) return occiURI = self.endpointConfig[ 'occiURI' ] vmName = osTemplateName + '_' + contextMethod + '_' + str( time.time() )[0:10] if flavorName != 'nouse': flavorArg = ' --mixin resource_tpl#' + flavorName + ' ' else: flavorArg = ' ' request = Request() if contextMethod == 'cloudinit': cloudinitScript = BuildCloudinitScript(); result = cloudinitScript.buildCloudinitScript(self.imageConfig, self.endpointConfig, runningPodRequirements = runningPodRequirements, instanceID = instanceID) if not result[ 'OK' ]: return result composedUserdataPath = result[ 'Value' ] self.log.info( "cloudinitScript : %s" % composedUserdataPath ) # with open( composedUserdataPath, 'r' ) as userDataFile: # userdata = ''.join( userDataFile.readlines() ) command = 'occi --endpoint ' + occiURI + ' --action create --resource compute --mixin os_tpl#' + osTemplateName + flavorArg + ' --attribute occi.core.title="' + vmName + '" --output-format json ' + self.__authArg + ' --context user_data="file://%s"' % composedUserdataPath # command = 'occi --endpoint ' + occiURI + ' --action create --resource compute --mixin os_tpl#' + osTemplateName + flavorArg + ' --attribute occi.core.title="' + vmName + '" --output-format json ' + self.__authArg + ' --context user_data="%s"' % userdata else: command = 'occi --endpoint ' + occiURI + ' --action create --resource compute --mixin os_tpl#' + osTemplateName + flavorArg + ' --attribute occi.core.title="' + vmName + '" --output-format json ' + self.__authArg request.exec_no_wait(command) print "command " print command if request.stdout == "nil": request.returncode = 1 return request if contextMethod == 'cloudinit': os.remove( composedUserdataPath ) # FIXME use simplejson, filtering non-json output lines searchstr = occiURI + '/compute/' first = request.stdout.find(searchstr) if first < 0: request.returncode = 1 return request #first += len(searchstr) #last = len(request.stdout) iD = request.stdout publicIP = ' ' if contextMethod == 'ssh': #then need the public IP # giving time sleep to REST API caching the instance to be available: time.sleep( 5 ) command = 'occi --endpoint ' + occiURI + ' --action describe --resource ' + iD + ' ' + self.__authArg + ' --output-format json_extended' request.exec_and_wait(command) infoDict = simplejson.loads(request.stdout) try: publicIP = infoDict[0]['links'][1]['attributes']['occi']['networkinterface']['address'] except Exception as e: self.log.error( 'The description of %s does not include the ip address: ' % iD, e ) request.returncode = 1 return request request.returncode = 0 request.stdout = iD + ', ' + publicIP return request
if not self.__vmImage: try: self.__vmImage = self.__conn.get_image( AMI ) except EC2ResponseError, e: if e.status == 400: errmsg = "boto connection problem! Check connection properties." else: errmsg = "boto exception: " self.log.error( errmsg ) return S_ERROR( errmsg+e.body) if contextMethod == 'cloudinit': cloudinitScript = BuildCloudinitScript(); result = cloudinitScript.buildCloudinitScript(self.imageConfig, self.endpointConfig, runningPodRequirements = runningPodRequirements) if not result[ 'OK' ]: return result composedUserdataPath = result[ 'Value' ] self.log.info( "cloudinitScript : %s" % composedUserdataPath ) with open( composedUserdataPath, 'r' ) as userDataFile: userdata = ''.join( userDataFile.readlines() ) os.remove( composedUserdataPath ) if maxAllowedPrice is None: maxAllowedPrice = 0 if maxAllowedPrice == 0: self.log.info( "Requesting normal instances" ) self.log.info( "Starting new instance for AMI %s (type %s)" % (