<commit_before>import datetime
import os
import re
import tempfile
import time

import yaml

from fabric.api import (
    env, execute, get, hide, local, put, require, run, settings, sudo, task)
from fabric.contrib import files, project
from fabric.utils import abort

DEFAULT_SALT_LOGLEVEL = 'info'

SALT_VERSION = '2014.7.6'

PROJECT_ROOT = os.path.dirname(__file__)

CONF_ROOT = os.path.join(PROJECT_ROOT, 'conf')

VALID_ROLES = (
    'salt-master',
    'web',
    'worker',
    'balancer',
    'db-master',
    'queue',
    'cache',
)

@task
def staging():
    env.environment = 'staging'
    env.master = '52.18.27.186'
    initialize_env()

@task
def production():
    env.environment = 'production'
    env.master = '52.18.126.172'
    initialize_env()

@task
def vagrant():
    env.environment = 'local'
    env.user = 'vagrant'
    # convert vagrant's ssh-config output to a dictionary
    ssh_config_output = local('vagrant ssh-config', capture=True)
    ssh_config = dict(line.split() for line in ssh_config_output.splitlines())
    env.master = '{HostName}:{Port}'.format(**ssh_config)
    env.key_filename = ssh_config['IdentityFile']
    initialize_env()

def initialize_env():
    """Build some common variables into the env dictionary."""
    env.gpg_key = os.path.join(CONF_ROOT, '{}.pub.gpg'.format(env.environment))

@task
def get_remote_db_dump(filename=None):
    """Dump remote database content to a local file."""
    # File will be put in the same place both locally and on the remote.
    if not filename:
        now = datetime.datetime.now().isoformat()
        filename = "tracpro-{env}-db-{now}.sql.gz".format(
            env=env.environment, now=now)
    output_path = os.path.join("/tmp/", filename)

    with settings(host_string=env.master):
        # Dump the database to a file on the remote host.
        cmd = 'pg_dump -Z 5 -U tracpro_{env} -d tracpro_{env} -f {output}'
        run(cmd.format(env=env.environment, output=output_path))

        # Copy the file from the remote host to the local machine.
        get(remote_path=output_path, local_path=output_path)

        # Remove the remote copy of the file.
        run("rm {}".format(output_path))

    return output_path

@task
def load_db_from_file(path, remove_files=True):
    """Load content from a database dump file.

    Removes the file and its unzipped contents unless specified otherwise.
    """
    unzipped = os.path.splitext(path)[0]
    local("cat {} | gunzip > {}".format(path, unzipped))
    local("dropdb --if-exists tracpro")
    local("createdb -E UTF-8 tracpro")
    local("psql -d tracpro -f {}".format(unzipped))
    if remove_files:
        local("rm {}".format(path))
        local("rm {}".format(unzipped))

@task
def get_db():
    """Copy the remote database to the local environment."""
    db_dump = get_remote_db_dump()
    load_db_from_file(db_dump)

def get_salt_version(command):
    """Run `command` --version, pick out the part of the output that is digits and dots,
    and return it as a string.
    If the command fails, return None.
    """
    with settings(warn_only=True):
        with hide('running', 'stdout', 'stderr'):
            result = run('%s --version' % command)
            if result.succeeded:
                return re.search(r'([\d\.]+)', result).group(0)

def service_enabled(name):
    """Check if an upstart service is enabled."""
    with settings(warn_only=True):
        with hide('running', 'stdout', 'stderr'):
            return sudo('service %s status' % name).succeeded

@task
def install_salt(version, master=False, minion=False, restart=True):
    """
    Install or upgrade Salt minion and/or master if needed.

    :param version: Version string, just numbers and dots, no leading 'v'.
                    E.g. "2015.5.0".
                    THERE IS NO DEFAULT, you must pick a version.
    :param master: If True, include master in the install.
    :param minion: If True, include minion in the install.
    :param restart: If we don't need to reinstall a salt package, restart its
                    server anyway.
    :returns: True if any changes were made, False if nothing was done.
    """
    master_version = None
    install_master = False
    if master:
        master_version = get_salt_version("salt")
        install_master = master_version != version or not service_enabled('salt-master')
        if install_master and master_version:
            # Already installed - if Ubuntu package, uninstall current version
            # first because we're going to do a git install later
            sudo("apt-get remove salt-master -yq")
        if restart and not install_master:
            sudo("service salt-master restart")

    minion_version = None
    install_minion = False
    if minion:
        minion_version = get_salt_version('salt-minion')
        install_minion = minion_version != version or not service_enabled('salt-minion')
        if install_minion and minion_version:
            # Already installed - if Ubuntu package, uninstall current version
            # first because we're going to do a git install later
            sudo("apt-get remove salt-minion -yq")
        if restart and not install_minion:
            sudo("service salt-minion restart")

    if install_master or install_minion:
        args = []
        if install_master:
            args.append('-M')
        if not install_minion:
            args.append('-N')
        args = ' '.join(args)
        # To update local install_salt.sh:
        #   wget -O install_salt.sh https://bootstrap.saltstack.com
        # then inspect it
        put(local_path="install_salt.sh", remote_path="install_salt.sh")
        sudo("sh install_salt.sh -D {args} git v{version}".format(
            args=args,
            version=version,
        ))
        return True
    return False

@task
def setup_master():
    """Provision master with salt-master."""
    require('environment')
    with settings(host_string=env.master):
        sudo('apt-get update -qq')
        sudo('apt-get install python-pip git-core python-git '
             'python-gnupg haveged -qq -y')
        sudo('mkdir -p /etc/salt/')
        put(local_path='conf/master.conf',
            remote_path="/etc/salt/master", use_sudo=True)
        # install salt master if it's not there already, or restart to pick up
        # config changes
        install_salt(master=True, restart=True, version=SALT_VERSION)
    generate_gpg_key()
    fetch_gpg_key()

@task
def sync():
    """
    Rysnc local states and pillar data to the master and update our checkout of
    margarita.
    """
    # project.rsync_project fails if host is not set
    with settings(host=env.master, host_string=env.master):
        salt_root = CONF_ROOT if CONF_ROOT.endswith('/') else CONF_ROOT + '/'
        project.rsync_project(
            local_dir=salt_root, remote_dir='/tmp/salt', delete=True)
        sudo('rm -rf /srv/salt /srv/pillar')
        sudo('mv /tmp/salt/* /srv/')
        sudo('rm -rf /tmp/salt/')
        execute(margarita)

@task
def setup_minion(*roles):
    """Setup a minion server with a set of roles."""
    require('environment')
    for r in roles:
        if r not in VALID_ROLES:
            abort('%s is not a valid server role for this project.' % r)
    config = {
        'master': 'localhost' if env.master == env.host else env.master,
        'output': 'mixed',
        'grains': {
            'environment': env.environment,
            'roles': list(roles),
        },
        'mine_functions': {
            'network.interfaces': []
        },
    }
    _, path = tempfile.mkstemp()
    with open(path, 'w') as f:
        yaml.dump(config, f, default_flow_style=False)
    put(local_path=path, remote_path="/etc/salt/minion", use_sudo=True)
    # install salt minion if it's not there already, or restart to pick up
    # config changes
    install_salt(SALT_VERSION, minion=True, restart=True)
    # queries server for its fully qualified domain name to get minion id
    key_name = run('python -c "import socket; print socket.getfqdn()"')
    time.sleep(5)
    execute(accept_key, key_name)

@task
def add_role(name):
    """Add a role to an exising minion configuration."""
    if name not in VALID_ROLES:
        abort('%s is not a valid server role for this project.' % name)
    _, path = tempfile.mkstemp()
    get("/etc/salt/minion", path)
    with open(path, 'r') as f:
        config = yaml.safe_load(f)
    grains = config.get('grains', {})
    roles = grains.get('roles', [])
    if name not in roles:
        roles.append(name)
    else:
        abort('Server is already configured with the %s role.' % name)
    grains['roles'] = roles
    config['grains'] = grains
    with open(path, 'w') as f:
        yaml.dump(config, f, default_flow_style=False)
    put(local_path=path, remote_path="/etc/salt/minion", use_sudo=True)
    sudo('service salt-minion restart')

@task
def salt(cmd, target="'*'", loglevel=DEFAULT_SALT_LOGLEVEL):
    """Run arbitrary salt commands."""
    with settings(warn_only=True, host_string=env.master):
        result = sudo("salt {0} -l{1} {2} ".format(target, loglevel, cmd))
    return result

@task
def state(name, target="'*'", loglevel=DEFAULT_SALT_LOGLEVEL):
    salt('state.sls {}'.format(name), target, loglevel)

@task
def margarita():
    require('environment')
    execute(state, 'margarita')
    # sudo('service salt-master restart')

@task
def highstate(target="'*'", loglevel=DEFAULT_SALT_LOGLEVEL):
    """Run highstate on master."""
    with settings(host_string=env.master):
        print("This can take a long time without output, be patient")
        salt('state.highstate', target, loglevel)

@task
def accept_key(name):
    """Accept minion key on master."""
    with settings(host_string=env.master):
        sudo('salt-key --accept={0} -y'.format(name))
        sudo('salt-key -L')

@task
def delete_key(name):
    """Delete specific key on master."""
    with settings(host_string=env.master):
        sudo('salt-key -L')
        sudo('salt-key --delete={0} -y'.format(name))
        sudo('salt-key -L')

@task
def deploy(loglevel=DEFAULT_SALT_LOGLEVEL):
    """
    Deploy to a given environment by pushing the latest states and executing
    the highstate.
    """
    require('environment')
    with settings(host_string=env.master):
        if env.environment != "local":
            sync()
        target = "-G 'environment:{0}'".format(env.environment)
        salt('saltutil.sync_all', target, loglevel)
        highstate(target)

