Source code for cloudify.utils

########
# Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
#    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    * See the License for the specific language governing permissions and
#    * limitations under the License.

import logging
import random
import shlex
import string
import subprocess
import tempfile
import sys
import os

from cloudify.exceptions import CommandExecutionException
from cloudify.constants import LOCAL_IP_KEY, MANAGER_IP_KEY, \
    MANAGER_REST_PORT_KEY, MANAGER_FILE_SERVER_BLUEPRINTS_ROOT_URL_KEY, \
    MANAGER_FILE_SERVER_URL_KEY


def setup_logger(logger_name, logger_level=logging.DEBUG, handlers=None,
                 remove_existing_handlers=True):
    """
    :param logger_name: Name of the logger.
    :param logger_level: Level for the logger (not for specific handler).
    :param handlers: An optional list of handlers (formatter will be
                     overridden); If None, only a StreamHandler for
                     sys.stdout will be used.
    :param remove_existing_handlers: Determines whether to remove existing
                                     handlers before adding new ones
    :return: A logger instance.
    :rtype: Logger
    """

    logger = logging.getLogger(logger_name)

    if remove_existing_handlers:
        for handler in logger.handlers:
            logger.removeHandler(handler)

    if not handlers:
        handler = logging.StreamHandler(sys.stdout)
        handler.setLevel(logging.DEBUG)
        handlers = [handler]

    formatter = logging.Formatter(fmt='%(asctime)s [%(levelname)s] '
                                      '[%(name)s] %(message)s',
                                  datefmt='%H:%M:%S')
    for handler in handlers:
        handler.setFormatter(formatter)
        logger.addHandler(handler)

    logger.setLevel(logger_level)
    return logger


[docs]def get_local_ip(): """ Return the IP address used to connect to this machine by the management. machine """ return os.environ[LOCAL_IP_KEY]
[docs]def get_manager_ip(): """ Returns the IP address of manager inside the management network. """ return os.environ[MANAGER_IP_KEY]
[docs]def get_manager_file_server_blueprints_root_url(): """ Returns the blueprints root url in the file server. """ return os.environ[MANAGER_FILE_SERVER_BLUEPRINTS_ROOT_URL_KEY]
[docs]def get_manager_file_server_url(): """ Returns the manager file server base url. """ return os.environ[MANAGER_FILE_SERVER_URL_KEY]
[docs]def get_manager_rest_service_port(): """ Returns the port the manager REST service is running on. """ return int(os.environ[MANAGER_REST_PORT_KEY])
[docs]def id_generator(size=6, chars=string.ascii_uppercase + string.digits): """ Generate and return a random string using upper case letters and digits. """ return ''.join(random.choice(chars) for x in range(size))
def create_temp_folder(): """ Create a temporary folder. """ path_join = os.path.join(tempfile.gettempdir(), id_generator(5)) os.makedirs(path_join) return path_join def get_cosmo_properties(): return { "management_ip": get_manager_ip(), "ip": get_local_ip() } def find_type_in_kwargs(cls, all_args): result = [v for v in all_args if isinstance(v, cls)] if not result: return None if len(result) > 1: raise RuntimeError( "Expected to find exactly one instance of {0} in " "kwargs but found {1}".format(cls, len(result))) return result[0]
[docs]class LocalCommandRunner(object): def __init__(self, logger=None, host='localhost'): """ :param logger: This logger will be used for printing the output and the command. """ logger = logger or setup_logger('LocalCommandRunner') self.logger = logger self.host = host
[docs] def run(self, command, exit_on_failure=True, stdout_pipe=True, stderr_pipe=True): """ Runs local commands. :param command: The command to execute. :param exit_on_failure: False to ignore failures. :param stdout_pipe: False to not pipe the standard output. :param stderr_pipe: False to not pipe the standard error. :return: A wrapper object for all valuable info from the execution. :rtype: CommandExecutionResponse """ self.logger.info('[{0}] run: {1}'.format(self.host, command)) shlex_split = _shlex_split(command) stdout = subprocess.PIPE if stdout_pipe else None stderr = subprocess.PIPE if stderr_pipe else None p = subprocess.Popen(shlex_split, stdout=stdout, stderr=stderr) out, err = p.communicate() if p.returncode == 0: if out: self.logger.info('[{0}] out: {1}'.format(self.host, out)) else: error = CommandExecutionException( command=command, code=p.returncode, error=err, output=out) self.logger.error(error) if exit_on_failure: raise error return CommandExecutionResponse(command=command, std_out=out, std_err=err, return_code=p.returncode)
[docs]class CommandExecutionResponse(object): """ Wrapper object for info returned when running commands. :param command: The command that was executed. :param std_out: The output from the execution. :param std_err: The error message from the execution. :param return_code: The return code from the execution. """ def __init__(self, command, std_out, std_err, return_code): self.command = command self.std_out = std_out self.std_err = std_err self.return_code = return_code
def _shlex_split(command): lex = shlex.shlex(command, posix=True) lex.whitespace_split = True lex.escape = '' return list(lex) setup_default_logger = setup_logger # deprecated; for backwards compatibility