Пример #1
0
def set_current(timestamp):
    """
    Set an app directory to the currently live app
    by creating a symlink as specified in config
    """

    app_path = path.join(install_parent, timestamp)

    log(
        "Linking live path '{live}' to app dir: {app_dir}".format(
            app_dir=app_path, live=live_link_path
        )
    )

    run(sh.rm, live_link_path, force=True)
    run(sh.ln, app_path, live_link_path, symbolic=True)

    site_to_enable = path.join(sites_available_dir, timestamp)

    site_links = sh.glob(path.join(sites_enabled_dir, '*'))

    # Delete existing site links
    run(sh.rm, site_links, f=True)

    # Add our link into sites-enabled
    run(sh.ln, site_to_enable, sites_enabled_path, s=True)

    # Restart apache
    restart()
Пример #2
0
def extract_app_files(url, timestamp):
    """
    Extract the app zip file
    into an install directory (specified in config)
    """

    install_path = path.join(install_parent, timestamp)

    # Unless install dir already exists, extract it
    if not (path.exists(install_path) and listdir(install_path)):
        tempfile_path = '/tmp/wsgi-app-package.tgz'

        create_dir(install_path)

        log(
            "Extracting '{url}' to '{dir}'".format(
                url=url, dir=install_path
            )
        )

        run(sh.rm, tempfile_path, f=True)

        urlretrieve(url, tempfile_path)

        # Extract files into install dir
        run(
            sh.tar,
            file=tempfile_path,
            directory=install_path,
            strip="1", z=True, x=True
        )

    return install_path
Пример #3
0
def setup_http_server():
    public_address = sh.unit_get('public-address').rstrip()

    log('setting up "http-server" with address "{0}"'.format(public_address))

    sh.relation_set('hostname={0}'.format(public_address))

    restart()
Пример #4
0
def run(sh_function, *args, **kwargs):
    """
    Run command with logging
    """

    output = sh_function(*args, **kwargs)

    if output:
        log(str(output))
Пример #5
0
def install_packages(packages):
    """
    Install a list of packages if the list isn't empty
    and log that we've done so
    """

    if packages:
        log("Installing apt packages: {0}".format(packages))
        run(sh.apt_get.install, packages.split(), y=True)
Пример #6
0
def create_dir(dir_path):
    """
    Create a directoy and all parents, if it doesn't already exists
    and log that we've done so
    """

    if not path.exists(dir_path):
        log('Creating directory: {0}'.format(dir_path))
        run(sh.mkdir, dir_path, p=True)
Пример #7
0
def wsgi_relation_broken():
    """
    When WSGI relation (e.g.: gunicorn) goes away
    """

    log('Hook function: wsgi_relation_broken')

    config_data = ansible_config()

    close_port(config_data['listen_port'])
Пример #8
0
def wsgi_relation():
    """
    Setup relation for serving the WSGI file (e.g. gunicorn)

    Sets a whole bunch of relation settings
    including log file locations and environent variables
    """

    log('Hook function: wsgi_relation')

    config_data = ansible_config()

    log_file_path = path.join(
        config_data['log_dir'],
        config_data['app_label'] + '-access.log'
    )

    env_dictionary = parse_json_file(env_file_path)
    env_list = ["{0}={1}".format(k, v) for k, v in env_dictionary.items()]
    env_string = " ".join(env_list)

    wsgi_relation_settings = {
        'project_name': config_data.get('app_label', ''),
        'working_dir': path.join(config_data.get('code_dir', ''), 'current'),
        'python_path': config_data.get('python_path', ''),
        'wsgi_user': config_data.get('wsgi_user', ''),
        'wsgi_group': config_data.get('wsgi_group', ''),
        'port': config_data.get('listen_port', ''),
        'wsgi_access_logfile': log_file_path,
        'wsgi_wsgi_file': config_data.get('wsgi_application', ''),
        'wsgi_extra': '--error-logfile=' + log_file_path,
        'env_extra': env_string,
        'timestamp': datetime.now().isoformat()
    }

    # Set these settings on any wsgi-file relations
    for relation_id in relation_ids('wsgi-file'):
        log(
            'Setting wsgi-file relation settings: '
            + str(wsgi_relation_settings)
        )

        relation_set(
            relation_id=relation_id,
            **wsgi_relation_settings
        )

        # Relation changed - re-run update target
        update_target()

    open_port(config_data['listen_port'])