@task
def generate_gpg_key():
    """Generate a GPG on the master if one does not exist."""
    require('environment')
    gpg_home = '/etc/salt/gpgkeys'
    gpg_file = '/tmp/gpg-batch'
    with settings(host_string=env.master):
        if not files.exists(os.path.join(gpg_home, 'secring.gpg'), use_sudo=True):
            sudo('mkdir -p {}'.format(gpg_home))
            files.upload_template(
                filename='conf/gpg.tmpl', destination=gpg_file,
                context={'environment': env.environment},
                use_jinja=False, use_sudo=False, backup=True)
            sudo('gpg --gen-key --homedir {} --batch {}'.format(gpg_home, gpg_file))

@task
def fetch_gpg_key():
    """Export GPG keys from the master."""
    require('environment')
    gpg_home = '/etc/salt/gpgkeys'
    gpg_public = '/tmp/public.gpg'
    with settings(host_string=env.master):
        with hide('running', 'stdout', 'stderr'):
            sudo('gpg --armor --homedir {} --armor --export > {}'.format(
                gpg_home, gpg_public))
            get(gpg_public, env.gpg_key)

@task
def encrypt(*args, **kwargs):
    """Encrypt a secret value for a given environment."""
    require('environment')
    # Convert ASCII key to binary
    temp_key = '/tmp/tmp.key'
    with hide('running', 'stdout', 'stderr'):
        local('gpg --dearmor < {} > {}'.format(env.gpg_key, temp_key))
        # Encrypt each file
        for name in args:
            local(
                'gpg --no-default-keyring --keyring {} '
                '--trust-model always -aer {}_salt_key {}'.format(
                    temp_key, env.environment, name))
        # Encrypt each value
        updates = {}
        for name, value in kwargs.items():
            updates[name] = '{}'.format(
                local(
                    'echo -n "{}" | '
                    'gpg --no-default-keyring --keyring {} '
                    '--trust-model always -aer {}_salt_key'.format(
                        value, temp_key, env.environment), capture=True))
        os.remove(temp_key)
    if updates:
        print(yaml.dump(updates, default_flow_style=False, default_style='|', indent=2))

def hostnames_for_role(role):
    with hide('running', 'stdout'):
        result = salt(
            cmd='test.ping --output=yaml',
            target='-G "roles:%s"' % role)
    return yaml.safe_load(result.stdout).keys()

def get_project_name():
    with open(os.path.join(CONF_ROOT, 'pillar', 'project.sls'), 'r') as f:
        return yaml.safe_load(f)['project_name']

@task
def manage_run(command):
    require('environment')
    project_name = get_project_name()
    manage_sh = u'/var/www/%s/manage.sh ' % project_name
    with settings(host_string=hostnames_for_role('web')[0]):
        sudo(manage_sh + command, user=project_name)

@task
def manage_shell():
    manage_run('shell')
<commit_msg>Added fabric command to add a swapfile<commit_after>import datetime
import os
import re
import tempfile
import time

import yaml

from fabric.api import (
    env, execute, get, hide, local, put, require, run, settings, sudo, task)
from fabric.contrib import files, project
from fabric.utils import abort

DEFAULT_SALT_LOGLEVEL = 'info'

SALT_VERSION = '2014.7.6'

PROJECT_ROOT = os.path.dirname(__file__)

CONF_ROOT = os.path.join(PROJECT_ROOT, 'conf')

VALID_ROLES = (
    'salt-master',
    'web',
    'worker',
    'balancer',
    'db-master',
    'queue',
    'cache',
)

@task
def staging():
    env.environment = 'staging'
    env.master = '52.18.27.186'
    initialize_env()

@task
def production():
    env.environment = 'production'
    env.master = '52.18.126.172'
    initialize_env()

@task
def vagrant():
    env.environment = 'local'
    env.user = 'vagrant'
    # convert vagrant's ssh-config output to a dictionary
    ssh_config_output = local('vagrant ssh-config', capture=True)
    ssh_config = dict(line.split() for line in ssh_config_output.splitlines())
    env.master = '{HostName}:{Port}'.format(**ssh_config)
    env.key_filename = ssh_config['IdentityFile']
    initialize_env()

def initialize_env():
    """Build some common variables into the env dictionary."""
    env.gpg_key = os.path.join(CONF_ROOT, '{}.pub.gpg'.format(env.environment))

@task
def get_remote_db_dump(filename=None):
    """Dump remote database content to a local file."""
    # File will be put in the same place both locally and on the remote.
    if not filename:
        now = datetime.datetime.now().isoformat()
        filename = "tracpro-{env}-db-{now}.sql.gz".format(
            env=env.environment, now=now)
    output_path = os.path.join("/tmp/", filename)

    with settings(host_string=env.master):
        # Dump the database to a file on the remote host.
        cmd = 'pg_dump -Z 5 -U tracpro_{env} -d tracpro_{env} -f {output}'
        run(cmd.format(env=env.environment, output=output_path))

        # Copy the file from the remote host to the local machine.
        get(remote_path=output_path, local_path=output_path)

        # Remove the remote copy of the file.
        run("rm {}".format(output_path))

    return output_path

@task
def load_db_from_file(path, remove_files=True):
    """Load content from a database dump file.

    Removes the file and its unzipped contents unless specified otherwise.
    """
    unzipped = os.path.splitext(path)[0]
    local("cat {} | gunzip > {}".format(path, unzipped))
    local("dropdb --if-exists tracpro")
    local("createdb -E UTF-8 tracpro")
    local("psql -d tracpro -f {}".format(unzipped))
    if remove_files:
        local("rm {}".format(path))
        local("rm {}".format(unzipped))

@task
def get_db():
    """Copy the remote database to the local environment."""
    db_dump = get_remote_db_dump()
    load_db_from_file(db_dump)

def get_salt_version(command):
    """Run `command` --version, pick out the part of the output that is digits and dots,
    and return it as a string.
    If the command fails, return None.
    """
    with settings(warn_only=True):
        with hide('running', 'stdout', 'stderr'):
            result = run('%s --version' % command)
            if result.succeeded:
                return re.search(r'([\d\.]+)', result).group(0)

def service_enabled(name):
    """Check if an upstart service is enabled."""
    with settings(warn_only=True):
        with hide('running', 'stdout', 'stderr'):
            return sudo('service %s status' % name).succeeded

@task
def install_salt(version, master=False, minion=False, restart=True):
    """
    Install or upgrade Salt minion and/or master if needed.

    :param version: Version string, just numbers and dots, no leading 'v'.
                    E.g. "2015.5.0".
                    THERE IS NO DEFAULT, you must pick a version.
    :param master: If True, include master in the install.
    :param minion: If True, include minion in the install.
    :param restart: If we don't need to reinstall a salt package, restart its
                    server anyway.
    :returns: True if any changes were made, False if nothing was done.
    """
    master_version = None
    install_master = False
    if master:
        master_version = get_salt_version("salt")
        install_master = master_version != version or not service_enabled('salt-master')
        if install_master and master_version:
            # Already installed - if Ubuntu package, uninstall current version
            # first because we're going to do a git install later
            sudo("apt-get remove salt-master -yq")
        if restart and not install_master:
            sudo("service salt-master restart")

    minion_version = None
    install_minion = False
    if minion:
        minion_version = get_salt_version('salt-minion')
        install_minion = minion_version != version or not service_enabled('salt-minion')
        if install_minion and minion_version:
            # Already installed - if Ubuntu package, uninstall current version
            # first because we're going to do a git install later
            sudo("apt-get remove salt-minion -yq")
        if restart and not install_minion:
            sudo("service salt-minion restart")

    if install_master or install_minion:
        args = []
        if install_master:
            args.append('-M')
        if not install_minion:
            args.append('-N')
        args = ' '.join(args)
        # To update local install_salt.sh:
        #   wget -O install_salt.sh https://bootstrap.saltstack.com
        # then inspect it
        put(local_path="install_salt.sh", remote_path="install_salt.sh")
        sudo("sh install_salt.sh -D {args} git v{version}".format(
            args=args,
            version=version,
        ))
        return True
    return False

@task
def setup_master():
    """Provision master with salt-master."""
    require('environment')
    with settings(host_string=env.master):
        sudo('apt-get update -qq')
        sudo('apt-get install python-pip git-core python-git '
             'python-gnupg haveged -qq -y')
        sudo('mkdir -p /etc/salt/')
        put(local_path='conf/master.conf',
            remote_path="/etc/salt/master", use_sudo=True)
        # install salt master if it's not there already, or restart to pick up
        # config changes
        install_salt(master=True, restart=True, version=SALT_VERSION)
    generate_gpg_key()
    fetch_gpg_key()

@task
def sync():
    """
    Rysnc local states and pillar data to the master and update our checkout of
    margarita.
    """
    # project.rsync_project fails if host is not set
    with settings(host=env.master, host_string=env.master):
        salt_root = CONF_ROOT if CONF_ROOT.endswith('/') else CONF_ROOT + '/'
        project.rsync_project(
            local_dir=salt_root, remote_dir='/tmp/salt', delete=True)
        sudo('rm -rf /srv/salt /srv/pillar')
        sudo('mv /tmp/salt/* /srv/')
        sudo('rm -rf /tmp/salt/')
        execute(margarita)

@task
def setup_minion(*roles):
    """Setup a minion server with a set of roles."""
    require('environment')
    for r in roles:
        if r not in VALID_ROLES:
            abort('%s is not a valid server role for this project.' % r)
    config = {
        'master': 'localhost' if env.master == env.host else env.master,
        'output': 'mixed',
        'grains': {
            'environment': env.environment,
            'roles': list(roles),
        },
        'mine_functions': {
            'network.interfaces': []
        },
    }
    _, path = tempfile.mkstemp()
    with open(path, 'w') as f:
        yaml.dump(config, f, default_flow_style=False)
    put(local_path=path, remote_path="/etc/salt/minion", use_sudo=True)
    # install salt minion if it's not there already, or restart to pick up
    # config changes
    install_salt(SALT_VERSION, minion=True, restart=True)
    # queries server for its fully qualified domain name to get minion id
    key_name = run('python -c "import socket; print socket.getfqdn()"')
    time.sleep(5)
    execute(accept_key, key_name)

@task
def add_role(name):
    """Add a role to an exising minion configuration."""
    if name not in VALID_ROLES:
        abort('%s is not a valid server role for this project.' % name)
    _, path = tempfile.mkstemp()
    get("/etc/salt/minion", path)
    with open(path, 'r') as f:
        config = yaml.safe_load(f)
    grains = config.get('grains', {})
    roles = grains.get('roles', [])
    if name not in roles:
        roles.append(name)
    else:
        abort('Server is already configured with the %s role.' % name)
    grains['roles'] = roles
    config['grains'] = grains
    with open(path, 'w') as f:
        yaml.dump(config, f, default_flow_style=False)
    put(local_path=path, remote_path="/etc/salt/minion", use_sudo=True)
    sudo('service salt-minion restart')

@task
def salt(cmd, target="'*'", loglevel=DEFAULT_SALT_LOGLEVEL):
    """Run arbitrary salt commands."""
    with settings(warn_only=True, host_string=env.master):
        result = sudo("salt {0} -l{1} {2} ".format(target, loglevel, cmd))
    return result

@task
def state(name, target="'*'", loglevel=DEFAULT_SALT_LOGLEVEL):
    salt('state.sls {}'.format(name), target, loglevel)

@task
def margarita():
    require('environment')
    execute(state, 'margarita')
    # sudo('service salt-master restart')

@task
def highstate(target="'*'", loglevel=DEFAULT_SALT_LOGLEVEL):
    """Run highstate on master."""
    with settings(host_string=env.master):
        print("This can take a long time without output, be patient")
        salt('state.highstate', target, loglevel)

@task
def accept_key(name):
    """Accept minion key on master."""
    with settings(host_string=env.master):
        sudo('salt-key --accept={0} -y'.format(name))
        sudo('salt-key -L')

@task
def delete_key(name):
    """Delete specific key on master."""
    with settings(host_string=env.master):
        sudo('salt-key -L')
        sudo('salt-key --delete={0} -y'.format(name))
        sudo('salt-key -L')

@task
def deploy(loglevel=DEFAULT_SALT_LOGLEVEL):
    """
    Deploy to a given environment by pushing the latest states and executing
    the highstate.
    """
    require('environment')
    with settings(host_string=env.master):
        if env.environment != "local":
            sync()
        target = "-G 'environment:{0}'".format(env.environment)
        salt('saltutil.sync_all', target, loglevel)
        highstate(target)

@task
def generate_gpg_key():
    """Generate a GPG on the master if one does not exist."""
    require('environment')
    gpg_home = '/etc/salt/gpgkeys'
    gpg_file = '/tmp/gpg-batch'
    with settings(host_string=env.master):
        if not files.exists(os.path.join(gpg_home, 'secring.gpg'), use_sudo=True):
            sudo('mkdir -p {}'.format(gpg_home))
            files.upload_template(
                filename='conf/gpg.tmpl', destination=gpg_file,
                context={'environment': env.environment},
                use_jinja=False, use_sudo=False, backup=True)
            sudo('gpg --gen-key --homedir {} --batch {}'.format(gpg_home, gpg_file))

@task
def fetch_gpg_key():
    """Export GPG keys from the master."""
    require('environment')
    gpg_home = '/etc/salt/gpgkeys'
    gpg_public = '/tmp/public.gpg'
    with settings(host_string=env.master):
        with hide('running', 'stdout', 'stderr'):
            sudo('gpg --armor --homedir {} --armor --export > {}'.format(
                gpg_home, gpg_public))
            get(gpg_public, env.gpg_key)

@task
def encrypt(*args, **kwargs):
    """Encrypt a secret value for a given environment."""
    require('environment')
    # Convert ASCII key to binary
    temp_key = '/tmp/tmp.key'
    with hide('running', 'stdout', 'stderr'):
        local('gpg --dearmor < {} > {}'.format(env.gpg_key, temp_key))
        # Encrypt each file
        for name in args:
            local(
                'gpg --no-default-keyring --keyring {} '
                '--trust-model always -aer {}_salt_key {}'.format(
                    temp_key, env.environment, name))
        # Encrypt each value
        updates = {}
        for name, value in kwargs.items():
            updates[name] = '{}'.format(
                local(
                    'echo -n "{}" | '
                    'gpg --no-default-keyring --keyring {} '
                    '--trust-model always -aer {}_salt_key'.format(
                        value, temp_key, env.environment), capture=True))
        os.remove(temp_key)
    if updates:
        print(yaml.dump(updates, default_flow_style=False, default_style='|', indent=2))

def hostnames_for_role(role):
    with hide('running', 'stdout'):
        result = salt(
            cmd='test.ping --output=yaml',
            target='-G "roles:%s"' % role)
    return yaml.safe_load(result.stdout).keys()

def get_project_name():
    with open(os.path.join(CONF_ROOT, 'pillar', 'project.sls'), 'r') as f:
        return yaml.safe_load(f)['project_name']

@task
def manage_run(command):
    require('environment')
    project_name = get_project_name()
    manage_sh = u'/var/www/%s/manage.sh ' % project_name
    with settings(host_string=hostnames_for_role('web')[0]):
        sudo(manage_sh + command, user=project_name)

@task
def manage_shell():
    manage_run('shell')

@task
def add_swap(size_of_swapfile=2048):
    """
    Create a swap file on the current filesystem. EC2 does not do this by default
    """
    if files.exists('/var/swapfile'):
        print "Swap file exists Exiting now"
        return
    sudo ('dd if=/dev/zero of=/var/swapfile bs=1M count={0}'.format(size_of_swapfile))
    sudo ('chmod 600 /var/swapfile')
    sudo ('mkswap /var/swapfile')
    files.append('/etc/fstab', '/var/swapfile none swap defaults 0 0', use_sudo=True)
    sudo ('swapon -a')
<|endoftext|>


<commit_before>
import requests
import telebot
import time

token = '125846015:AAH09k4Aj1YUYeV3gXuS6Tz19O7lUpKtZjE'
language = 'en'
time_for_quote = 3600
command = "/start, /help, /stop, /time, /lang"
switcher = True

def listener(messages):

    global switcher
    for m in messages:

                if m.text.startswith('/help'):

                    bot.send_message(m.chat.id,"Hello my friends, you can command me by next messages: "+command)
                elif m.text.startswith('/start'):
                    while switcher:
                          bot.send_message(m.chat.id,get_quote())
                          time.sleep(time_for_quote)
                elif m.text.startswith('/stop'):
                    switcher = False

#Return quote from api.forismatic.com
def get_quote():

    req = requests.get("http://api.forismatic.com/api/1.0/?method=getQuote&format=text&lang="+language)
    return req.text

if __name__ == '__main__':
#Put you token here
    bot  = telebot.TeleBot(token)

    bot.set_update_listener(listener)

# Run for Long Polling. Server holds the request open until new data is available

    bot.polling(none_stop=True)

    while True:
        time.sleep(1)

<commit_msg>Realize 3 simple commands<commit_after>
import requests
import telebot
import time

token = '125846015:AAFgMHVQuppvHqW-WnZ-A9wYJMa7kxsTGSo'
language = 'en'
time_for_quote = 3600
command = "/start, /help, /stop, /time, /lang"
switcher = True

def listener(messages):

    global switcher
    for m in messages:
        if m.content_type == 'text':

                if m.text.startswith('/help'):

                    bot.send_message(m.chat.id,"Hello my friends, you can command me by next messages: "+command)
                elif m.text.startswith('/start'):
                    switcher = True
                    while switcher:
                          bot.send_message(m.chat.id,get_quote())
                          time.sleep(2)
                elif m.text.startswith('/stop'):
                    switcher = False

#Return quote from api.forismatic.com
def get_quote():

    req = requests.get("http://api.forismatic.com/api/1.0/?method=getQuote&format=text&lang="+language)
    return req.text

if __name__ == '__main__':
#Put you token here
    bot  = telebot.TeleBot(token)

    bot.set_update_listener(listener)

# Run for Long Polling. Server holds the request open until new data is available

    bot.polling(none_stop=True)

    while True:
        time.sleep(1)

<|endoftext|>


<commit_before>#!/usr/bin/env python

# Copyright (c) 2009-2014 Sean M. Graham <www.sean-graham.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import os
import time
import sys
import getopt
import ConfigParser
import glob
import logging
import subprocess
import json

pluginList = { }

