Example #1
0
    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")
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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))
Example #5
0
    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")
Example #6
0
    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
Example #7
0
    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