def power_on(self): """ Switches electricity on """ regionId = self.get_setting('regionId') host = self.get_setting('apiHost') locationId = self.get_setting('locationId') try: if self.region is None: logging.debug("Getting driver for '%s / %s'", regionId, host) self.region = self.plumbery.get_compute_driver( region=regionId, host=host) self.backup = self.plumbery.get_backup_driver( region=regionId, host=host) if os.getenv('LIBCLOUD_HTTP_PROXY') is not None: logging.debug('Setting proxy to %s' % (os.getenv('LIBCLOUD_HTTP_PROXY'))) self.region.connection.set_http_proxy( proxy_url=os.getenv('LIBCLOUD_HTTP_PROXY')) self.backup.connection.set_http_proxy( proxy_url=os.getenv('LIBCLOUD_HTTP_PROXY')) logging.debug('Disabling SSL verification') import libcloud.security libcloud.security.VERIFY_SSL_CERT = False if self.location is None: logging.debug("Getting location '{}'".format(locationId)) locations = [] for location in self.region.list_locations(): locations.append(location.id) if location.id == locationId: self.location = location if self.location is None: logging.info("Known locations: {}".format(locations)) raise PlumberyException("Unknown location '{}' in '{}'" .format(locationId, regionId)) except ValueError: raise PlumberyException("Unknown region '{}'" .format(regionId)) except socket.gaierror: raise PlumberyException("Cannot communicate with the API endpoint")
def get_user_password(self): """ Retrieves user password to authenticate to the API :return: the user password to be used with the driver :rtype: ``str`` :raises: :class:`plumbery.PlumberyException` - if no user password can be found The user password is not put in the fittings plan, but is normally taken from the environment variable ``MCP_PASSWORD``. Under Linux, you may want to edit ``~/.bash_profile`` like this:: # credentials to access cloud resources from Dimension Data export MCP_USERNAME='******' export MCP_PASSWORD='******' """ if self._userPassword is None: self._userPassword = os.getenv('MCP_PASSWORD') if self._userPassword is None or len(self._userPassword) < 3: raise PlumberyException( "Error: missing credentials in environment MCP_PASSWORD") return self._userPassword
def get_shared_secret(self): """ Retrieves the secret that is communicated to new nodes during setup :return: the shared secret to be given to the driver :rtype: ``str`` :raises: :class:`plumbery.PlumberyException` - if no shared secret can be found The shared secret is not put in the fittings plan, but is normally taken from the environment variable ``SHARED_SECRET``. Under Linux, you may want to edit ``~/.bash_profile`` like this:: # password to access nodes remotely export SHARED_SECRET='*you really want to use a tricky password*' Alternatively, you can use the member function ``set_shared_secret()`` to set this important attribute via code. """ if self._sharedSecret is None: self._sharedSecret = os.getenv('SHARED_SECRET') if self._sharedSecret is None or len(self._sharedSecret) < 3: raise PlumberyException( "Error: missing node password in environment SHARED_SECRET" ) return self._sharedSecret
def from_shelf(cls, polishId, settings={}): """ Picks up a polisher from the shelf :param polishId: name of the polisher to use, e.g., ``inventory`` :type polishId: ``str`` :param settings: specific settings for this polisher :type param: ``dict`` :return: instance of a polisher ready to use :rtype: :class:`plumbery.PlumberyPolisher` :raises: :class:`plumbery.PlumberyException` if no polisher can be found """ try: settings['name'] = polishId moduleName = 'polishers.' + polishId polisherName = polishId.capitalize() + 'Polisher' polisherModule = __import__(moduleName, globals(), locals(), [polisherName]) polisherClass = getattr(polisherModule, polisherName) return polisherClass(settings) except Exception as feedback: raise PlumberyException( "Error: unable to load polisher '{0}' {1}!".format( polishId, feedback)) raise PlumberyException( "Error: unable to find polisher '{0}'!".format(polishId))
def power_on(self): """ Switches electricity on """ try: if self.region is None: self.region = self.plumbery.get_compute_driver( region=self.fittings.regionId) if self.location is None: self.location = self.region.ex_get_location_by_id( self.fittings.locationId) except socket.gaierror: raise PlumberyException("Cannot communicate with the API endpoint")
def build_blueprint(self, blueprint, container): """ Create missing nodes :param blueprint: the blueprint to build :type blueprint: ``dict`` :param container: the container where nodes will be built :type container: :class:`plumbery.PlumberyInfrastructure` """ self.facility.power_on() if 'nodes' not in blueprint or not isinstance(blueprint['nodes'], list): logging.info("No nodes have been defined") return for item in blueprint['nodes']: if type(item) is dict: label = item.keys()[0] settings = item.values()[0] else: label = item settings = {} for label in self.expand_labels(label): if self.get_node(label): logging.info("Creating node '{}'".format(label)) logging.info("- already there") continue description = '#plumbery' if 'description' in settings: description = settings['description'] + ' #plumbery' if 'appliance' in settings: imageName = settings['appliance'] else: imageName = 'Ubuntu' # if 'cpu' in settings: # tokens = settings['cpu'].split(' ') # if len(tokens) < 3: # tokens.append('1') # tokens.append('STANDARD') # # cpu = DimensionDataServerCpuSpecification( # cpu_count=tokens[0], # cores_per_socket=tokens[1], # performance=tokens[2]) # else: # cpu = None if 'memory' in settings: memory = settings['memory'] else: memory = None image = self.facility.get_image(imageName) if image is None: raise PlumberyException("Error: unable to find image " "for '{}'!".format(imageName)) logging.info("Creating node '{}'".format(label)) if self.plumbery.safeMode: logging.info("- not in safe mode") continue if container.domain is None: logging.info("- missing network domain") continue if container.network is None: logging.info("- missing Ethernet network") continue while True: try: self.region.create_node( name=label, image=image, auth=NodeAuthPassword( self.plumbery.get_shared_secret()), ex_network_domain=container.domain, ex_vlan=container.network, # ex_cpu_specification=cpu, # ex_memory_gb=memory, ex_is_started=False, ex_description=description) logging.info("- in progress") except Exception as feedback: if 'RESOURCE_BUSY' in str(feedback): time.sleep(10) continue elif 'RESOURCE_NOT_FOUND' in str(feedback): logging.info("- not now") logging.error(str(feedback)) elif 'RESOURCE_LOCKED' in str(feedback): logging.info("- not now - locked") logging.error(str(feedback)) else: logging.info("- unable to create node") logging.error(str(feedback)) break
def build_blueprint(self, blueprint, container): """ Create missing nodes :param blueprint: the blueprint to build :type blueprint: ``dict`` :param container: the container where nodes will be built :type container: :class:`plumbery.PlumberyInfrastructure` """ logging.debug("Building nodes of blueprint '{}'".format( blueprint['target'])) self.facility.power_on() if ('nodes' not in blueprint or not isinstance(blueprint['nodes'], list)): logging.info("No nodes have been defined") return for item in blueprint['nodes']: if type(item) is dict: label = item.keys()[0] settings = item.values()[0] else: label = item settings = {} for label in self.expand_labels(label): logging.info("Creating node '{}'".format(label)) if self.get_node(label): logging.info("- already there") continue description = '#plumbery' if 'description' in settings: description = settings['description'] + ' #plumbery' if 'appliance' in settings: imageName = settings['appliance'] else: imageName = None image = self.facility.get_image(imageName) if image is None: raise PlumberyException("Error: unable to find image " "for '{}'!".format(imageName)) logging.debug("- using image '{}'".format(image.name)) cpu = None if 'cpu' in settings: tokens = str(settings['cpu']).split(' ') if len(tokens) < 2: tokens.append('1') if len(tokens) < 3: tokens.append('standard') if (int(tokens[0]) < 1 or int(tokens[0]) > 32): logging.info("- cpu should be between 1 and 32") elif (int(tokens[1]) < 1 or int(tokens[1]) > 2): logging.info("- core per cpu should be either 1 or 2") elif tokens[2].upper() not in ('STANDARD', 'HIGHPERFORMANCE'): logging.info("- cpu speed should be either 'standard'" " or 'highspeed'") else: cpu = DimensionDataServerCpuSpecification( cpu_count=tokens[0], cores_per_socket=tokens[1], performance=tokens[2].upper()) logging.debug("- assigning {} cpus".format( cpu.cpu_count)) logging.debug("- core per cpu: {}".format( cpu.cores_per_socket)) logging.debug("- cpu performance: {}".format( cpu.performance.lower())) memory = None if 'memory' in settings: memory = int(settings['memory']) if memory < 1 or memory > 256: logging.info("- memory should be between 1 and 256") memory = None else: logging.debug( "- assigning {} GB of memory".format(memory)) if self.plumbery.safeMode: logging.info("- skipped - safe mode") continue if container.domain is None: logging.info("- missing network domain") continue if container.network is None: logging.info("- missing Ethernet network") continue while True: try: self.region.create_node( name=label, image=image, auth=NodeAuthPassword( self.plumbery.get_shared_secret()), ex_network_domain=container.domain, ex_vlan=container.network, ex_cpu_specification=cpu, ex_memory_gb=memory, ex_is_started=False, ex_description=description) logging.info("- in progress") except Exception as feedback: if 'RESOURCE_BUSY' in str(feedback): time.sleep(10) continue elif 'RESOURCE_NOT_FOUND' in str(feedback): logging.info("- not now") logging.error(str(feedback)) elif 'RESOURCE_LOCKED' in str(feedback): logging.info("- not now - locked") logging.error(str(feedback)) else: logging.info("- unable to create node") logging.error(str(feedback)) break