Пример #1
0
    def brand(self, *rest):

        brand_id = conf['branding'].get('brand_id', 'default')

        # return doc
        if request.path.startswith('/brand/doc/'):
            tmpl = normpath(
                request.path.replace('/brand',
                                     conf.app.assets_root + '/' + brand_id))
            if brand_id != 'default' and isfile(tmpl):
                f = open(tmpl)
                response.headers['Content-Type'] = 'text/html'
                response.app_iter = FileIter(f)
                return
            else:
                tmpl = request.path.replace('/brand', '')
                return render(tmpl, _gen_context_())

        # return requested brand asset
        path = normpath(
            request.path.replace('/brand',
                                 conf.app.assets_root + '/' + brand_id))
        if not isfile(path):
            path = request.path.replace('/brand',
                                        conf.app.assets_root + '/default/')
        if not isfile(path):
            abort(404)

        f = open(path)
        response.headers['Content-Type'] = guess_type(f.name)
        response.app_iter = FileIter(f)
Пример #2
0
    def key(self):
        """
        Serves the public SSH key for the user that own the current service
        """
        # look for the ssh key of the current user
        public_key_path = os.path.expanduser('~/.ssh/id_rsa.pub')
        ssh_dir = os.path.dirname(public_key_path)

        if not os.path.isdir(ssh_dir):
            msg = '.ssh directory not found: %s' % ssh_dir
            logger.error(msg)
            error(500, msg)

        if not os.path.exists(public_key_path):
            msg = 'expected public key not found: %s' % public_key_path
            logger.error(msg)
            error(500, msg)

        # define the file to download
        response.headers[
            'Content-Disposition'] = 'attachment; filename=id_rsa.pub'
        with open(public_key_path) as key_contents:
            key = StringIO()
            key.write(key_contents.read())
            key.seek(0)
        response.app_iter = FileIter(key)
Пример #3
0
    def __call__(self, req):
        if req.method not in ('GET', 'HEAD'):
            return exc.HTTPMethodNotAllowed("You cannot %s a file" %
                                            req.method)

        disposition = req.GET.get('disposition', 'attachment')
        try:
            file = self.open()
        except (IOError, OSError) as e:
            msg = "You are not permitted to view this file (%s)" % e
            return exc.HTTPForbidden(msg)

        if 'wsgi.file_wrapper' in req.environ:
            app_iter = req.environ['wsgi.file_wrapper'](file, BLOCK_SIZE)
        else:
            app_iter = FileIter(file)

        return Response(
            app_iter=app_iter,
            content_length=self.get_size(),
            content_type=self.mimetype,
            content_encoding=self.encoding,
            content_disposition='%s; filename="%s"' % (
                disposition, self.filename),
            # @@ etag
        ).conditional_response_app
Пример #4
0
    def get(self, id):
        LOG.info("Fetch resource.", resource={'type': self.type, 'id': id})

        download = strutils.bool_from_string(
            pecan.request.GET.get('download', False))
        func_db = db_api.get_function(id)
        ctx = context.get_ctx()

        if not download:
            pecan.override_template('json')
            return resources.Function.from_dict(func_db.to_dict()).to_dict()
        else:
            source = func_db.code['source']

            if source == 'package':
                f = self.storage_provider.retrieve(ctx.projectid, id)
            elif source == 'swift':
                container = func_db.code['swift']['container']
                obj = func_db.code['swift']['object']
                f = swift_util.download_object(container, obj)
            else:
                msg = 'Download image function is not allowed.'
                pecan.abort(status_code=405,
                            detail=msg,
                            headers={'Server-Error-Message': msg})

            pecan.response.app_iter = (f if isinstance(f, collections.Iterable)
                                       else FileIter(f))
            pecan.response.headers['Content-Type'] = 'application/zip'
            pecan.response.headers['Content-Disposition'] = (
                'attachment; filename="%s"' % os.path.basename(func_db.name))