Пример #9
0
def save_environment_variables_string(env_vars):
    log('setting environment variable: {0}'.format(env_vars))

    export_string = 'export {0}\n'.format(env_vars)

    already_set = False

    with open(scriptrc_path) as scriptrc_read:
        already_set = export_string in scriptrc_read.read()

    # Save into scripts/scriptrc
    if not already_set:
        with open(scriptrc_path, 'a') as scriptrc:
            scriptrc.write(export_string)
Пример #10
0
def run_command(command=None):

    if command is None:
        return False

    log('Running Command "%s"' % command)
    try:
        return subprocess.check_output(
            command, shell=True,
            stderr=subprocess.STDOUT).decode('utf-8').replace('\n', '')
    except subprocess.CalledProcessError as e:
        log('Error running "%s" : %s' % (command, e.output))

        return False
Пример #11
0
def unlink_database(variable_name):
    """
    Remove "DATABASE_URL" environment variable
    """

    log('Function: unlink_database')

    env_vars = parse_json_file(env_file_path)

    if 'DATABASE_URL' in env_vars:
        del env_vars['DATABASE_URL']

        save_to_json_file(env_file_path, env_vars)

        # Reset wsgi relation settings
        wsgi_relation()
Пример #12
0
def unlink_webservice():
    """
    Remove "WEBSERVICE_URL" environment variable
    """

    log('Function: unlink_database')

    env_vars = parse_json_file(env_file_path)

    if 'WEBSERVICE_URL' in env_vars:
        del env_vars['WEBSERVICE_URL']

        save_to_json_file(env_file_path, env_vars)

        # Reset wsgi relation settings
        wsgi_relation()
Пример #13
0
def mongodb_relation():
    """
    Setup relation to a mongodb database
    (will replace any other database relations)
    """

    log('Hook function: mongodb_relation')

    host = relation_get("hostname")

    if 'mongodb' in relations() and host:
        link_database(
            scheme='mongodb',
            database_host=host,
            port=relation_get("port"),
            variable_name='MONGO_URL'
        )
Пример #14
0
def copy_ssl_certificates(timestamp):
    """
    Copy either the default self-signed certificate
    or the provided custom ones
    into /etc/ssl/certs/wsgi-app.*
    Return the locations of the created files
    """

    certs_dir = '/etc/ssl/certs'
    keyfile_path = path.join(
        certs_dir,
        'wsgi-app.{0}.key'.format(timestamp)
    )
    certificate_path = path.join(
        certs_dir,
        'wsgi-app.{0}.crt'.format(timestamp)
    )

    custom_keyfile = config('ssl_keyfile')
    custom_certificate = config('ssl_certificate')

    create_dir(certs_dir)

    log('Saving certificate files')

    if custom_keyfile and custom_certificate:
        keyfile_content = b64decode(custom_keyfile)
        certificate_content = b64decode(custom_certificate)

        with open(keyfile_path, 'w') as keyfile:
            keyfile.write(keyfile_content)

        with open(certificate_path, 'w') as certificate:
            certificate.write(certificate_content)
    else:
        config_path = path.join(charm_dir, 'ssl/wsgi-app.conf')

        run(
            sh.openssl.req,
            "-new", "-nodes", "-x509", "-newkey", "rsa:2048", "-days",
            "365", "-keyout", keyfile_path, "-out", certificate_path,
            "-config", config_path
        )

    return (keyfile_path, certificate_path)
Пример #15
0
def webservice_relation():
    """
    Create "WEBSERVICE_URL" environment variable from relation
    """

    log('Function: webservice_relation')
    http_protocol = relation_get('http_protocol') or 'http'
    address = relation_get('private-address')
    hostname = relation_get('hostname') or address

    # If hostname is IP address or FQDN, use it
    # otherwise use private_address
    ip_regex = re.compile(
        (
            r"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)"
            r"{3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
        )
    )
    hostname_regex = re.compile(
        (
            r"^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)+"
            r"([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
        )
    )

    if hostname_regex.match(hostname) or ip_regex.match(hostname):
        domain = hostname
    else:
        domain = address

    webservice_url = build_url(
        scheme=http_protocol,
        domain=domain,
        port=relation_get("port")
    )

    update_property_in_json_file(
        env_file_path, 'WEBSERVICE_URL', webservice_url
    )

    # Relation changed - re-run update target
    update_target()

    # Reset wsgi relation settings
    wsgi_relation()
Пример #16
0
def install():
    """
    - Install ansible
    - Create the cache directory

    The hook() helper decorating this install function ensures that after this
    function finishes, any tasks in the playbook tagged with install are
    executed.
    """

    log('Hook function: install')

    # Recreate cache directory
    if path.isdir(cache_dir):
        rmtree(cache_dir)

    mkdir(cache_dir)

    update_env()
