""" OpenNebula Endpoint base class implementation for the OpenNebula cloud service. """ from __future__ import print_function from __future__ import division from __future__ import absolute_import __RCSID__ = "$Id" import os import base64 import ssl from requests.auth import HTTPBasicAuth try: from xmlrpc.client import ServerProxy except ImportError: # python2 compat from xmlrpclib import ServerProxy # DIRAC from DIRAC import gLogger, S_OK, S_ERROR from DIRAC.Resources.Cloud.Endpoint import Endpoint from DIRAC.Core.Utilities.File import makeGuid DEBUG = False # In case of debugging, switch class OpenNebulaEndpoint(Endpoint): """ OpenNebula implementation of the Cloud Endpoint interface """ def __init__(self, parameters=None): super(OpenNebulaEndpoint, self).__init__( parameters=parameters, bootstrapParameters=parameters) self.parameters['HostCert'] = self.parameters.get("HostCert") self.parameters['HostKey'] = self.parameters.get("HostKey") self.bootstrapParameters['HostCert'] = self.parameters['HostCert'] self.bootstrapParameters['HostKey'] = self.parameters['HostKey'] self.log = gLogger.getSubLogger('OpenNebulaEndpoint') self.valid = False self.vmType = self.parameters.get('VMType') self.site = self.parameters.get('Site') # Prepare the authentication request parameters self.session = None self.authArgs = {} self.user = self.parameters.get("User") self.password = self.parameters.get("Password") self.loginMode = False if self.user and self.password: # we have the login/password case self.authArgs['auth'] = HTTPBasicAuth(self.user, self.password) self.authArgs['verify'] = False self.loginMode = True self.oneauth = self.user + ':' + self.password else: # we have the user proxy case # TODO: test self.userProxy = os.environ.get('X509_USER_PROXY') self.userProxy = self.parameters.get("Proxy", self.userProxy) if self.userProxy is None: self.log.error("User proxy is not defined") self.valid = False return self.authArgs['cert'] = self.userProxy self.caPath = self.parameters.get('CAPath') self.authArgs['verify'] = self.caPath if self.parameters.get("Auth") == "voms": self.authArgs['data'] = '{"auth":{"voms": true}}' self.serviceUrl = self.parameters.get('EndpointUrl') result = self.initialize() if result['OK']: self.log.debug('OpenNebulaEndpoint created and validated') self.valid = True def initialize(self): self.log.info('INITIALIZE') ssl_ctx = ssl.create_default_context() ssl_ctx.check_hostname = False ssl_ctx.verify_mode = ssl.CERT_NONE self.rpcproxy = ServerProxy(self.serviceUrl, context=ssl_ctx) return S_OK() def createInstances(self, vmsToSubmit): outputDict = {} message = '' self.log.debug("vmsToSubmit " + str(vmsToSubmit)) for nvm in range(vmsToSubmit): instanceID = makeGuid()[:8] createPublicIP = 'ipPool' in self.parameters result = self.createInstance(instanceID, createPublicIP) if result['OK']: nodeID, publicIP = result['Value'] self.log.debug( 'Created VM instance %s/%s with publicIP %s' % (nodeID, instanceID, publicIP)) nodeDict = {} nodeDict['PublicIP'] = publicIP nodeDict['InstanceID'] = instanceID nodeDict['NumberOfProcessors'] = self.parameters.get("NumberOfProcessors", 1) outputDict[nodeID] = nodeDict else: message = result['Message'] break # We failed submission utterly if not outputDict: return S_ERROR('No VM submitted: %s' % message) return S_OK(outputDict) def createInstance(self, instanceID='', createPublicIP=True): """ Creates VM in OpenNebula cloud. one.template.instantiate XML-RPC method is called with the following parameters 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. * template ID is obtained from Endpoint's `TemplateID` constructor parameter * VM name equals to `instanceID` method argument * onhold flag is obtained from Endpoint's `Onhold` constructor parameter * template string contains userdata scripts encoded in base64 and DNS servers adresses The node name has the following format: