Esempio n. 1
0
def handler(catchall_path=None, fmt=None, target=None):
    '''
    Main endpoint handler; generic for every endpoint, including catchall.
    Handles the catchall, anything with <.fmt>, anything with embedded
    <target>.  Partial match or ?help cause the HTML-table
    "show_human_help" output.
    '''

    ep = catchall_path or flask.request.endpoint
    ep = ep.replace('.<fmt>', '')

    if ep[0] != '/':
        ep = '/' + ep

    # demand that endpoint begin with app.ceph_baseurl
    if not ep.startswith(app.ceph_baseurl):
        return make_response(fmt, '', 'Page not found', 404)

    rel_ep = ep[len(app.ceph_baseurl) + 1:]

    # Extensions override Accept: headers override defaults
    if not fmt:
        if 'application/json' in flask.request.accept_mimetypes.values():
            fmt = 'json'
        elif 'application/xml' in flask.request.accept_mimetypes.values():
            fmt = 'xml'

    prefix = ''
    pgid = None
    cmdtarget = 'mon', ''

    if target:
        # got tell/<target>; validate osdid or pgid
        name = CephOsdName()
        pgidobj = CephPgid()
        try:
            name.valid(target)
        except ArgumentError:
            # try pgid
            try:
                pgidobj.valid(target)
            except ArgumentError:
                return flask.make_response("invalid osdid or pgid", 400)
            else:
                # it's a pgid
                pgid = pgidobj.val
                cmdtarget = 'pg', pgid
        else:
            # it's an osd
            cmdtarget = name.nametype, name.nameid

        # prefix does not include tell/<target>/
        prefix = ' '.join(rel_ep.split('/')[2:]).strip()
    else:
        # non-target command: prefix is entire path
        prefix = ' '.join(rel_ep.split('/')).strip()

    # show "match as much as you gave me" help for unknown endpoints
    if ep not in app.ceph_urls:
        helptext = show_human_help(prefix)
        if helptext:
            resp = flask.make_response(helptext, 400)
            resp.headers['Content-Type'] = 'text/html'
            return resp
        else:
            return make_response(fmt, '', 'Invalid endpoint ' + ep, 400)

    found = None
    exc = ''
    for urldict in app.ceph_urls[ep]:
        if flask.request.method not in urldict['methods']:
            continue
        paramsig = urldict['paramsig']

        # allow '?help' for any specifically-known endpoint
        if 'help' in flask.request.args:
            response = flask.make_response('{0}: {1}'.
                                           format(prefix +
                                                  concise_sig(paramsig),
                                                  urldict['help']))
            response.headers['Content-Type'] = 'text/plain'
            return response

        # if there are parameters for this endpoint, process them
        if paramsig:
            args = {}
            for k, l in flask.request.args.iterlists():
                if len(l) == 1:
                    args[k] = l[0]
                else:
                    args[k] = l

            # is this a valid set of params?
            try:
                argdict = validate(args, paramsig)
                found = urldict
                break
            except Exception as e:
                exc += str(e)
                continue
        else:
            if flask.request.args:
                continue
            found = urldict
            argdict = {}
            break

    if not found:
        return make_response(fmt, '', exc + '\n', 400)

    argdict['format'] = fmt or 'plain'
    argdict['module'] = found['module']
    argdict['perm'] = found['perm']
    if pgid:
        argdict['pgid'] = pgid

    if not cmdtarget:
        cmdtarget = ('mon', '')

    app.logger.debug('sending command prefix %s argdict %s', prefix, argdict)
    ret, outbuf, outs = json_command(app.ceph_cluster, prefix=prefix,
                                     target=cmdtarget,
                                     inbuf=flask.request.data, argdict=argdict)
    if ret:
        return make_response(fmt, '', 'Error: {0} ({1})'.format(outs, ret), 400)

    response = make_response(fmt, outbuf, outs or 'OK', 200)
    if fmt:
        contenttype = 'application/' + fmt.replace('-pretty', '')
    else:
        contenttype = 'text/plain'
    response.headers['Content-Type'] = contenttype
    return response
