Exemple #1
0
 def inner(namespace, *args, **kwargs):
     """
     :param namespace:
         :class:`argparse.Namespace` instance. This is the only
         required/expected parameter for a command function.
     """
     LOG.setLevel(zpmlib.LOG_LEVEL_MAP.get(namespace.log_level))
     return func(namespace, *args, **kwargs)
Exemple #2
0
def bundle_project(root):
    """
    Bundle the project under root.
    """
    zapp_yaml = os.path.join(root, 'zapp.yaml')
    zapp = yaml.safe_load(open(zapp_yaml))

    zapp_name = zapp['meta']['name'] + '.zapp'

    tar = tarfile.open(zapp_name, 'w:gz')

    job = _generate_job_desc(zapp)
    job_json = json.dumps(job)
    info = tarfile.TarInfo(name='%s.json' % zapp['meta']['name'])
    # This size is only correct because json.dumps uses
    # ensure_ascii=True by default and we thus have a 1-1
    # correspondence between Unicode characters and bytes.
    info.size = len(job_json)

    LOG.info('adding %s' % info.name)
    # In Python 3, we cannot use a str or bytes object with addfile,
    # we need a BytesIO object. In Python 2, BytesIO is just StringIO.
    # Since json.dumps produces an ASCII-only Unicode string in Python
    # 3, it is safe to encode it to ASCII.
    tar.addfile(info, BytesIO(job_json.encode('ascii')))
    _add_file_to_tar(root, 'zapp.yaml', tar)

    sections = ('bundling', 'ui')
    # Keep track of the files we add, given the configuration in the zapp.yaml.
    file_add_count = 0
    for section in sections:
        for pattern in zapp.get(section, []):
            paths = glob.glob(os.path.join(root, pattern))
            if len(paths) == 0:
                LOG.warning(
                    "pattern '%(pat)s' in section '%(sec)s' matched no files",
                    dict(pat=pattern, sec=section)
                )
            else:
                for path in paths:
                    _add_file_to_tar(root, path, tar)
                file_add_count += len(paths)

    if file_add_count == 0:
        # None of the files specified in the "bundling" or "ui" sections were
        # found. Something is wrong.
        raise zpmlib.ZPMException(
            "None of the files specified in the 'bundling' or 'ui' sections of"
            " the zapp.yaml matched anything."
        )

    if not zapp.get('ui'):
        _add_ui(tar, zapp)

    tar.close()
    print('created %s' % zapp_name)
Exemple #3
0
def _add_file_to_tar(root, path, tar):
    """
    :param root:
        Root working directory.
    :param path:
        File path.
    :param tar:
        Open :class:`tarfile.TarFile` object to add the ``files`` to.
    """
    LOG.info('adding %s' % path)
    relpath = os.path.relpath(path, root)
    info = tarfile.TarInfo(name=relpath)
    info.size = os.path.getsize(path)
    tar.addfile(info, open(path, 'rb'))
Exemple #4
0
def _add_ui(tar, zapp):
    loader = jinja2.PackageLoader('zpmlib', 'templates')
    env = jinja2.Environment(loader=loader)

    for path in _DEFAULT_UI_TEMPLATES:
        tmpl = env.get_template(path)
        output = tmpl.render(zapp=zapp)
        # NOTE(larsbutler): Python 2.7.2 has a bug related to unicode and
        # cStringIO. To work around this, we need the following explicit
        # encoding. See http://bugs.python.org/issue1548891.
        output = output.encode('utf-8')
        info = tarfile.TarInfo(name=path)
        info.size = len(output)
        LOG.info('adding %s' % path)
        tar.addfile(info, BytesIO(output))