class TrackUpdate(object):
    introAlbum = ""
    trackArtist = ""
    trackName  = ""
    trackAlbum = ""
    trackTime = ""
    episodeNumber = "XX"
    pollTime = 10
    startTime = -1
    useStopValues = False
    stopTitle = ""
    stopArtist = ""
    stopAlbum = ""

    def usage(self):
        print( "Usage: trackupdate.py [arguments]" )
        print( """
This is a simple script which polls iTunes every (default) 10 seconds and writes information about the current track to Nicecast's "NowPlaying.txt" file.

Arguments:
    -e  --episode     the episode number (optional, used by some plugins)
    -t  --polltime    the time to wait between polling iTunes
    -h  --help        show this help page
    -v  --verbose     you are lonely and want trackupdate to talk more

Example:
    ./trackupdate.py -e 42 -t 5 -v
    """)

    def __init__(self,argv):
        config = None
        logging.basicConfig(level=logging.WARNING)

        # process config file
        try:
            config = ConfigParser.ConfigParser()
            config.read(os.path.expanduser('~/.trackupdaterc'))
        except ConfigParser.MissingSectionHeaderError:
            logging.warning("Warning: Invalid config file, no [trackupdate] section.")
            raise

        try:
            self.introAlbum = config.get('trackupdate', 'introAlbum')
            self.pollTime = int(config.get('trackupdate', 'pollTime'))
            self.useStopValues = config.get('trackupdate', 'useStopValues')
            self.stopTitle = config.get('trackupdate', 'stopTitle')
            self.stopArtist = config.get('trackupdate', 'stopArtist')
            self.stopAlbum = config.get('trackupdate', 'stopAlbum')
        except ConfigParser.NoSectionError:
            pass

        # process command-line arguments
        if(len(argv) > 0):
            try:
                opts, args = getopt.getopt(sys.argv[1:], "h:e:t:v", ["help",
                                           "episode=", "polltime=", "verbose"])
            except getopt.GetoptError, err:
                # print help information and exit:
                logging.error(str(err)) # will print something like
                                        # "option -a not recognized"
                self.usage()
                sys.exit(2)

            for o, a in opts:
                if o in ("-e", "--episode"):
                    self.episodeNumber = a
                elif o in ("-t", "--polltime"):
                    a = int(a)
                    if(a <= 0):
                        a = 1

                    self.pollTime = a
                elif o in ("-v", "--verbose"):
                    # remove any logging handlers created by logging before
                    # BasicConfig() is called
                    root = logging.getLogger()
                    if root.handlers:
                        for handler in root.handlers:
                            root.removeHandler(handler)

                    logging.basicConfig(level=logging.DEBUG)
                    logging.debug("Starting up. Press Ctrl-C to stop.")
                elif o in ("-h", "--help"):
                    self.usage()
                    sys.exit()
                else:
                    assert False, "unhandled option"

        self.loadPlugins(config, self.episodeNumber)
        logging.debug("Episode #: %s" % str(self.episodeNumber))
        logging.debug("Time between polling: %i" % self.pollTime)

        try:
            if(self.introAlbum != ""):
            #     logging.debug("Disabling Archiving until intro over")
            #     nc.stop_archiving()

                while(1):
                    if(self.startTime==-1):
                        track = json.loads(subprocess.check_output(["osascript",
                                             "Automation/GetCurrentTrackJSON.scpt"]))
                        album = None

                        if('album' in track.keys()):
                            album = track['album']

                        if((len(track) == 0) or (album == self.introAlbum)):
                            time.sleep(self.pollTime)
                        else:
                            # logging.debug("Enabling Archiving")
                            # nc.start_archiving()
                            break
                    else:
                        # logging.debug("Enabling Archiving")
                        # nc.start_archiving()
                        break
            # else:
            #     logging.debug("Enabling Archiving")
            #     nc.start_archiving()

            while(1):
                # if((it.player_state() == k.playing) and
                #    (nc.archiving()) and
                #    (nc.broadcasting()) and
                #    (self.startTime==-1)):
                #     # don't start the timeline until the intro is over
                #     self.startTime=time.time()

                track = json.loads(subprocess.check_output(["osascript",
                                     "Automation/GetCurrentTrackJSON.scpt"]))

                if(len(track) > 0):
                    self.processCurrentTrack(track)
                elif(self.useStopValues == 'True'):
                    self.updateTrack(self.stopTitle,
                                     self.stopArtist,
                                     self.stopAlbum,
                                     "9:99",
                                     self.startTime)

                time.sleep(self.pollTime)
        except (KeyboardInterrupt,SystemExit):
            self.cleanUp()

    def cleanUp(self):
        logging.debug("Exiting...")
        # logging.debug("Disabling Archiving")

        # try:
        #     nc.stop_archiving()
        # except (appscript.reference.CommandError):
        #     logging.error("Nicecast no longer running, unable to stop archiving")

        for plugin in pluginList:
            try:
                pluginList[plugin].close()
            except:
                logging.error(plugin + ": Error trying to close target")

    def processCurrentTrack(self, t):
        iArtist = ""
        iName = ""
        iAlbum = ""
        iTime = ""

        if('artist' in t.keys()):
            iArtist = t['artist']
        if('name' in t.keys()):
            iName = t['name']
        if('album' in t.keys()):
            iAlbum = t['album']
        if('time' in t.keys()):
            iTime = t['time']

        self.updateTrack(iName, iArtist, iAlbum,
                         iTime, self.startTime)

    def updateTrack(self, name, artist, album, time, startTime):
        # make sure the track has actually changed
        if( (artist != self.trackArtist) or (name != self.trackName) ):
            self.trackArtist = artist
            self.trackName  = name
            self.trackAlbum = album
            self.trackTime = time

            for plugin in pluginList:
                try:
                    pluginList[plugin].logTrack(name, artist, album,
                                                time, startTime)
                except:
                    logging.error(plugin + ": Error trying to update track")

    def loadPlugins(self, config, episode):
        logging.debug("Loading plugins...")

        scriptPath = os.path.split(os.path.abspath(__file__))[0]

        sys.path.append(scriptPath)
        sys.path.append(scriptPath + "/plugins/")
        pluginNames = glob.glob(scriptPath + "/plugins/*.py")
        for x in pluginNames:
            className = x.replace(".py","").replace(scriptPath + "/plugins/","")
            enabled = 'False'

            # if the .rc doesn't define whether it is enabled, defaults to False
            try:
                enabled = config.get(className, 'enabled')
            except ConfigParser.NoSectionError:
                enabled = 'False'
            except ConfigParser.NoOptionError:
                enabled = 'False'

            if(enabled=='False'):
                logging.debug("Skipping plugin '%s'." % className)
            else:
                logging.debug("Loading plugin '%s'...." % className)

                # import the module
                mod = __import__(className, globals(), locals(), [''])

                # find the symbol for the class
                cls  = getattr(mod,className)

                # initialize the plugin
                o = cls(config,episode)

                # add the plugin to the list
                pluginList[ o.pluginName ] = o

if __name__ == "__main__":
    trackUpdate = TrackUpdate(sys.argv[1:])
<commit_msg>Improved check for .trackupdaterc<commit_after>#!/usr/bin/env python

# Copyright (c) 2009-2014 Sean M. Graham <www.sean-graham.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import os
import time
import sys
import getopt
import ConfigParser
import glob
import logging
import subprocess
import json

pluginList = { }

class TrackUpdate(object):
    introAlbum = ""
    trackArtist = ""
    trackName  = ""
    trackAlbum = ""
    trackTime = ""
    episodeNumber = "XX"
    pollTime = 10
    startTime = -1
    useStopValues = False
    stopTitle = ""
    stopArtist = ""
    stopAlbum = ""

    def usage(self):
        print( "Usage: trackupdate.py [arguments]" )
        print( """
This is a simple script which polls iTunes every (default) 10 seconds and writes information about the current track to Nicecast's "NowPlaying.txt" file.

Arguments:
    -e  --episode     the episode number (optional, used by some plugins)
    -t  --polltime    the time to wait between polling iTunes
    -h  --help        show this help page
    -v  --verbose     you are lonely and want trackupdate to talk more

Example:
    ./trackupdate.py -e 42 -t 5 -v
    """)

    def __init__(self,argv):
        config = None
        logging.basicConfig(level=logging.WARNING)

        # process config file
        #STH 2017-0524 the following wouldn't actually catch whether .trackupdaterc
        #is missing, and wouldn't see whether it had a [trackupdate] section
        # try:
        #     config = ConfigParser.ConfigParser()
        #     config.read(os.path.expanduser('~/.trackupdaterc'))
        # except ConfigParser.MissingSectionHeaderError:
        #     logging.warning("Warning: Invalid config file, no [trackupdate] section.")
        #     raise
        if not os.path.isfile(os.path.expanduser('~/.trackupdaterc')):
            logging.warning("Warning: no config .trackupdaterc file.")

        config = ConfigParser.ConfigParser()
        config.read(os.path.expanduser('~/.trackupdaterc'))

        try:
            self.introAlbum = config.get('trackupdate', 'introAlbum')
            self.pollTime = int(config.get('trackupdate', 'pollTime'))
            self.useStopValues = config.get('trackupdate', 'useStopValues')
            self.stopTitle = config.get('trackupdate', 'stopTitle')
            self.stopArtist = config.get('trackupdate', 'stopArtist')
            self.stopAlbum = config.get('trackupdate', 'stopAlbum')
        except ConfigParser.NoSectionError:
            logging.warning("Warning: Invalid config file, no [trackupdate] section.")
            pass
        except ConfigParser.NoOptionError:
            print("[trackupdate]: Missing values in config")
            return

        # process command-line arguments
        if(len(argv) > 0):
            try:
                opts, args = getopt.getopt(sys.argv[1:], "h:e:t:v", ["help",
                                           "episode=", "polltime=", "verbose"])
            except getopt.GetoptError, err:
                # print help information and exit:
                logging.error(str(err)) # will print something like
                                        # "option -a not recognized"
                self.usage()
                sys.exit(2)

            for o, a in opts:
                if o in ("-e", "--episode"):
                    self.episodeNumber = a
                elif o in ("-t", "--polltime"):
                    a = int(a)
                    if(a <= 0):
                        a = 1

                    self.pollTime = a
                elif o in ("-v", "--verbose"):
                    # remove any logging handlers created by logging before
                    # BasicConfig() is called
                    root = logging.getLogger()
                    if root.handlers:
                        for handler in root.handlers:
                            root.removeHandler(handler)

                    logging.basicConfig(level=logging.DEBUG)
                    logging.debug("Starting up. Press Ctrl-C to stop.")
                elif o in ("-h", "--help"):
                    self.usage()
                    sys.exit()
                else:
                    assert False, "unhandled option"

        self.loadPlugins(config, self.episodeNumber)
        logging.debug("Episode #: %s" % str(self.episodeNumber))
        logging.debug("Time between polling: %i" % self.pollTime)

        try:
            if(self.introAlbum != ""):
            #     logging.debug("Disabling Archiving until intro over")
            #     nc.stop_archiving()

                while(1):
                    if(self.startTime==-1):
                        track = json.loads(subprocess.check_output(["osascript",
                                             "Automation/GetCurrentTrackJSON.scpt"]))
                        album = None

                        if('album' in track.keys()):
                            album = track['album']

                        if((len(track) == 0) or (album == self.introAlbum)):
                            time.sleep(self.pollTime)
                        else:
                            # logging.debug("Enabling Archiving")
                            # nc.start_archiving()
                            break
                    else:
                        # logging.debug("Enabling Archiving")
                        # nc.start_archiving()
                        break
            # else:
            #     logging.debug("Enabling Archiving")
            #     nc.start_archiving()

            while(1):
                # if((it.player_state() == k.playing) and
                #    (nc.archiving()) and
                #    (nc.broadcasting()) and
                #    (self.startTime==-1)):
                #     # don't start the timeline until the intro is over
                #     self.startTime=time.time()

                track = json.loads(subprocess.check_output(["osascript",
                                     "Automation/GetCurrentTrackJSON.scpt"]))

                if(len(track) > 0):
                    self.processCurrentTrack(track)
                elif(self.useStopValues == 'True'):
                    self.updateTrack(self.stopTitle,
                                     self.stopArtist,
                                     self.stopAlbum,
                                     "9:99",
                                     self.startTime)

                time.sleep(self.pollTime)
        except (KeyboardInterrupt,SystemExit):
            self.cleanUp()

    def cleanUp(self):
        logging.debug("Exiting...")
        # logging.debug("Disabling Archiving")

        # try:
        #     nc.stop_archiving()
        # except (appscript.reference.CommandError):
        #     logging.error("Nicecast no longer running, unable to stop archiving")

        for plugin in pluginList:
            try:
                pluginList[plugin].close()
            except:
                logging.error(plugin + ": Error trying to close target")

    def processCurrentTrack(self, t):
        iArtist = ""
        iName = ""
        iAlbum = ""
        iTime = ""

        if('artist' in t.keys()):
            iArtist = t['artist']
        if('name' in t.keys()):
            iName = t['name']
        if('album' in t.keys()):
            iAlbum = t['album']
        if('time' in t.keys()):
            iTime = t['time']

        self.updateTrack(iName, iArtist, iAlbum,
                         iTime, self.startTime)

    def updateTrack(self, name, artist, album, time, startTime):
        # make sure the track has actually changed
        if( (artist != self.trackArtist) or (name != self.trackName) ):
            self.trackArtist = artist
            self.trackName  = name
            self.trackAlbum = album
            self.trackTime = time

            for plugin in pluginList:
                try:
                    pluginList[plugin].logTrack(name, artist, album,
                                                time, startTime)
                except:
                    logging.error(plugin + ": Error trying to update track")

    def loadPlugins(self, config, episode):
        logging.debug("Loading plugins...")

        scriptPath = os.path.split(os.path.abspath(__file__))[0]

        sys.path.append(scriptPath)
        sys.path.append(scriptPath + "/plugins/")
        pluginNames = glob.glob(scriptPath + "/plugins/*.py")
        for x in pluginNames:
            className = x.replace(".py","").replace(scriptPath + "/plugins/","")
            enabled = 'False'

            # if the .rc doesn't define whether it is enabled, defaults to False
            try:
                enabled = config.get(className, 'enabled')
            except ConfigParser.NoSectionError:
                enabled = 'False'
            except ConfigParser.NoOptionError:
                enabled = 'False'

            if(enabled=='False'):
                logging.debug("Skipping plugin '%s'." % className)
            else:
                logging.debug("Loading plugin '%s'...." % className)

                # import the module
                mod = __import__(className, globals(), locals(), [''])

                # find the symbol for the class
                cls  = getattr(mod,className)

                # initialize the plugin
                o = cls(config,episode)

                # add the plugin to the list
                pluginList[ o.pluginName ] = o