Esempio n. 2
0
def handler(catchall_path=None, fmt=None, target=None):
    '''
    Main endpoint handler; generic for every endpoint, including catchall.
    Handles the catchall, anything with <.fmt>, anything with embedded
    <target>.  Partial match or ?help cause the HTML-table
    "show_human_help" output.
    '''

    ep = catchall_path or flask.request.endpoint
    ep = ep.replace('.<fmt>', '')

    if ep[0] != '/':
        ep = '/' + ep

    # demand that endpoint begin with app.ceph_baseurl
    if not ep.startswith(app.ceph_baseurl):
        return make_response(fmt, '', 'Page not found', 404)

    rel_ep = ep[len(app.ceph_baseurl) + 1:]

    # Extensions override Accept: headers override defaults
    if not fmt:
        if 'application/json' in flask.request.accept_mimetypes.values():
            fmt = 'json'
        elif 'application/xml' in flask.request.accept_mimetypes.values():
            fmt = 'xml'

    prefix = ''
    pgid = None
    cmdtarget = 'mon', ''

    if target:
        # got tell/<target>; validate osdid or pgid
        name = CephOsdName()
        pgidobj = CephPgid()
        try:
            name.valid(target)
        except ArgumentError:
            # try pgid
            try:
                pgidobj.valid(target)
            except ArgumentError:
                return flask.make_response("invalid osdid or pgid", 400)
            else:
                # it's a pgid
                pgid = pgidobj.val
                cmdtarget = 'pg', pgid
        else:
            # it's an osd
            cmdtarget = name.nametype, name.nameid

        # prefix does not include tell/<target>/
        prefix = ' '.join(rel_ep.split('/')[2:]).strip()
    else:
        # non-target command: prefix is entire path
        prefix = ' '.join(rel_ep.split('/')).strip()

    # show "match as much as you gave me" help for unknown endpoints
    if ep not in app.ceph_urls:
        helptext = show_human_help(prefix)
        if helptext:
            resp = flask.make_response(helptext, 400)
            resp.headers['Content-Type'] = 'text/html'
            return resp
        else:
            return make_response(fmt, '', 'Invalid endpoint ' + ep, 400)

    found = None
    exc = ''
    for urldict in app.ceph_urls[ep]:
        if flask.request.method not in urldict['methods']:
            continue
        paramsig = urldict['paramsig']

        # allow '?help' for any specifically-known endpoint
        if 'help' in flask.request.args:
            response = flask.make_response('{0}: {1}'.format(
                prefix + concise_sig(paramsig), urldict['help']))
            response.headers['Content-Type'] = 'text/plain'
            return response

        # if there are parameters for this endpoint, process them
        if paramsig:
            args = {}
            for k, l in flask.request.args.iterlists():
                if len(l) == 1:
                    args[k] = l[0]
                else:
                    args[k] = l

            # is this a valid set of params?
            try:
                argdict = validate(args, paramsig)
                found = urldict
                break
            except Exception as e:
                exc += str(e)
                continue
        else:
            if flask.request.args:
                continue
            found = urldict
            argdict = {}
            break

    if not found:
        return make_response(fmt, '', exc + '\n', 400)

    argdict['format'] = fmt or 'plain'
    argdict['module'] = found['module']
    argdict['perm'] = found['perm']
    if pgid:
        argdict['pgid'] = pgid

    if not cmdtarget:
        cmdtarget = ('mon', '')

    app.logger.debug('sending command prefix %s argdict %s', prefix, argdict)

    for _ in range(DEFAULT_TRIES):
        ret, outbuf, outs = json_command(app.ceph_cluster,
                                         prefix=prefix,
                                         target=cmdtarget,
                                         inbuf=flask.request.data,
                                         argdict=argdict,
                                         timeout=DEFAULT_TIMEOUT)
        if ret != -errno.EINTR:
            break
    else:
        return make_response(fmt, '', 'Timedout: {0} ({1})'.format(outs, ret),
                             504)
    if ret:
        return make_response(fmt, '', 'Error: {0} ({1})'.format(outs, ret),
                             400)

    response = make_response(fmt, outbuf, outs or 'OK', 200)
    if fmt:
        contenttype = 'application/' + fmt.replace('-pretty', '')
    else:
        contenttype = 'text/plain'
    response.headers['Content-Type'] = contenttype
    return response