Пример #17
0
def bridge_setup(cni):
    status_set('maintenance', 'Setting up new interface')

    interface = get_config('gateway-physical-interface')
    if interface == 'none' or interface == None:
        op = run_command('ip route | grep default').split(' ')
        interface = op[4]

    store('old_interface', interface)
    store('new_interface', 'br%s' % (interface))

    op = run_command('ovn-k8s-util nics-to-bridge %s' % (interface))
    log('Bridge create output: %s' % (op))

    op = run_command('dhclient -r br%s' % (interface))
    op = run_command('dhclient br%s' % (interface))

    status_set('maintenance', 'Waiting to initialise master')
    set_state('bridge.setup.done')
Пример #18
0
def pgsql_relation():
    """
    Setup relation to a postgresql database
    (will replace any other database relations)
    """

    log('Hook function: pgsql_relation')

    host = relation_get("host")

    if 'pgsql' in relations() and host:
        link_database(
            scheme='postgresql',
            database_host=host,
            port=relation_get("port"),
            username=relation_get("user"),
            password=relation_get("password"),
            database_name=relation_get("database")
        )
Пример #19
0
def pip_dependencies(app_path):
    """
    Install pip dependencies from requirements file
    and from the dependencies directory
    """

    # Read paths from config
    requirements_path = path.join(app_path, config('pip_requirements_path'))
    dependencies_path = path.join(app_path, config('pip_cache_path'))

    if path.isfile(requirements_path):
        # Install from requirements file if possible
        log("Installing pip requirements from {0}".format(requirements_path))

        # Install dependencies in dependencies directory
        run(
            sh.pip.install,
            r=requirements_path,
            find_links=dependencies_path,  # Path to local package files
            no_index=config('pip_no_index')  # Use PyPi?
        )
Пример #20
0
def install_gateway(cni):
    status_set('maintenance', 'Initialising gateway')

    run_command(
        'sudo ovs-vsctl set Open_vSwitch . external_ids:k8s-api-server="0.0.0.0:8080"'
    )

    run_command(
        'git clone https://github.com/openvswitch/ovn-kubernetes /tmp/ovn-kubernetes'
    )
    os.chdir('/tmp/ovn-kubernetes')
    run_command('sudo pip2 install .')

    old_interface = get_interface(old=True)
    new_interface = get_interface(old=False)

    op = run_command('ifconfig %s | grep "inet addr:"' % (new_interface))
    br_ip = op.lstrip().split()[1].replace('addr:', '')

    gateway_ip = run_command('ip route | grep default').split(' ')[2]
    hostname = run_command('hostname')

    op = run_command('ovn-k8s-overlay gateway-init \
                    --cluster-ip-subnet="192.168.0.0/16" \
                    --bridge-interface %s \
                    --physical-ip %s/32 \
                    --node-name="%s-gateway" \
                    --default-gw %s' %
                     (new_interface, br_ip, hostname, gateway_ip))
    log('Gateway init output: %s' % (op))

    op = run_command('ovn-k8s-gateway-helper --physical-bridge=%s \
                        --physical-interface=%s --pidfile --detach' %
                     (new_interface, old_interface))
    log('Gateway Helper start: %s' % (op))

    status_set('active', 'Master subnet : 192.168.1.0/24')
    set_state('gateway.installed')
Пример #21
0
def update_target():
    """
    Run the "update-charm" make target within the project
    """

    log('Hook function: update_target')

    config_data = ansible_config()

    required_configs = [
        'build_label',
        'archive_filename',
        'current_code_dir',
        'update_make_target'
    ]

    # Check all required configs are set
    if (
        items_are_not_empty(config_data, required_configs)
        and path.isdir(config_data['current_code_dir'])
    ):
        # Ensure make is installed
        apt_output = sh.apt_get.install('make')
        log('Installed make:')
        log(str(apt_output))

        env_vars = parse_json_file(env_file_path)

        # Execute make target with all environment variables
        make_output = sh.make(
            config_data['update_make_target'],
            directory=path.join(config_data['current_code_dir']),
            _env=env_vars
        )

        log('Make output:')
        log(str(make_output))
Пример #22
0
def can_connect(url):
    """
    Check whether we can connect to a URL
    and log the result
    """

    log("Checking connection to: {0}".format(url))
    success = True

    try:
        urlopen(url, timeout=1)
        log("... can connect")
    except URLError:
        log("... can't connect")
        success = False

    return success
Пример #23
0
def initialize_vault():
    log("Running initialize_vault now")
    set_state('vault.initialized')
Пример #24
0
def restart():
    service_restart("apache2")
    log('Restarted apache')