if __name__ == "__main__":
    trackUpdate = TrackUpdate(sys.argv[1:])
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""
This module is for working with Micron Optics interrogators.

"""
from __future__ import print_function, division
import socket
import struct
import sys

class MicronInterrogator(object):
    def __init__(self, ip_address="10.0.0.126", port=1852):
        self.ip_address = ip_address
        self.port = port
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.latest_response = ""

    def connect(self):
        self.socket.connect((self.ip_address, self.port))

    def send_command(self, command):
        if command[0] != "#":
            command = "#" + command
        if command[-1] != "\n":
            command += "\n"
        self.socket.send(command.encode("ascii"))
        respsize = int(self.socket.recv(10))
        self.latest_response = self.socket.recv(respsize)

    @property
    def idn(self):
        self.send_command("IDN?")
        return self.latest_response.decode()

    def get_data(self):
        self.send_command("GET_DATA")
        self.data = self.latest_response
        data = struct.unpack("88B", self.data)
        print(data)

    def disconnect(self):
        self.socket.close()

def test_class():
    interr = MicronInterrogator()
    interr.connect()
    print(interr.idn)
    interr.get_data()

def terminal(ip_address="10.0.0.126", port=1852):
    """Creates a communcation terminal to send commands."""
    if sys.version_info >= (3, 0):
        input_function = input
        raw_input = None
    else:
        input_function = raw_input
    message = "#IDN?\n"
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip_address, port))
    while message != "exit":
        message = input_function("#")
        if message != "exit":
            s.send(b"#" + message.encode("ascii") + b"\n")
            respsize = int(s.recv(10))
            response = s.recv(respsize)
            print(response)
    s.close()

if __name__ == "__main__":
#    test_class()
    terminal()<commit_msg>Add parsing answer from Stackoverflow; a good start<commit_after>#!/usr/bin/env python
"""
This module is for working with Micron Optics interrogators.

"""
from __future__ import print_function, division
import socket
import struct
import sys

class MicronInterrogator(object):
    def __init__(self, ip_address="10.0.0.126", port=1852):
        self.ip_address = ip_address
        self.port = port
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.latest_response = ""

    def connect(self):
        self.socket.connect((self.ip_address, self.port))

    def send_command(self, command):
        if command[0] != "#":
            command = "#" + command
        if command[-1] != "\n":
            command += "\n"
        self.socket.send(command.encode("ascii"))
        respsize = int(self.socket.recv(10))
        self.latest_response = self.socket.recv(respsize)

    @property
    def idn(self):
        self.send_command("IDN?")
        return self.latest_response.decode()

    def get_data(self):
        self.send_command("GET_DATA")
        data = self.latest_response
        # unpack the struct into variables
        (
            abcde, fw_ver, cur_layer, fs_radix,  # 0 needs parse
            fghij, knpl, fbg_thermistor,  # 1 needs parse
            tx_ambient_temp, reserved2,  # 2
            num_ffpi_peaks, num_fbg_peaks,  # 3
            num_dut2_peaks, num_dut1_peaks,  # 4
            num_dut4_peaks, num_dut3_peaks,  # 5
            reserved7, qr, acq_counter3,  # 6 needs parse
            serial_number,  # 7
            kernel_timestamp_microseconds,  # 8
            kernel_timestamp_seconds,  # 9
            kernel_src_buffer, kernel_buffers,  # 10
            error_and_kernel_rt_loc0,  # 11 needs parse
            header_length, header_ver, buffers,  # 12
            dut2_gain, dut1_gain,  # 13
            dut4_gain, dut3_gain,  # 14
            dut2_noise_thresh, dut1_noise_thresh,  # 15
            dut4_noise_thresh, dut3_noise_thresh,  # 16
            hw_clk_div, peak_data_rate_div,  # 17
            granularity,  # 18
            reserved4,  # 19
            starting_lambda,  # 20
            ending_lambda  # 21
        ) = struct.unpack(
            '>'  # big endian
            'BBBB'  # 0 needs parse
            'BBH'  # 1 needs parse
            'HH'  # 2
            'HH'  # 3
            'HH'  # 4
            'HH'  # 5
            'BBH'  # 6 needs parse
            'I'  # 7
            'I'  # 8
            'I'  # 9
            'HH'  # 10
            'I'  # 11 needs parse
            'HBB'  # 12
            'HH'  # 13
            'HH'  # 14
            'HH'  # 15
            'HH'  # 16
            'HH'  # 17
            'I'  # 18
            'I'  # 19
            'I'  # 20
            'I',  # 21
            data
        )

        # 0 parse abcde
        acq_triggered = bool(abcde & 0x80)
        calibration_fault = bool(abcde & 0x40)
        start_of_frame = bool(abcde & 0x20)
        primary_fan_state = bool(abcde & 0x10)
        secondary_fan_state = bool(abcde & 0x08)
        s0_mux_state = bool(abcde & 0x04)
        s1_mux_state = bool(abcde & 0x02)
        s2_mux_state = bool(abcde & 0x01)

        # 1 parse fghij
        xfer_type = fghij >> 4
        soa_therm_limit = bool(fghij & 0x08)
        soa_current_limit = bool(fghij & 0x04)
        tec_over_temp = bool(fghij & 0x02)
        tec_under_temp = bool(fghij & 0x01)

        # 1 parse knpl
        operating_mode = knpl >> 6
        triggering_mode = (knpl & 0x30) >> 4
        sm041_mux_level = (knpl & 0x0c) >> 2
        sw_position = knpl & 0x03

        # 6 parse qr
        nrz_command = qr >> 5
        reserved6 = qr & 0x1f

        # 11 parse
        error = error_and_kernel_rt_loc0 >> 24
        kernel_rt_loc0 = error_and_kernel_rt_loc0 & 0xffffff

        print("Serial number", serial_number)

        print("Firmware version:", fw_ver)
        print("Acquisition triggered:", acq_triggered)
        print("Calibration fault:", calibration_fault)
        print("Primary fan state:", primary_fan_state)
        print("Secondary fan state:", secondary_fan_state)

        print("Header length:", header_length)

        print("Tx ambient temp:", tx_ambient_temp)

        print("Operating mode:", operating_mode)

    def disconnect(self):
        self.socket.close()

def test_class():
    interr = MicronInterrogator()
    interr.connect()
    print(interr.idn)
    interr.get_data()

def terminal(ip_address="10.0.0.126", port=1852):
    """Creates a communcation terminal to send commands."""
    if sys.version_info >= (3, 0):
        input_function = input
        raw_input = None
    else:
        input_function = raw_input
    message = "#IDN?\n"
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip_address, port))
    while message != "exit":
        message = input_function("#")
        if message != "exit":
            s.send(b"#" + message.encode("ascii") + b"\n")
            respsize = int(s.recv(10))
            response = s.recv(respsize)
            print(response)
    s.close()

if __name__ == "__main__":
    test_class()
#    terminal()<|endoftext|>


<commit_before>"""
High-level functionality for creating clients and services in OpenNSA.