Пример #5
0
    def index(self, **kw):
        try:
            conf.build_map[self.name]
        except (AttributeError, KeyError):
            abort(404)

        script = make_setup_script(self.name, **kw)

        response.headers[
            'Content-Disposition'] = 'attachment; filename=setup.sh'
        response.app_iter = FileIter(script)
Пример #6
0
 def ansible(self):
     """
     Servers the pre-made ansible source to avoid installation of packages
     """
     try:
         conf.setup_ansible
     except (AttributeError, KeyError):
         abort(404, 'setup_ansible value is not configured')
     response.headers[
         'Content-Disposition'] = 'attachment; filename=ansible.tar.gz'
     f = open(conf.setup_ansible, 'rb')
     response.app_iter = FileIter(f)
Пример #7
0
def vendor_passthru(ident, method, topic, data=None, driver_passthru=False):
    """Call a vendor passthru API extension.

    Call the vendor passthru API extension and process the method response
    to set the right return code for methods that are asynchronous or
    synchronous; Attach the return value to the response object if it's
    being served statically.

    :param ident: The resource identification. For node's vendor passthru
        this is the node's UUID, for driver's vendor passthru this is the
        driver's name.
    :param method: The vendor method name.
    :param topic: The RPC topic.
    :param data: The data passed to the vendor method. Defaults to None.
    :param driver_passthru: Boolean value. Whether this is a node or
        driver vendor passthru. Defaults to False.
    :returns: A WSME response object to be returned by the API.

    """
    if not method:
        raise wsme.exc.ClientSideError(_("Method not specified"))

    if data is None:
        data = {}

    http_method = pecan.request.method.upper()
    params = (pecan.request.context, ident, method, http_method, data, topic)
    if driver_passthru:
        response = pecan.request.rpcapi.driver_vendor_passthru(*params)
    else:
        response = pecan.request.rpcapi.vendor_passthru(*params)

    status_code = 202 if response['async'] else 200
    return_value = response['return']
    response_params = {'status_code': status_code}

    # Attach the return value to the response object
    if response.get('attach'):
        if isinstance(return_value, six.text_type):
            # If unicode, convert to bytes
            return_value = return_value.encode('utf-8')
        file_ = wsme.types.File(content=return_value)
        pecan.response.app_iter = FileIter(file_.file)
        # Since we've attached the return value to the response
        # object the response body should now be empty.
        return_value = None
        response_params['return_type'] = None

    return wsme.api.Response(return_value, **response_params)
Пример #8
0
    def index(self):
        """
        Special method for internal redirect URI's so that webservers (like
        Nginx) can serve downloads to clients while the app just delegates.
        This method will require an Nginx configuration that points to
        resources and match `binary_root` URIs::

            location /home/ubuntu/repos/ {
              internal;
              alias   /files/;
            }

        `alias` can be anything, it would probably make sense to have a set of rules that allow
        distinct URIs, like::

            location /home/ubuntu/repos/rpm-firefly/ {
              internal;
              alias   /files/rpm-firefly/;
            }


        There are two ways to get binaries into this app: via existing files in
        certain paths POSTing JSON to the arch/ endpoint, or via actual upload
        of the binary. So if many locations need to be supported, they each
        need to have a corresponding section in Nginx to be configured.
        """
        if not self.binary:
            abort(404)
        # we need to slap some headers so Nginx can serve this
        # TODO: maybe disable this for testing?
        # XXX Maybe we don't need to set Content-Disposition here?
        response.headers[
            'Content-Disposition'] = 'attachment; filename=%s' % str(
                self.binary.name)
        if conf.delegate_downloads is False:
            f = open(self.binary.path, 'rb')
            response.app_iter = FileIter(f)
        else:
            relative_path = self.binary.path.split(
                pecan.conf.binary_root)[-1].strip('/')
            # FIXME: this should be read from configuration, this is not configurable
            # at the moment and relies on the nginx config being properly set
            path = os.path.join('/b/', relative_path)
            logger.info('setting path header: %s', path)
            response.headers['X-Accel-Redirect'] = path