Esempio n. 3
0
def handler(catchall_path=None, fmt=None, target=None):
    """
    Main endpoint handler; generic for every endpoint, including catchall.
    Handles the catchall, anything with <.fmt>, anything with embedded
    <target>.  Partial match or ?help cause the HTML-table
    "show_human_help" output.
    """

    ep = catchall_path or flask.request.endpoint
    ep = ep.replace(".<fmt>", "")

    if ep[0] != "/":
        ep = "/" + ep

    # demand that endpoint begin with app.ceph_baseurl
    if not ep.startswith(app.ceph_baseurl):
        return make_response(fmt, "", "Page not found", 404)

    rel_ep = ep[len(app.ceph_baseurl) + 1 :]

    # Extensions override Accept: headers override defaults
    if not fmt:
        if "application/json" in flask.request.accept_mimetypes.values():
            fmt = "json"
        elif "application/xml" in flask.request.accept_mimetypes.values():
            fmt = "xml"

    prefix = ""
    pgid = None
    cmdtarget = "mon", ""

    if target:
        # got tell/<target>; validate osdid or pgid
        name = CephOsdName()
        pgidobj = CephPgid()
        try:
            name.valid(target)
        except ArgumentError:
            # try pgid
            try:
                pgidobj.valid(target)
            except ArgumentError:
                return flask.make_response("invalid osdid or pgid", 400)
            else:
                # it's a pgid
                pgid = pgidobj.val
                cmdtarget = "pg", pgid
        else:
            # it's an osd
            cmdtarget = name.nametype, name.nameid

        # prefix does not include tell/<target>/
        prefix = " ".join(rel_ep.split("/")[2:]).strip()
    else:
        # non-target command: prefix is entire path
        prefix = " ".join(rel_ep.split("/")).strip()

    # show "match as much as you gave me" help for unknown endpoints
    if not ep in app.ceph_urls:
        helptext = show_human_help(prefix)
        if helptext:
            resp = flask.make_response(helptext, 400)
            resp.headers["Content-Type"] = "text/html"
            return resp
        else:
            return make_response(fmt, "", "Invalid endpoint " + ep, 400)

    found = None
    exc = ""
    for urldict in app.ceph_urls[ep]:
        if flask.request.method not in urldict["methods"]:
            continue
        paramsig = urldict["paramsig"]

        # allow '?help' for any specifically-known endpoint
        if "help" in flask.request.args:
            response = flask.make_response("{0}: {1}".format(prefix + concise_sig(paramsig), urldict["help"]))
            response.headers["Content-Type"] = "text/plain"
            return response

        # if there are parameters for this endpoint, process them
        if paramsig:
            args = {}
            for k, l in flask.request.args.iterlists():
                if len(l) == 1:
                    args[k] = l[0]
                else:
                    args[k] = l

            # is this a valid set of params?
            try:
                argdict = validate(args, paramsig)
                found = urldict
                break
            except Exception as e:
                exc += str(e)
                continue
        else:
            if flask.request.args:
                continue
            found = urldict
            argdict = {}
            break

    if not found:
        return make_response(fmt, "", exc + "\n", 400)

    argdict["format"] = fmt or "plain"
    argdict["module"] = found["module"]
    argdict["perm"] = found["perm"]
    if pgid:
        argdict["pgid"] = pgid

    if not cmdtarget:
        cmdtarget = ("mon", "")

    app.logger.debug("sending command prefix %s argdict %s", prefix, argdict)
    ret, outbuf, outs = json_command(
        app.ceph_cluster, prefix=prefix, target=cmdtarget, inbuf=flask.request.data, argdict=argdict
    )
    if ret:
        return make_response(fmt, "", "Error: {0} ({1})".format(outs, ret), 400)

    response = make_response(fmt, outbuf, outs or "OK", 200)
    if fmt:
        contenttype = "application/" + fmt.replace("-pretty", "")
    else:
        contenttype = "text/plain"
    response.headers["Content-Type"] = contenttype
    return response