Binds all the OpenNSA modules together into a useful service.
This is a tad complex.

Beware that the Twisted HTTP module should be fed paths in bytes, not string,
or nothing will work.

TODO:
Split out the main setup into some more comprehensible parts.
Split out the main setup so the site can be retrieved without the service (so the whole thing can be tested).

"""

import os
import hashlib
import datetime
import importlib

from twisted.python import log
from twisted.web import resource, server
from twisted.application import internet, service as twistedservice

from opennsa import __version__ as version

from opennsa.config import Config
from opennsa import config, logging, constants as cnt, nsa, provreg, database, aggregator, viewresource
from opennsa.topology import nrm, nml, linkvector, service as nmlservice
from opennsa.protocols import rest, nsi2
from opennsa.protocols.shared import httplog
from opennsa.discovery import service as discoveryservice, fetcher

NSI_RESOURCE = b'NSI'

def setupBackend(backend_cfg, network_name, nrm_ports, parent_requester):
    bc = backend_cfg.copy()
    backend_type = backend_cfg.pop('_backend_type')

    if backend_type == config.BLOCK_DUD:
        from opennsa.backends import dud
        BackendConstructer = dud.DUDNSIBackend

    elif backend_type == config.BLOCK_JUNOSMX:
        from opennsa.backends import junosmx
        BackendConstructer = junosmx.JUNOSMXBackend

    elif backend_type == config.BLOCK_FORCE10:
        from opennsa.backends import force10
        BackendConstructer = force10.Force10Backend

    elif backend_type == config.BLOCK_JUNIPER_EX:
        from opennsa.backends import juniperex
        BackendConstructer = juniperex.JuniperEXBackend

    elif backend_type == config.BLOCK_JUNIPER_VPLS:
        from opennsa.backends import junipervpls
        BackendConstructer = junipervpls.JuniperVPLSBackend

    elif backend_type == config.BLOCK_BROCADE:
        from opennsa.backends import brocade
        BackendConstructer = brocade.BrocadeBackend

    elif backend_type == config.BLOCK_NCSVPN:
        from opennsa.backends import ncsvpn
        BackendConstructer = ncsvpn.NCSVPNBackend

    elif backend_type == config.BLOCK_PICA8OVS:
        from opennsa.backends import pica8ovs
        BackendConstructer = pica8ovs.Pica8OVSBackend

    elif backend_type == config.BLOCK_JUNOSSPACE:
        from opennsa.backends import junosspace
        BackendConstructer = junosspace.JUNOSSPACEBackend

    elif backend_type == config.BLOCK_JUNOSEX:
        from opennsa.backends import junosex
        BackendConstructer = junosex.JunosEXBackend

    elif backend_type == config.BLOCK_OESS:
        from opennsa.backends import oess
        BackendConstructer = oess.OESSBackend

    elif backend_type == config.BLOCK_CUSTOM_BACKEND:
        module_name = backend_cfg.pop('module')
        try:
            module = importlib.import_module(module_name)
            BackendConstructer = module.Backend
        except Exception as e:
            log.msg('Failed to load backend {}:\n{}'.format(module_name, e))
            raise config.ConfigurationError('Failed to load backend')
    else:
        raise config.ConfigurationError('No backend specified')

    b = BackendConstructer(network_name, nrm_ports, parent_requester, bc)
    return b

def setupTLSContext(vc):
    # ssl/tls contxt
    if vc[config.TLS]:
        log.msg('setup for full client/server TLS mode')
        from opennsa.opennsaTlsContext import opennsa2WayTlsContext
        ctx_factory = opennsa2WayTlsContext(
            vc[config.KEY], vc[config.CERTIFICATE], vc[config.CERTIFICATE_DIR], vc[config.VERIFY_CERT])
    elif vc[config.CERTIFICATE_DIR]:
        # create a context so we can verify https urls
        if not os.path.isdir(vc[config.CERTIFICATE_DIR]):
            raise config.ConfigurationError(
                'certdir value {} is not a directory'.format(vc[config.CERTIFICATE_DIR]))
        if vc[config.KEY] and vc[config.CERTIFICATE]:
            # enable client authentication even when not in TLS mode
            log.msg('setup for client TLS mode with client authentication')
            from opennsa.opennsaTlsContext import opennsa2WayTlsContext
            ctx_factory = opennsa2WayTlsContext(
                vc[config.KEY], vc[config.CERTIFICATE], vc[config.CERTIFICATE_DIR], vc[config.VERIFY_CERT])
        else:
            from opennsa.opennsaTlsContext import opennsaTlsContext
            log.msg('setup for client TLS mode without client authentication')
            ctx_factory = opennsaTlsContext(
                vc[config.CERTIFICATE_DIR], vc[config.VERIFY_CERT])
    else:
        ctx_factory = None

    return ctx_factory

class CS2RequesterCreator:

    def __init__(self, top_resource, aggregator, host, port, tls, ctx_factory):
        self.top_resource = top_resource
        self.aggregator = aggregator
        self.host = host
        self.port = port
        self.tls = tls
        self.ctx_factory = ctx_factory

    def create(self, nsi_agent):
        hash_input = nsi_agent.urn() + nsi_agent.endpoint
        resource_name = b'RequesterService2-' + \
                        hashlib.sha1(hash_input.encode()).hexdigest().encode()
        return nsi2.setupRequesterPair(self.top_resource, self.host, self.port, nsi_agent.endpoint, self.aggregator,
                                       resource_name, tls=self.tls, ctx_factory=self.ctx_factory)

class OpenNSAService(twistedservice.MultiService):

    def __init__(self, vc):
        twistedservice.MultiService.__init__(self)
        self.vc = vc

    def setupServiceFactory(self):
        """
        This sets up the OpenNSA service and ties together everything in the initialization.
        There are a lot of things going on, but none of it it particular deep.
        """
        log.msg('OpenNSA service initializing')

        vc = self.vc

        now = datetime.datetime.utcnow().replace(microsecond=0)

        if vc[config.HOST] is None:
            # guess name if not configured
            import socket
            vc[config.HOST] = socket.getfqdn()

        # database
        database.setupDatabase(vc[config.DATABASE], vc[config.DATABASE_USER],
                               vc[config.DATABASE_PASSWORD], vc[config.DATABASE_HOST], vc[config.SERVICE_ID_START])

        service_endpoints = []

        # base names
        domain_name = vc[config.DOMAIN]  # FIXME rename variable to domain
        nsa_name = domain_name + ':nsa'

        # base url
        if vc[config.BASE_URL]:
            base_url = vc[config.BASE_URL]
        else:
            base_protocol = 'https://' if vc[config.TLS] else 'http://'
            base_url = base_protocol + vc[config.HOST] + ':' + str(vc[config.PORT])

        # nsi endpoint and agent
        provider_endpoint = base_url + '/NSI/services/CS2'  # hardcode for now
        service_endpoints.append(('Provider', provider_endpoint))

        ns_agent = nsa.NetworkServiceAgent(
            nsa_name, provider_endpoint, 'local')

        # ssl/tls context
        ctx_factory = setupTLSContext(vc)  # May be None

        # plugin
        if vc[config.PLUGIN]:
            from twisted.python import reflect
            plugin = reflect.namedAny(
                'opennsa.plugins.%s.plugin' % vc[config.PLUGIN])
        else:
            from opennsa.plugin import BasePlugin
            plugin = BasePlugin()

        plugin.init(vc, ctx_factory)

        # the dance to setup dynamic providers right
        top_resource = resource.Resource()
        requester_creator = CS2RequesterCreator(
            top_resource, None, vc[config.HOST], vc[config.PORT], vc[config.TLS], ctx_factory)  # set aggregator later

        provider_registry = provreg.ProviderRegistry(
            {cnt.CS2_SERVICE_TYPE: requester_creator.create})

        link_vector = linkvector.LinkVector()

        networks = {}
        ports = {}  # { network : { port : nrmport } }

        parent_requester = None  # parent requester is set later
        aggr = aggregator.Aggregator(
            ns_agent, ports, link_vector, parent_requester, provider_registry, vc[config.POLICY], plugin)

        requester_creator.aggregator = aggr

        pc = nsi2.setupProvider(
            aggr, top_resource, ctx_factory=ctx_factory, allowed_hosts=vc.get(config.ALLOWED_HOSTS))
        aggr.parent_requester = pc

        # setup backend(s) - for now we only support one
        backend_configs = vc['backend']
        if len(backend_configs) == 0:
            log.msg('No backend specified. Running in aggregator-only mode')
            if not cnt.AGGREGATOR in vc[config.POLICY]:
                vc[config.POLICY].append(cnt.AGGREGATOR)

        else:  # at least one backend

            # This is all temporary right now... clean up later

            for backend_name, b_cfg in backend_configs.items():

                if backend_name is None or backend_name == '':
                    raise config.ConfigurationError(
                        'You need to specify backend name, use [backend:name]')

                backend_network_name = '{}:{}'.format(
                    domain_name, backend_name)

                if not config.NRM_MAP_FILE in b_cfg:  # move to verify config
                    raise config.ConfigurationError(
                        'No nrm map specified for backend')

                backend_nrm_map_file = b_cfg[config.NRM_MAP_FILE]
                if not os.path.exists(backend_nrm_map_file):  # move to verify config
                    raise config.ConfigError('nrm map file {} for backend {} does not exists'.format(
                        backend_nrm_map_file, backend_name))

                nrm_map = open(backend_nrm_map_file)
                backend_nrm_ports = nrm.parsePortSpec(nrm_map)

                link_vector.addLocalNetwork(backend_network_name)
                for np in backend_nrm_ports:
                    if np.remote_network is not None:
                        link_vector.updateVector(backend_network_name, np.name, {
                            np.remote_network: 1})  # hack
                        for network, cost in np.vectors.items():
                            link_vector.updateVector(np.name, {network: cost})
                    # build port map for aggreator to lookup
                    ports.setdefault(backend_network_name, {})[np.name] = np

                backend_service = setupBackend(
                    b_cfg, backend_network_name, backend_nrm_ports, aggr)

                networks[backend_network_name] = {
                    'backend': backend_service,
                    'nrm_ports': backend_nrm_ports
                }

                provider_registry.addProvider(
                    ns_agent.urn(), backend_network_name, backend_service)

        # fetcher
        if vc[config.PEERS]:
            fetcher_service = fetcher.FetcherService(
                link_vector, networks, vc[config.PEERS], provider_registry, ctx_factory=ctx_factory)
            fetcher_service.setServiceParent(self)
        else:
            log.msg(
                'No peers configured, will not be able to do outbound requests (UPA mode)')

        # discovery service
        opennsa_version = 'OpenNSA-' + version
        network_urns = ['{}{}'.format(
            cnt.URN_OGF_PREFIX, network_name) for network_name in networks]
        interfaces = [(cnt.CS2_PROVIDER, provider_endpoint, None),
                      (cnt.CS2_SERVICE_TYPE, provider_endpoint, None)]
        features = []
        if networks:
            features.append((cnt.FEATURE_UPA, None))
        if vc[config.PEERS]:
            features.append((cnt.FEATURE_AGGREGATOR, None))

        # view resource
        vr = viewresource.ConnectionListResource()
        top_resource.children[NSI_RESOURCE].putChild('connections', vr)

        # rest service
        if vc[config.REST]:
            rest_url = base_url + '/connections'

            rest.setupService(aggr, top_resource, vc.get(config.ALLOWED_HOSTS))

            service_endpoints.append(('REST', rest_url))
            interfaces.append((cnt.OPENNSA_REST, rest_url, None))

        for backend_network_name, no in networks.items():
            nml_resource_name = '{}.nml.xml'.format(backend_network_name)
            nml_url = '%s/NSI/%s' % (base_url, nml_resource_name)

            nml_network = nml.createNMLNetwork(
                no['nrm_ports'], backend_network_name, backend_network_name)
            can_swap_label = no['backend'].connection_manager.canSwapLabel(
                cnt.ETHERNET_VLAN)

            nml_service = nmlservice.NMLService(nml_network, can_swap_label)

            top_resource.children[NSI_RESOURCE].putChild(
                nml_resource_name.encode(), nml_service.resource())

            service_endpoints.append(('NML Topology', nml_url))
            interfaces.append((cnt.NML_SERVICE_TYPE, nml_url, None))

        # discovery service
        discovery_resource_name = b'discovery.xml'
        discovery_url = '%s/NSI/%s' % (base_url,
                                       discovery_resource_name.decode())

        ds = discoveryservice.DiscoveryService(ns_agent.urn(
        ), now, domain_name, opennsa_version, now, network_urns, interfaces, features, provider_registry, link_vector)

        discovery_resource = ds.resource()
        top_resource.children[NSI_RESOURCE].putChild(
            discovery_resource_name, discovery_resource)
        link_vector.callOnUpdate(
            lambda: discovery_resource.updateResource(ds.xml()))

        service_endpoints.append(('Discovery', discovery_url))

        # log service urls
        for service_name, url in service_endpoints:
            log.msg('{:<12} URL: {}'.format(service_name, url))

        factory = server.Site(top_resource)
        factory.log = httplog.logRequest  # default logging is weird, so we do our own

        return factory, ctx_factory

    def startService(self):

        factory, ctx_factory = self.setupServiceFactory()

        if self.vc[config.TLS]:
            internet.SSLServer(
                self.vc[config.PORT], factory, ctx_factory).setServiceParent(self)
        else:
            internet.TCPServer(self.vc[config.PORT],
                               factory).setServiceParent(self)

        # do not start sub-services until we have started this one
        twistedservice.MultiService.startService(self)

        log.msg('OpenNSA service started')

    def stopService(self):
        twistedservice.Service.stopService(self)

def createApplication(config_file=config.DEFAULT_CONFIG_FILE, debug=False, payload=False):
    application = twistedservice.Application('OpenNSA')

    try:
        configIns = Config.instance()
        cfg, vc = configIns.read_config(config_file)

        # if log file is empty string use stdout
        if vc[config.LOG_FILE]:
            log_file = open(vc[config.LOG_FILE], 'a')
        else:
            import sys
            log_file = sys.stdout

        nsa_service = OpenNSAService(vc)
        nsa_service.setServiceParent(application)

        application.setComponent(log.ILogObserver, logging.DebugLogObserver(
            log_file, debug, payload=payload).emit)
        return application

    except config.ConfigurationError as e:
        import sys
        sys.stderr.write("Configuration error: %s\n" % e)
        sys.exit(1)
<commit_msg>simplified setupTLSContext()<commit_after>"""
High-level functionality for creating clients and services in OpenNSA.