Пример #9
0
    def save_file(self, file_obj):
        dir_path = self.create_directory()
        if self.binary_name in os.listdir(dir_path):
            # resource exists so we will update it
            response.status = 200
        else:
            # we will create a resource
            response.status = 201

        destination = os.path.join(dir_path, self.binary_name)

        with open(destination, 'wb') as f:
            file_iterable = FileIter(file_obj)
            for chunk in file_iterable:
                f.write(chunk)

        # return the full path to the saved object:
        return destination
Пример #10
0
    def get(self, id):
        """Get function information or download function package.

        This method can support HTTP request using either
        'Accept:application/json' or no 'Accept' header.
        """
        ctx = context.get_ctx()
        acl.enforce('function:get', ctx)

        download = strutils.bool_from_string(
            pecan.request.GET.get('download', False)
        )
        func_db = db_api.get_function(id)

        if not download:
            LOG.info("Getting function %s.", id)
            pecan.override_template('json')
            return resources.Function.from_db_obj(func_db).to_dict()

        LOG.info("Downloading function %s", id)
        source = func_db.code['source']

        if source == constants.PACKAGE_FUNCTION:
            f = self.storage_provider.retrieve(func_db.project_id, id,
                                               func_db.code['md5sum'])
        elif source == constants.SWIFT_FUNCTION:
            container = func_db.code['swift']['container']
            obj = func_db.code['swift']['object']
            f = swift_util.download_object(container, obj)
        else:
            msg = 'Download image function is not allowed.'
            pecan.abort(
                status_code=405,
                detail=msg,
                headers={'Server-Error-Message': msg}
            )

        pecan.response.app_iter = (f if isinstance(f, collections.Iterable)
                                   else FileIter(f))
        pecan.response.headers['Content-Type'] = 'application/zip'
        pecan.response.headers['Content-Disposition'] = (
            'attachment; filename="%s"' % id
        )
Пример #11
0
    def key(self):
        """
        Serves the public SSH key for the user that own the current service
        """
        # look for the ssh key of the current user
        private_key_path = os.path.expanduser('~/.ssh/id_rsa')
        public_key_path = os.path.expanduser('~/.ssh/id_rsa.pub')
        ssh_dir = os.path.dirname(public_key_path)

        if not os.path.isdir(ssh_dir):
            logger.warning('.ssh directory not found, creating one at: %s',
                           ssh_dir)
            mkdir(ssh_dir)

        # if there isn't one create it
        if not os.path.exists(public_key_path):
            logger.warning('expected public key not found: %s',
                           public_key_path)
            logger.warning('will create new ssh key pair')
            # create one
            command = [
                'ssh-keygen',
                '-q',
                '-t',
                'rsa',
                '-N',
                '',
                '-f',
                private_key_path,
            ]
            out, err, code = process.run(command, send_input='y\n')
            if code != 0:
                error(500, err)

        # define the file to download
        response.headers[
            'Content-Disposition'] = 'attachment; filename=id_rsa.pub'
        with open(public_key_path) as key_contents:
            key = StringIO()
            key.write(key_contents.read())
            key.seek(0)
        response.app_iter = FileIter(key)
Пример #12
0
    def get(self, id):
        LOG.info("Fetch function [id=%s]", id)

        download = strutils.bool_from_string(
            pecan.request.GET.get('download', False))
        func_db = db_api.get_function(id)
        ctx = context.get_ctx()

        if not download:
            pecan.override_template('json')
            return resources.Function.from_dict(func_db.to_dict()).to_dict()
        else:
            f = self.storage_provider.retrieve(
                ctx.projectid,
                id,
            )

            pecan.response.app_iter = FileIter(f)
            pecan.response.headers['Content-Type'] = 'application/zip'
            pecan.response.headers['Content-Disposition'] = (
                'attachment; filename="%s"' % os.path.basename(f.name))