Exemple #5
0
def deploy(args):
    """Deploy a ZeroVM application

    This deploys a zapp onto Swift. The zapp can be one you have
    downloaded or produced yourself with "zpm bundle".

    You will need to know the Swift authentication URL, username,
    password, and tenant name. These can be supplied with command line
    flags (see below) or you can set the corresponding environment
    variables. The environment variables are the same as the ones used
    by the Swift command line tool, so if you're already using that to
    upload files to Swift, you will be ready to go.
    """
    LOG.info('deploying %s' % args.zapp)
    zpm.deploy_project(args)
Exemple #6
0
def deploy_project(args):
    version = args.auth_version
    conn = _get_zerocloud_conn(args)
    conn.authenticate()

    # We can now reset the auth for the web UI, if needed
    if args.no_ui_auth:
        version = '0.0'
    auth = _prepare_auth(version, args, conn)
    auth_opts = jinja2.Markup(json.dumps(auth))

    _deploy_zapp(conn, args.target, args.zapp, auth_opts)
    if args.execute:
        # for compatibility with the option name in 'zpm execute'
        args.container = args.target
        execute(args)

    LOG.info('app deployed to\n  %s/%s/' % (conn.url, args.target))
Exemple #7
0
def _post_job(url, token, json_data, http_conn=None, response_dict=None):
    # Modelled after swiftclient.client.post_account.
    headers = {'X-Auth-Token': token,
               'Accept': 'application/json',
               'X-Zerovm-Execute': '1.0',
               'Content-Type': 'application/json'}

    if http_conn:
        parsed, conn = http_conn
    else:
        parsed, conn = swiftclient.http_connection(url)

    conn.request('POST', parsed.path, json_data, headers)
    resp = conn.getresponse()
    body = resp.read()
    swiftclient.http_log((url, 'POST'), {'headers': headers}, resp, body)
    swiftclient.store_response(resp, response_dict)

    LOG.debug('response status: %s' % resp.status)
    print(body)
Exemple #8
0
def deploy_project(args):
    version = args.auth_version
    conn = _get_zerocloud_conn(args)

    # We can now reset the auth for the web UI, if needed
    if args.no_ui_auth:
        version = '0.0'

    tar = tarfile.open(args.zapp)
    zapp = yaml.safe_load(tar.extractfile('zapp.yaml'))

    path = '%s/%s' % (args.target, os.path.basename(args.zapp))
    container, obj = path.split('/', 1)
    conn.put_object(container, obj, gzip.open(args.zapp).read())

    swift_url = _get_swift_zapp_url(conn.url, path)

    job = _prepare_job(tar, zapp, swift_url)
    path = '%s/%s.json' % (args.target, zapp['meta']['name'])
    container, obj = path.split('/', 1)
    conn.put_object(container, obj, json.dumps(job))

    deploy = {'version': version}
    if version == '0.0':
        deploy['swiftUrl'] = conn.url
    elif version == '1.0':
        deploy['authUrl'] = args.auth
        deploy['username'] = args.user
        deploy['password'] = args.key
    else:
        # TODO(mg): inserting the username and password in the
        # uploaded file makes testing easy, but should not be done in
        # production. See issue #44.
        deploy['authUrl'] = args.os_auth_url
        deploy['tenant'] = args.os_tenant_name
        deploy['username'] = args.os_username
        deploy['password'] = args.os_password
    auth_opts = jinja2.Markup(json.dumps(deploy))
    for path in _find_ui_uploads(zapp, tar):
        # Upload UI files after expanding deployment parameters
        tmpl = jinja2.Template(tar.extractfile(path).read())
        output = tmpl.render(auth_opts=auth_opts)
        container, obj = ('%s/%s' % (args.target, path)).split('/', 1)
        conn.put_object(container, obj, output)

    if args.execute:
        job_details = BytesIO()
        pprint.pprint(job, stream=job_details)
        job_details.seek(0)
        LOG.debug('job template:\n%s' % job_details.read())
        LOG.info('executing')
        conn.post_job(job)

    LOG.info('app deployed to\n  %s/%s/' % (conn.url, args.target))