Binds all the OpenNSA modules together into a useful service.
This is a tad complex.

Beware that the Twisted HTTP module should be fed paths in bytes, not string,
or nothing will work.

TODO:
Split out the main setup into some more comprehensible parts.
Split out the main setup so the site can be retrieved without the service (so the whole thing can be tested).

"""

import os
import hashlib
import datetime
import importlib

from twisted.python import log
from twisted.web import resource, server
from twisted.application import internet, service as twistedservice

from opennsa import __version__ as version

from opennsa.config import Config
from opennsa import config, logging, constants as cnt, nsa, provreg, database, aggregator, viewresource
from opennsa.topology import nrm, nml, linkvector, service as nmlservice
from opennsa.protocols import rest, nsi2
from opennsa.protocols.shared import httplog
from opennsa.discovery import service as discoveryservice, fetcher

NSI_RESOURCE = b'NSI'

def setupBackend(backend_cfg, network_name, nrm_ports, parent_requester):
    bc = backend_cfg.copy()
    backend_type = backend_cfg.pop('_backend_type')

    if backend_type == config.BLOCK_DUD:
        from opennsa.backends import dud
        BackendConstructer = dud.DUDNSIBackend

    elif backend_type == config.BLOCK_JUNOSMX:
        from opennsa.backends import junosmx
        BackendConstructer = junosmx.JUNOSMXBackend

    elif backend_type == config.BLOCK_FORCE10:
        from opennsa.backends import force10
        BackendConstructer = force10.Force10Backend

    elif backend_type == config.BLOCK_JUNIPER_EX:
        from opennsa.backends import juniperex
        BackendConstructer = juniperex.JuniperEXBackend

    elif backend_type == config.BLOCK_JUNIPER_VPLS:
        from opennsa.backends import junipervpls
        BackendConstructer = junipervpls.JuniperVPLSBackend

    elif backend_type == config.BLOCK_BROCADE:
        from opennsa.backends import brocade
        BackendConstructer = brocade.BrocadeBackend

    elif backend_type == config.BLOCK_NCSVPN:
        from opennsa.backends import ncsvpn
        BackendConstructer = ncsvpn.NCSVPNBackend

    elif backend_type == config.BLOCK_PICA8OVS:
        from opennsa.backends import pica8ovs
        BackendConstructer = pica8ovs.Pica8OVSBackend

    elif backend_type == config.BLOCK_JUNOSSPACE:
        from opennsa.backends import junosspace
        BackendConstructer = junosspace.JUNOSSPACEBackend

    elif backend_type == config.BLOCK_JUNOSEX:
        from opennsa.backends import junosex
        BackendConstructer = junosex.JunosEXBackend

    elif backend_type == config.BLOCK_OESS:
        from opennsa.backends import oess
        BackendConstructer = oess.OESSBackend

    elif backend_type == config.BLOCK_CUSTOM_BACKEND:
        module_name = backend_cfg.pop('module')
        try:
            module = importlib.import_module(module_name)
            BackendConstructer = module.Backend
        except Exception as e:
            log.msg('Failed to load backend {}:\n{}'.format(module_name, e))
            raise config.ConfigurationError('Failed to load backend')
    else:
        raise config.ConfigurationError('No backend specified')

    b = BackendConstructer(network_name, nrm_ports, parent_requester, bc)
    return b

def setupTLSContext(vc):
    # ssl/tls contxt
    if vc[config.KEY] and vc[config.CERTIFICATE]:
        log.msg('setup full 2Way TLS context')
        from opennsa.opennsaTlsContext import opennsa2WayTlsContext
        ctx_factory = opennsa2WayTlsContext(
            vc[config.KEY], vc[config.CERTIFICATE], vc[config.CERTIFICATE_DIR], vc[config.VERIFY_CERT])
    else:
        from opennsa.opennsaTlsContext import opennsaTlsContext
        log.msg('setup client TLS context without client authentication')
        ctx_factory = opennsaTlsContext(
            vc[config.CERTIFICATE_DIR], vc[config.VERIFY_CERT])

    return ctx_factory

class CS2RequesterCreator:

    def __init__(self, top_resource, aggregator, host, port, tls, ctx_factory):
        self.top_resource = top_resource
        self.aggregator = aggregator
        self.host = host
        self.port = port
        self.tls = tls
        self.ctx_factory = ctx_factory

    def create(self, nsi_agent):
        hash_input = nsi_agent.urn() + nsi_agent.endpoint
        resource_name = b'RequesterService2-' + \
                        hashlib.sha1(hash_input.encode()).hexdigest().encode()
        return nsi2.setupRequesterPair(self.top_resource, self.host, self.port, nsi_agent.endpoint, self.aggregator,
                                       resource_name, tls=self.tls, ctx_factory=self.ctx_factory)

class OpenNSAService(twistedservice.MultiService):

    def __init__(self, vc):
        twistedservice.MultiService.__init__(self)
        self.vc = vc

    def setupServiceFactory(self):
        """
        This sets up the OpenNSA service and ties together everything in the initialization.
        There are a lot of things going on, but none of it it particular deep.
        """
        log.msg('OpenNSA service initializing')

        vc = self.vc

        now = datetime.datetime.utcnow().replace(microsecond=0)

        if vc[config.HOST] is None:
            # guess name if not configured
            import socket
            vc[config.HOST] = socket.getfqdn()

        # database
        database.setupDatabase(vc[config.DATABASE], vc[config.DATABASE_USER],
                               vc[config.DATABASE_PASSWORD], vc[config.DATABASE_HOST], vc[config.SERVICE_ID_START])

        service_endpoints = []

        # base names
        domain_name = vc[config.DOMAIN]  # FIXME rename variable to domain
        nsa_name = domain_name + ':nsa'

        # base url
        if vc[config.BASE_URL]:
            base_url = vc[config.BASE_URL]
        else:
            base_protocol = 'https://' if vc[config.TLS] else 'http://'
            base_url = base_protocol + vc[config.HOST] + ':' + str(vc[config.PORT])

        # nsi endpoint and agent
        provider_endpoint = base_url + '/NSI/services/CS2'  # hardcode for now
        service_endpoints.append(('Provider', provider_endpoint))

        ns_agent = nsa.NetworkServiceAgent(
            nsa_name, provider_endpoint, 'local')

        # ssl/tls context
        ctx_factory = setupTLSContext(vc)  # May be None

        # plugin
        if vc[config.PLUGIN]:
            from twisted.python import reflect
            plugin = reflect.namedAny(
                'opennsa.plugins.%s.plugin' % vc[config.PLUGIN])
        else:
            from opennsa.plugin import BasePlugin
            plugin = BasePlugin()

        plugin.init(vc, ctx_factory)

        # the dance to setup dynamic providers right
        top_resource = resource.Resource()
        requester_creator = CS2RequesterCreator(
            top_resource, None, vc[config.HOST], vc[config.PORT], vc[config.TLS], ctx_factory)  # set aggregator later

        provider_registry = provreg.ProviderRegistry(
            {cnt.CS2_SERVICE_TYPE: requester_creator.create})

        link_vector = linkvector.LinkVector()

        networks = {}
        ports = {}  # { network : { port : nrmport } }

        parent_requester = None  # parent requester is set later
        aggr = aggregator.Aggregator(
            ns_agent, ports, link_vector, parent_requester, provider_registry, vc[config.POLICY], plugin)

        requester_creator.aggregator = aggr

        pc = nsi2.setupProvider(
            aggr, top_resource, ctx_factory=ctx_factory, allowed_hosts=vc.get(config.ALLOWED_HOSTS))
        aggr.parent_requester = pc

        # setup backend(s) - for now we only support one
        backend_configs = vc['backend']
        if len(backend_configs) == 0:
            log.msg('No backend specified. Running in aggregator-only mode')
            if not cnt.AGGREGATOR in vc[config.POLICY]:
                vc[config.POLICY].append(cnt.AGGREGATOR)

        else:  # at least one backend

            # This is all temporary right now... clean up later

            for backend_name, b_cfg in backend_configs.items():

                if backend_name is None or backend_name == '':
                    raise config.ConfigurationError(
                        'You need to specify backend name, use [backend:name]')

                backend_network_name = '{}:{}'.format(
                    domain_name, backend_name)

                if not config.NRM_MAP_FILE in b_cfg:  # move to verify config
                    raise config.ConfigurationError(
                        'No nrm map specified for backend')

                backend_nrm_map_file = b_cfg[config.NRM_MAP_FILE]
                if not os.path.exists(backend_nrm_map_file):  # move to verify config
                    raise config.ConfigError('nrm map file {} for backend {} does not exists'.format(
                        backend_nrm_map_file, backend_name))

                nrm_map = open(backend_nrm_map_file)
                backend_nrm_ports = nrm.parsePortSpec(nrm_map)

                link_vector.addLocalNetwork(backend_network_name)
                for np in backend_nrm_ports:
                    if np.remote_network is not None:
                        link_vector.updateVector(backend_network_name, np.name, {
                            np.remote_network: 1})  # hack
                        for network, cost in np.vectors.items():
                            link_vector.updateVector(np.name, {network: cost})
                    # build port map for aggreator to lookup
                    ports.setdefault(backend_network_name, {})[np.name] = np

                backend_service = setupBackend(
                    b_cfg, backend_network_name, backend_nrm_ports, aggr)

                networks[backend_network_name] = {
                    'backend': backend_service,
                    'nrm_ports': backend_nrm_ports
                }

                provider_registry.addProvider(
                    ns_agent.urn(), backend_network_name, backend_service)

        # fetcher
        if vc[config.PEERS]:
            fetcher_service = fetcher.FetcherService(
                link_vector, networks, vc[config.PEERS], provider_registry, ctx_factory=ctx_factory)
            fetcher_service.setServiceParent(self)
        else:
            log.msg(
                'No peers configured, will not be able to do outbound requests (UPA mode)')

        # discovery service
        opennsa_version = 'OpenNSA-' + version
        network_urns = ['{}{}'.format(
            cnt.URN_OGF_PREFIX, network_name) for network_name in networks]
        interfaces = [(cnt.CS2_PROVIDER, provider_endpoint, None),
                      (cnt.CS2_SERVICE_TYPE, provider_endpoint, None)]
        features = []
        if networks:
            features.append((cnt.FEATURE_UPA, None))
        if vc[config.PEERS]:
            features.append((cnt.FEATURE_AGGREGATOR, None))

        # view resource
        vr = viewresource.ConnectionListResource()
        top_resource.children[NSI_RESOURCE].putChild('connections', vr)

        # rest service
        if vc[config.REST]:
            rest_url = base_url + '/connections'

            rest.setupService(aggr, top_resource, vc.get(config.ALLOWED_HOSTS))

            service_endpoints.append(('REST', rest_url))
            interfaces.append((cnt.OPENNSA_REST, rest_url, None))

        for backend_network_name, no in networks.items():
            nml_resource_name = '{}.nml.xml'.format(backend_network_name)
            nml_url = '%s/NSI/%s' % (base_url, nml_resource_name)

            nml_network = nml.createNMLNetwork(
                no['nrm_ports'], backend_network_name, backend_network_name)
            can_swap_label = no['backend'].connection_manager.canSwapLabel(
                cnt.ETHERNET_VLAN)

            nml_service = nmlservice.NMLService(nml_network, can_swap_label)

            top_resource.children[NSI_RESOURCE].putChild(
                nml_resource_name.encode(), nml_service.resource())

            service_endpoints.append(('NML Topology', nml_url))
            interfaces.append((cnt.NML_SERVICE_TYPE, nml_url, None))

        # discovery service
        discovery_resource_name = b'discovery.xml'
        discovery_url = '%s/NSI/%s' % (base_url,
                                       discovery_resource_name.decode())

        ds = discoveryservice.DiscoveryService(ns_agent.urn(
        ), now, domain_name, opennsa_version, now, network_urns, interfaces, features, provider_registry, link_vector)

        discovery_resource = ds.resource()
        top_resource.children[NSI_RESOURCE].putChild(
            discovery_resource_name, discovery_resource)
        link_vector.callOnUpdate(
            lambda: discovery_resource.updateResource(ds.xml()))

        service_endpoints.append(('Discovery', discovery_url))

        # log service urls
        for service_name, url in service_endpoints:
            log.msg('{:<12} URL: {}'.format(service_name, url))

        factory = server.Site(top_resource)
        factory.log = httplog.logRequest  # default logging is weird, so we do our own

        return factory, ctx_factory

    def startService(self):

        factory, ctx_factory = self.setupServiceFactory()

        if self.vc[config.TLS]:
            internet.SSLServer(
                self.vc[config.PORT], factory, ctx_factory).setServiceParent(self)
        else:
            internet.TCPServer(self.vc[config.PORT],
                               factory).setServiceParent(self)

        # do not start sub-services until we have started this one
        twistedservice.MultiService.startService(self)

        log.msg('OpenNSA service started')

    def stopService(self):
        twistedservice.Service.stopService(self)

def createApplication(config_file=config.DEFAULT_CONFIG_FILE, debug=False, payload=False):
    application = twistedservice.Application('OpenNSA')

    try:
        configIns = Config.instance()
        cfg, vc = configIns.read_config(config_file)

        # if log file is empty string use stdout
        if vc[config.LOG_FILE]:
            log_file = open(vc[config.LOG_FILE], 'a')
        else:
            import sys
            log_file = sys.stdout

        nsa_service = OpenNSAService(vc)
        nsa_service.setServiceParent(application)

        application.setComponent(log.ILogObserver, logging.DebugLogObserver(
            log_file, debug, payload=payload).emit)
        return application

    except config.ConfigurationError as e:
        import sys
        sys.stderr.write("Configuration error: %s\n" % e)
        sys.exit(1)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

from __future__ import unicode_literals

from fabric.api import *
from fabric.contrib.project import rsync_project

PROJECT_PATH = "rustwarsaw.org"

env.roledefs = {
    'web': ["rustwarsaw@rustwarsaw.org"],
}

@task
def supervisorctl(command):
    run('supervisorctl {} rustwarsaw_org'.format(command))

@task
@roles("web")
def build_release():
    local("cargo build --release")

@task
@roles("web")
def update_binaries():
    with cd(PROJECT_PATH):
        put("target/release/rustwarsaw", "rustwarsaw")
    rsync_project("{}/www/".format(PROJECT_PATH), "www/", delete=True)

@task
@roles("web")
def deploy():
    build_release()
    supervisorctl('stop')
    update_binaries()
    supervisorctl('start')
<commit_msg>Make Fabric honor ~/.ssh/config<commit_after># -*- coding: utf-8 -*-

from __future__ import unicode_literals

from fabric.api import *
from fabric.contrib.project import rsync_project

PROJECT_PATH = "rustwarsaw.org"

env.roledefs = {
    'web': ["rustwarsaw@rustwarsaw.org"],
}
env.use_ssh_config = True

@task
def supervisorctl(command):
    run('supervisorctl {} rustwarsaw_org'.format(command))

@task
@roles("web")
def build_release():
    local("cargo build --release")

@task
@roles("web")
def update_binaries():
    with cd(PROJECT_PATH):
        put("target/release/rustwarsaw", "rustwarsaw")
    rsync_project("{}/www/".format(PROJECT_PATH), "www/", delete=True)

@task
@roles("web")
def deploy():
    build_release()
    supervisorctl('stop')
    update_binaries()
    supervisorctl('start')
<|endoftext|>