Пример #13
0
    def save_file(self, file_obj):
        # TODO: we should just use self.binary.path for this
        dir_path = self.create_directory()
        if self.binary_name in os.listdir(dir_path):
            # resource exists so we will update it
            response.status = 200
        else:
            # TODO: enforce this.
            # we will create a resource, but this SHOULD NOT HAPPEN
            # because we are PUT not POST
            response.status = 201

        destination = os.path.join(dir_path, self.binary_name)

        with open(destination, 'wb') as f:
            file_iterable = FileIter(file_obj)
            for chunk in file_iterable:
                f.write(chunk)

        # return the full path to the saved object:
        return destination
Пример #14
0
    def index(self, **kw):
        try:
            conf.build_map[self.name]
        except (AttributeError, KeyError):
            abort(404)

        playbook = conf.build_map[self.name]['playbook']
        playbook_path = conf.build_map[self.name]['playbook_path']

        files_to_compress = []
        tmp_dir = tempfile.mkdtemp()
        yml_file = os.path.join(tmp_dir, 'main.yml')
        copyfile(playbook, yml_file)
        files_to_compress.append(playbook_path)
        files_to_compress.append(yml_file)

        playbook = tar_czf(files_to_compress)

        response.headers[
            'Content-Disposition'] = 'attachment; filename=playbook.tar.gz'
        f = open(playbook, 'rb')
        response.app_iter = FileIter(f)
Пример #15
0
 def __call__(self, req):
     # Adapted from `FileApp.__call__()`.
     if 'wsgi.file_wrapper' in req.environ:
         app_iter = req.environ['wsgi.file_wrapper'](self.file, BLOCK_SIZE)
     else:
         app_iter = FileIter(self.file)
     last_modified = datetime.datetime.now()
     # Need to seek to end of cStringIO.StringIO buffer to get size.
     self.file.seek(0, os.SEEK_END)
     content_length = self.file.tell()
     # Remember to seek back to the beginning before the buffer is sent!
     self.file.seek(0)
     content_type, content_encoding = mimetypes.guess_type(self.filename)
     content_disposition = "attachment; filename=%s" % self.filename
     accept_ranges = 'bytes'
     return Response(app_iter=app_iter,
                     last_modified=last_modified,
                     content_length=content_length,
                     content_type=content_type,
                     content_encoding=content_encoding,
                     content_disposition=content_disposition,
                     accept_ranges=accept_ranges,
                     conditional_response=True)
Пример #16
0
    def get(self, function_id, version):
        """Get function version or download function version package.

        This method can support HTTP request using either
        'Accept:application/json' or no 'Accept' header.
        """
        ctx = context.get_ctx()
        acl.enforce('function_version:get', ctx)

        download = strutils.bool_from_string(
            pecan.request.GET.get('download', False)
        )
        version = int(version)

        version_db = db_api.get_function_version(function_id, version)

        if not download:
            LOG.info("Getting version %s for function %s.", version,
                     function_id)
            pecan.override_template('json')
            return resources.FunctionVersion.from_db_obj(version_db).to_dict()

        LOG.info("Downloading version %s for function %s.", version,
                 function_id)

        f = self.storage_provider.retrieve(version_db.project_id, function_id,
                                           None, version=version)

        if isinstance(f, collections.Iterable):
            pecan.response.app_iter = f
        else:
            pecan.response.app_iter = FileIter(f)
        pecan.response.headers['Content-Type'] = 'application/zip'
        pecan.response.headers['Content-Disposition'] = (
            'attachment; filename="%s_%s"' % (function_id, version)
        )
Пример #17
0
 def _default(self, view, *remainder):
     body = media.get_file(request.path[12:])
     mime_type = guess_type(request.path[12:])[0]
     r = Response(content_type=mime_type)
     r.app_iter = FileIter(body)
     return r
Пример #18
0
 def agent(self):
     script = make_agent_script(request.url, request.client_addr)
     response.headers[
         'Content-Disposition'] = 'attachment; filename=agent-setup.sh'
     response.app_iter = FileIter(script)
Пример #19
0
 def index(self):
     script = make_setup_script(request.url)
     response.headers[
         'Content-Disposition'] = 'attachment; filename=setup.sh'
     response.app_iter = FileIter(script)