예제 #1
0
def delete(driver, name):
    """
Deletes an object if it matches the given driver

 *  Requires HTTP parameters ``name``

Examples:

.. code:: bash

    $ ${post} -d 'name=servercreated' ${server_url}/entity/basicserver
    [
        "/basicserver/servercreated"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${delete} ${server_url}/entity/nondriver/servercreated
    "Requested driver \"nondriver\" does not exist"
    HTTP: 412
    Content-type: application/json

.. code:: bash

    $ ${delete} ${server_url}/entity/basicserver/servercreated
    HTTP: 204
    Content-type:

.. code:: bash

    $ ${delete} ${server_url}/entity/basicserver/servercreated
    HTTP: 404
    Content-type: None

Will create a new ``servercreated`` object with a ``basicserver`` driver. Then
it will proceed to delete it. If the operation succeeded, it will return a 200,
if the object doesn't exist, it will return a 404.

"""

    if driver not in clusto.driverlist:
        return util.dumps('Requested driver "%s" does not exist' % (driver, ),
                          412)

    notfound = None

    try:
        obj = clusto.get_by_name(name)
    except LookupError:
        notfound = name

    code = 204
    if notfound:
        code = 404
    else:
        obj.entity.delete()

    return bottle.HTTPResponse('', code, headers={'Content-type': None})
예제 #2
0
def show(driver, name):
    """
Returns a json representation of the given object

Example:

.. code:: bash

    $ ${post} -d 'name=showpool' ${server_url}/entity/pool
    [
        "/pool/showpool"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${get} ${server_url}/entity/pool/showpool
    {
        "attrs": [],
        "contents": [],
        "driver": "pool",
        "name": "showpool",
        "parents": [],
        "type": "pool"
    }
    HTTP: 200
    Content-type: application/json

Will return a JSON representation of the previously created ``showpool``.

.. code:: bash

    $ ${get} ${server_url}/entity/basicserver/showpool
    "The driver for object \"showpool\" is not \"basicserver\""
    HTTP: 409
    Content-type: application/json

Will yield a 409 (Conflict) because the object ``showpool`` is not a
``basicserver`` object.
"""

    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)

    return util.dumps(util.show(obj))
예제 #3
0
def show(driver, name):
    """
Returns a json representation of the given object

Example:

.. code:: bash

    $ ${post} -d 'name=showpool' ${server_url}/entity/pool
    [
        "/pool/showpool"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${get} ${server_url}/entity/pool/showpool
    {
        "attrs": [],
        "contents": [],
        "driver": "pool",
        "name": "showpool",
        "parents": [],
        "type": "pool"
    }
    HTTP: 200
    Content-type: application/json

Will return a JSON representation of the previously created ``showpool``.

.. code:: bash

    $ ${get} ${server_url}/entity/basicserver/showpool
    "The driver for object \"showpool\" is not \"basicserver\""
    HTTP: 409
    Content-type: application/json

Will yield a 409 (Conflict) because the object ``showpool`` is not a
``basicserver`` object.
"""

    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)

    return util.dumps(util.show(obj))
예제 #4
0
def delete(driver, name):
    """
Deletes an object if it matches the given driver

 *  Requires HTTP parameters ``name``

Examples:

.. code:: bash

    $ ${post} -d 'name=servercreated' ${server_url}/entity/basicserver
    [
        "/basicserver/servercreated"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${delete} ${server_url}/entity/nondriver/servercreated
    "Requested driver \"nondriver\" does not exist"
    HTTP: 412
    Content-type: application/json

.. code:: bash

    $ ${delete} ${server_url}/entity/basicserver/servercreated
    HTTP: 204
    Content-type:

.. code:: bash

    $ ${delete} ${server_url}/entity/basicserver/servercreated
    HTTP: 404
    Content-type: None

Will create a new ``servercreated`` object with a ``basicserver`` driver. Then
it will proceed to delete it. If the operation succeeded, it will return a 200,
if the object doesn't exist, it will return a 404.

"""

    if driver not in clusto.driverlist:
        return util.dumps('Requested driver "%s" does not exist' % (driver,), 412)

    notfound = None

    try:
        obj = clusto.get_by_name(name)
    except LookupError:
        notfound = name

    code = 204
    if notfound:
        code = 404
    else:
        obj.entity.delete()

    return bottle.HTTPResponse('', code, headers={'Content-type': None})
예제 #5
0
def _write_attrs(method, name, **kwargs):
    """
Helper method for reduced code between POST and PUT.
Returns a response for the methods calling it.
"""
    if method == 'set':
        code = 200
    if method == 'add':
        code = 201
    else:
        util.dumps('"%s" is neither set nor add. How did you get here?' % method, 400)

    request_kwargs = dict(request.params.items())
    driver = kwargs.get('driver', None)
    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)

    try:
        # Merge URL values and kwarg values, but do not allow conflicts.
        for k, v in request_kwargs.items():
            if kwargs.get(k) is not None and kwargs[k] != v:
                raise ValueError('Two different values were submitted for "%s": %s' % (k, [kwargs[k], v]))
            kwargs[k] = v

        # Additionally capture a value error if the json is bad.
        json_kwargs = request.json
    except ValueError as ve:
        return util.dumps('%s' % (ve,), 400)

    if json_kwargs:
        if request.query:
            return util.dumps('Error: json and query params may not be passed in the same request.', 400)
        kwargs = json_kwargs

    # Adds support for bulk attr posting.
    attrs = [kwargs] if isinstance(kwargs, dict) else kwargs
    # Check for malformed data or missing pieces before adding any attrs.
    for attr in attrs:
        for k in ('key', 'value'):
            if k not in attr.keys():
                bottle.abort(412, 'Provide at least "key" and "value"')

        if 'number' in attr:
            try:
                attr['number'] = int(attr['number'])
            except ValueError as ve:
                return util.dumps('%s' % (ve,), 400)

        if 'datatype' in attr:
            datatype = attr.pop('datatype')
            mask = attr.pop('mask', '%Y-%m-%dT%H:%M:%S.%f')
            attr['value'] = util.typecast(attr['value'], datatype, mask=mask)

    for attr in attrs:
        getattr(obj, method + '_attr')(**attr)

    return util.dumps([util.unclusto(_) for _ in obj.attrs()], code)
예제 #6
0
def action(driver, name):
    """
Inserts/removes the given device from the request parameters into/from the object

Example:

.. code:: bash

    $ ${post} -d 'name=pool1' ${server_url}/entity/pool
    [
        "/pool/pool1"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'name=server1' ${server_url}/entity/basicserver
    [
        "/basicserver/server1"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'device=server1' -d 'action=insert' ${server_url}/entity/pool/pool1
    {
        "attrs": [],
        "contents": [
            "/basicserver/server1"
        ],
        "driver": "pool",
        "name": "pool1",
        "parents": [],
        "type": "pool"
    }
    HTTP: 200
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'device=server1' -d 'action=remove' ${server_url}/entity/pool/pool1
    {
        "attrs": [],
        "contents": [],
        "driver": "pool",
        "name": "pool1",
        "parents": [],
        "type": "pool"
    }
    HTTP: 200
    Content-type: application/json

Will:

#.  Create a pool entity called ``pool1``
#.  Create a basicserver entity called ``server1``
#.  Insert the entity ``server1`` into the entity ``pool1``
#.  Remove the entity ``server1`` from the entity ``pool1``

Examples:

.. code:: bash

    $ ${post} -d 'name=pool2' ${server_url}/entity/pool
    [
        "/pool/pool2"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'name=server2' -d 'name=server3' ${server_url}/entity/basicserver
    [
        "/basicserver/server2",
        "/basicserver/server3"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'device=server2' -d 'device=server3' -d 'action=insert' ${server_url}/entity/pool/pool2
    {
        "attrs": [],
        "contents": [
            "/basicserver/server2",
            "/basicserver/server3"
        ],
        "driver": "pool",
        "name": "pool2",
        "parents": [],
        "type": "pool"
    }
    HTTP: 200
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'device=server2' -d 'device=server3' -d 'action=remove' ${server_url}/entity/pool/pool2
    {
        "attrs": [],
        "contents": [],
        "driver": "pool",
        "name": "pool2",
        "parents": [],
        "type": "pool"
    }
    HTTP: 200
    Content-type: application/json

The above will:

#.  Create a pool entity called ``pool2``
#.  Create two basicserver entities called ``server2`` and ``server3``
#.  Insert both basicserver entities into the pool entity
#.  Remove both basicserver entities from the pool entity

"""

    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)
    devices = request.params.getall('device')
    action = request.params.get('action')

    if not action:
        bottle.abort(400, 'Parameter \'action\' is required.')

    devobjs = []
    notfound = []
    for device in devices:
        try:
            devobjs.append(clusto.get_by_name(device))
        except LookupError:
            notfound.append(device)

    if notfound:
        bottle.abort(
            404, 'Objects %s do not exist and cannot be used with "%s"' % (
                ','.join(notfound),
                name,
            ))

    if action == 'insert':
        for devobj in devobjs:
            if devobj not in obj:
                obj.insert(devobj)

    elif action == 'remove':
        for devobj in devobjs:
            if devobj in obj:
                obj.remove(devobj)

    else:
        bottle.abort(400, '%s is not a valid action.' % (action))

    return show(driver, name)
예제 #7
0
def attrs(name, key=None, subkey=None, number=None):
    """
Query attributes from this object.

Example:

.. code:: bash

    $ ${post} -d 'name=attrpool1' ${server_url}/entity/pool
    [
        "/pool/attrpool1"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${get} ${server_url}/attribute/attrpool1
    []
    HTTP: 200
    Content-type: application/json

Will show all the attributes from the object ``attrpool1``:

.. code:: bash

    $ ${get} -d 'driver=pool' ${server_url}/attribute/attrpool1
    []
    HTTP: 200
    Content-type: application/json

Will show all the attributes from the object ``attrpool1`` **if** the driver
for ``attrpool1`` is ``pool``. In the same vein this code:

.. code:: bash

    $ ${get} -d 'driver=basicserver' ${server_url}/attribute/attrpool1
    ...
    HTTP: 409
    ...

Should fail, because the ``attrpool1`` object is of type ``pool``,
**not** ``basicserver``

Example:

.. code:: bash

    $ ${get} ${server_url}/attribute/attrpool1/owner
    []
    HTTP: 200
    Content-type: application/json

Will show the attributes for ``server1`` if their key is ``owner``.
"""

    attrs = []
    kwargs = dict(request.params.items())
    driver = kwargs.get('driver', None)
    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)

    qkwargs = {}
    if key:
        qkwargs['key'] = key
    if subkey:
        qkwargs['subkey'] = subkey
    if number:
        qkwargs['number'] = number
    for attr in obj.attrs(**qkwargs):
        attrs.append(util.unclusto(attr))
    return util.dumps(attrs)
예제 #8
0
def del_attrs(name, key, subkey=None, number=None):
    """
Deletes an attribute from this object

 *  Requires HTTP path ``key``
 *  Optional parameters are ``subkey``, ``value``, and ``number``

Examples:

.. code:: bash

    $ ${post} -d 'name=deleteserver1' ${server_url}/entity/basicserver
    [
        "/basicserver/deleteserver1"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${put} -d 'value=joe' ${server_url}/attribute/deleteserver1/group/owner
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": "owner",
            "value": "joe"
        }
    ]
    HTTP: 200
    Content-type: application/json

.. code:: bash

    $ ${delete} ${server_url}/attribute/deleteserver1/group/owner
    []
    HTTP: 200
    Content-type: application/json

Will create a ``basicserver`` object called ``deleteserver1``, then it will
add an attribute (the only attribute so far), then it will delete it.

.. code:: bash

    $ ${post} -d 'name=deleteserver2' ${server_url}/entity/basicserver
    [
        "/basicserver/deleteserver2"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${put} -d 'value=engineering' ${server_url}/attribute/deleteserver2/group
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": null,
            "value": "engineering"
        }
    ]
    HTTP: 200
    Content-type: application/json

.. code:: bash

    $ ${put} -d 'value=joe' ${server_url}/attribute/deleteserver2/group/owner
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": null,
            "value": "engineering"
        },
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": "owner",
            "value": "joe"
        }
    ]
    HTTP: 200
    Content-type: application/json

.. code:: bash

    $ ${delete} ${server_url}/attribute/deleteserver2/group/owner
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": null,
            "value": "engineering"
        }
    ]
    HTTP: 200
    Content-type: application/json

This example should add two attributes with the same key, but different
subkey, then it will delete only the second value.
"""

    kwargs = dict(request.params.items())
    driver = kwargs.get('driver', None)
    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)
    qkwargs = {'key': key}
    if subkey:
        qkwargs['subkey'] = subkey
    if number:
        qkwargs['number'] = number
    obj.del_attrs(**qkwargs)
    return util.dumps([util.unclusto(_) for _ in obj.attrs()])
예제 #9
0
def deallocate(driver, manager):
    """
Resource managers should allow you to deallocate *things* just the same
as allocating *things*.

Examples:

.. code:: bash

    $ ${post} -d 'name=ipman2' -d 'gateway=192.168.1.1' -d 'netmask=255.255.255.0' -d 'baseip=192.168.1.10' ${server_url}/resourcemanager/ipmanager
    {
        "attrs": [
            {
                "datatype": "string",
                "key": "baseip",
                "number": null,
                "subkey": "property",
                "value": "192.168.1.10"
            },
            {
                "datatype": "string",
                "key": "gateway",
                "number": null,
                "subkey": "property",
                "value": "192.168.1.1"
            },
            {
                "datatype": "string",
                "key": "netmask",
                "number": null,
                "subkey": "property",
                "value": "255.255.255.0"
            }
        ],
        "contents": [],
        "count": 0,
        "driver": "ipmanager",
        "name": "ipman2",
        "parents": [],
        "type": "resourcemanager"
    }
    HTTP: 201
    Content-type: application/json

    $ ${post} -d 'name=names2' -d 'basename=a' ${server_url}/resourcemanager/simpleentitynamemanager
    {
        "attrs": [
            ...
        ],
        "contents": [],
        "count": 0,
        "driver": "simpleentitynamemanager",
        "name": "names2",
        "parents": [],
        "type": "resourcemanager"
    }
    HTTP: 201
    Content-type: application/json

    $ ${post} -d 'driver=basicserver' ${server_url}/resourcemanager/simpleentitynamemanager/names2
    "/basicserver/a01"
    HTTP: 201
    Content-type: application/json

    $ ${post} -d 'object=a01' ${server_url}/resourcemanager/ipmanager/ipman2
    {
        "datatype": "int",
        "key": "ip",
        "number": 0,
        "subkey": null,
        "value": 1084752130
    }
    HTTP: 201
    Content-type: application/json

    $ ${delete} -d 'object=a01' ${server_url}/resourcemanager/ipmanager/ipman2
    HTTP: 204
    Content-type:

"""

    resman, status, msg = _get_resource_manager(manager, driver)
    if not resman:
        return util.dumps(msg, status)
    else:
        obj = request.params.get('object')
        if not obj:
            return util.dumps(
                'Cannot deallocate empty, send an object to deallocate',
                404
            )
        obj, status, msg = util.get(obj)
        resource = request.params.get('resource', ())
#       Attempt to deallocate
        resman.deallocate(obj, resource=resource)
        return util.dumps(util.unclusto(resman), 204)
예제 #10
0
def set_attr(name, key, subkey=None, number=None):
    """
Sets an attribute from this object. If the attribute doesn't exist
it will be added, if the attribute already exists then it will be
updated.

 *  Requires HTTP parameters ``key`` and ``value``
 *  Optional parameters are ``subkey`` and ``number``

Example:

.. code:: bash

    $ ${post} -d 'name=setattrserver' ${server_url}/entity/basicserver
    [
        "/basicserver/setattrserver"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'key=group' -d 'value=web' ${server_url}/attribute/setattrserver
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": null,
            "value": "web"
        }
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${put} -d 'value=db' ${server_url}/attribute/setattrserver/group
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": null,
            "value": "db"
        }
    ]
    HTTP: 200
    Content-type: application/json

Will:

#.  Create the entity ``setattrserver``
#.  Add the attribute with ``key=group`` and ``value=web``
#.  Update the attribute to ``value=db``

Example:

.. code:: bash

    $ ${post} -d 'name=setattrserver2' ${server_url}/entity/basicserver
    [
        "/basicserver/setattrserver2"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${put} -d 'value=joe' ${server_url}/attribute/setattrserver2/group/owner
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": "owner",
            "value": "joe"
        }
    ]
    HTTP: 200
    Content-type: application/json

.. code:: bash

    $ ${put} -d 'value=bob' ${server_url}/attribute/setattrserver2/group/owner
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": "owner",
            "value": "bob"
        }
    ]
    HTTP: 200
    Content-type: application/json

Will:

#.  Create a new object ``setattrserver2`` of type ``basicserver``
#.  Set the attribute with key ``group`` *and* subkey ``owner`` with value
    ``joe`` to the object ``setattrserver1``. Since this is the only attribute
    so far, this operation works just like ``add_attr()``
#.  Update the attribute we set above, now the ``value`` will read ``bob``
"""

    kwargs = dict(request.params.items())
    obj, status, msg = util.get(name)
    if not obj:
        return util.dumps(msg, status)
    if 'value' not in kwargs.keys():
        bottle.abort(412, 'Provide at least "key" and "value"')
    obj.set_attr(key=key, subkey=subkey, number=number, value=kwargs['value'])
    return util.dumps([util.unclusto(_) for _ in obj.attrs()])
예제 #11
0
def create(driver):
    """
Creates a new object of the given driver.

 *  Requires HTTP parameters ``name``

Example:

.. code:: bash

    $ ${post} -d 'name=createpool1' ${server_url}/entity/pool
    [
        "/pool/createpool1"
    ]
    HTTP: 201
    Content-type: application/json

Will create a new ``pool1`` object with a ``pool`` driver. If the
``pool1`` object already exists, the status code returned will be 202,
and you will see whatever warnings in the ``Warnings`` header:

.. code:: bash

    $ ${post_i} -d 'name=createpool1' ${server_url}/entity/pool
    HTTP/1.0 202 Accepted
    ...
    Warnings: Entity(s) /pool/createpool1 already exist(s)...
    [
        "/pool/createpool1"
    ]

If you try to create a server of an unknown driver, you should receive
a 412 status code back:

.. code:: bash

    $ ${post} -d 'name=createobject' ${server_url}/entity/nondriver
    "Requested driver \"nondriver\" does not exist"
    HTTP: 412
    Content-type: application/json

The following example:

.. code:: bash

    $ ${post_i} -d 'name=createpool1' -d 'name=createpool2' ${server_url}/entity/pool
    HTTP/1.0 202 Accepted
    ...
    Warnings: Entity(s) /pool/createpool1 already exist(s)...
    [
        "/pool/createpool1",
        "/pool/createpool2"
    ]

Will attempt to create new objects ``createpool1`` and ``createpool2`` with
a ``pool`` driver. As all objects are validated prior to creation, if any of
them already exists the return code will be 202 (Accepted) and you will get
an extra header ``Warnings`` with the message.

"""

    if driver not in clusto.driverlist:
        return util.dumps('Requested driver "%s" does not exist' % (driver,), 412)
    cls = clusto.driverlist[driver]
    names = request.params.getall('name')
    request.params.pop('name')

    found = []
    for name in names:
        try:
            found.append(util.unclusto(clusto.get_by_name(name)))
        except LookupError:
            pass

    result = []
    for name in names:
        result.append(util.unclusto(clusto.get_or_create(name, cls)))

    headers = {}
    if found:
        headers['Warnings'] = 'Entity(s) %s already exist(s)' % (','.join(found),)

    code = 201
    if found:
        code = 202
    return util.dumps(result, code, headers=headers)
예제 #12
0
def show(driver, manager):
    """
Shows the details of the given resource manager, if it is a resource manager

Examples:

.. code:: bash

    $ ${post} -d 'name=nameman2' ${server_url}/resourcemanager/simplenamemanager
    {
        "attrs": [
            ...
        ],
        "contents": [],
        "count": 0,
        "driver": "simplenamemanager",
        "name": "nameman2",
        "parents": [],
        "type": "resourcemanager"
    }
    HTTP: 201
    Content-type: application/json

    $ ${get} ${server_url}/resourcemanager/simplenamemanager/nameman1
    {
        "attrs": [
            ...
        ],
        "contents": [],
        "count": 0,
        "driver": "simplenamemanager",
        "name": "nameman1",
        "parents": [],
        "type": "resourcemanager"
    }
    HTTP: 200
    Content-type: application/json

Will create the ``nameman2`` resource manager, then show its details. In this
case both operations yield the same data.

.. code:: bash

    $ ${get} ${server_url}/resourcemanager/simpleentitynamemanager/nonames
    "Object \"nonames\" not found (nonames does not exist.)"
    HTTP: 404
    Content-type: application/json

Will return a ``404`` error since the resource manager wasn't found

.. code:: bash

    $ ${get} ${server_url}/resourcemanager/nomanager/testnames
    "The driver \"nomanager\" is not a valid driver"
    HTTP: 412
    Content-type: application/json

Will return a ``412`` because the driver ``nomanager`` doesn't exist

.. code:: bash

    $ ${get} ${server_url}/resourcemanager/basicserver/testserver1
    "The object \"testserver1\" is not a resource manager"
    HTTP: 409
    Content-type: application/json

Will return a ``412`` instead because even though the driver ``basicserver``
exists, it is not a resource manager driver
"""

    obj, status, msg = _get_resource_manager(manager, driver)
    if not obj:
        return util.dumps(msg, status)
    else:
        return util.dumps(util.show(obj))
예제 #13
0
def list(driver=None):
    """
Returns all entities, or (optionally) all entities of the given driver

Example:

.. code:: bash

    $ ${get} ${server_url}/entity/
    [
        ...
    ]
    HTTP: 200
    Content-type: application/json

Will list all entities

Example:

.. code:: bash

    $ ${get} ${server_url}/entity/clustometa
    [
        "/clustometa/clustometa"
    ]
    HTTP: 200
    Content-type: application/json

Will list all entities that match the driver ``clustometa``

The following example should fail because there is no driver ``nondriver``:

.. code:: bash

    $ ${get} ${server_url}/entity/nondriver
    "The requested driver \"nondriver\" does not exist"
    HTTP: 412
    Content-type: application/json

"""

    result = []
    kwargs = {}
    for param in request.params.keys():
        kwargs[param] = request.params.getall(param)
    if driver:
        if driver in clusto.driverlist:
            kwargs['clusto_drivers'] = [clusto.driverlist[driver]]
        else:
            return util.dumps('The requested driver "%s" does not exist' % (driver,), 412)
    ents = clusto.get_entities(**kwargs)
    for ent in ents:
        result.append(util.unclusto(ent))

    result = []
    kwargs = {}
    for param in request.params.keys():
        kwargs[param] = request.params.getall(param)
    if driver:
        if driver in clusto.driverlist:
            kwargs['clusto_drivers'] = [clusto.driverlist[driver]]
    ents = clusto.get_entities(**kwargs)
    for ent in ents:
        result.append(util.unclusto(ent))
    return util.dumps(result)
예제 #14
0
def list(driver=None):
    """
Returns all entities, or (optionally) all entities of the given driver

Example:

.. code:: bash

    $ ${get} ${server_url}/entity/
    [
        ...
    ]
    HTTP: 200
    Content-type: application/json

Will list all entities

Example:

.. code:: bash

    $ ${get} ${server_url}/entity/clustometa
    [
        "/clustometa/clustometa"
    ]
    HTTP: 200
    Content-type: application/json

Will list all entities that match the driver ``clustometa``

The following example should fail because there is no driver ``nondriver``:

.. code:: bash

    $ ${get} ${server_url}/entity/nondriver
    "The requested driver \"nondriver\" does not exist"
    HTTP: 412
    Content-type: application/json

"""

    result = []
    kwargs = {}
    mode = bottle.request.headers.get('Clusto-Mode', default='compact')
    headers = {}
    try:
        # Assignments are moved into the try block because of the int casting.
        current = int(bottle.request.headers.get('Clusto-Page', default='0'))
        per = int(bottle.request.headers.get('Clusto-Per-Page', default='50'))
    except TypeError as ve:
        return util.dumps('%s' % (ve, ), 400)

    for param in request.params.keys():
        kwargs[param] = request.params.getall(param)
    if driver:
        if driver in clusto.driverlist:
            kwargs['clusto_drivers'] = [clusto.driverlist[driver]]
        else:
            return util.dumps(
                'The requested driver "%s" does not exist' % (driver, ), 412)
    ents = clusto.get_entities(**kwargs)
    if current:
        ents, total = util.page(ents, current=current, per=per)
        headers['Clusto-Pages'] = total
        headers['Clusto-Per-Page'] = per
        headers['Clusto-Page'] = current

    for ent in ents:
        result.append(util.show(ent, mode))
    return util.dumps(result, headers=headers)
예제 #15
0
def _write_attrs(method, name, **kwargs):
    """
Helper method for reduced code between POST and PUT.
Returns a response for the methods calling it.
"""
    if method == 'set':
        code = 200
    if method == 'add':
        code = 201
    else:
        util.dumps(
            '"%s" is neither set nor add. How did you get here?' % method, 400)

    request_kwargs = dict(request.params.items())
    driver = kwargs.get('driver', None)
    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)

    try:
        # Merge URL values and kwarg values, but do not allow conflicts.
        for k, v in request_kwargs.items():
            if kwargs.get(k) is not None and kwargs[k] != v:
                raise ValueError(
                    'Two different values were submitted for "%s": %s' %
                    (k, [kwargs[k], v]))
            kwargs[k] = v

        # Additionally capture a value error if the json is bad.
        json_kwargs = request.json
    except ValueError as ve:
        return util.dumps('%s' % (ve, ), 400)

    if json_kwargs:
        if request.query:
            return util.dumps(
                'Error: json and query params may not be passed in the same request.',
                400)
        kwargs = json_kwargs

    # Adds support for bulk attr posting.
    attrs = [kwargs] if isinstance(kwargs, dict) else kwargs
    # Check for malformed data or missing pieces before adding any attrs.
    for attr in attrs:
        for k in ('key', 'value'):
            if k not in attr.keys():
                bottle.abort(412, 'Provide at least "key" and "value"')

        if 'number' in attr:
            try:
                attr['number'] = int(attr['number'])
            except ValueError as ve:
                return util.dumps('%s' % (ve, ), 400)

        if 'datatype' in attr:
            datatype = attr.pop('datatype')
            mask = attr.pop('mask', '%Y-%m-%dT%H:%M:%S.%f')
            attr['value'] = util.typecast(attr['value'], datatype, mask=mask)

    for attr in attrs:
        getattr(obj, method + '_attr')(**attr)

    return util.dumps([util.unclusto(_) for _ in obj.attrs()], code)
예제 #16
0
def del_attrs(name, key, subkey=None, number=None):
    """
Deletes an attribute from this object

 *  Requires HTTP path ``key``
 *  Optional parameters are ``subkey``, ``value``, and ``number``

Examples:

.. code:: bash

    $ ${post} -d 'name=deleteserver1' ${server_url}/entity/basicserver
    [
        "/basicserver/deleteserver1"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${put} -d 'value=joe' ${server_url}/attribute/deleteserver1/group/owner
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": "owner",
            "value": "joe"
        }
    ]
    HTTP: 200
    Content-type: application/json

.. code:: bash

    $ ${delete} ${server_url}/attribute/deleteserver1/group/owner
    []
    HTTP: 200
    Content-type: application/json

Will create a ``basicserver`` object called ``deleteserver1``, then it will
add an attribute (the only attribute so far), then it will delete it.

.. code:: bash

    $ ${post} -d 'name=deleteserver2' ${server_url}/entity/basicserver
    [
        "/basicserver/deleteserver2"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${put} -d 'value=engineering' ${server_url}/attribute/deleteserver2/group
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": null,
            "value": "engineering"
        }
    ]
    HTTP: 200
    Content-type: application/json

.. code:: bash

    $ ${put} -d 'value=joe' ${server_url}/attribute/deleteserver2/group/owner
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": null,
            "value": "engineering"
        },
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": "owner",
            "value": "joe"
        }
    ]
    HTTP: 200
    Content-type: application/json

.. code:: bash

    $ ${delete} ${server_url}/attribute/deleteserver2/group/owner
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": null,
            "value": "engineering"
        }
    ]
    HTTP: 200
    Content-type: application/json

This example should add two attributes with the same key, but different
subkey, then it will delete only the second value.
"""

    kwargs = dict(request.params.items())
    driver = kwargs.get('driver', None)
    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)
    qkwargs = {'key': key}
    if subkey:
        qkwargs['subkey'] = subkey
    if number:
        qkwargs['number'] = number
    obj.del_attrs(**qkwargs)
    return util.dumps([util.unclusto(_) for _ in obj.attrs()])
예제 #17
0
def attrs(name, key=None, subkey=None, number=None):
    """
Query attributes from this object.

Example:

.. code:: bash

    $ ${post} -d 'name=attrpool1' ${server_url}/entity/pool
    [
        "/pool/attrpool1"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${get} ${server_url}/attribute/attrpool1
    []
    HTTP: 200
    Content-type: application/json

Will show all the attributes from the object ``attrpool1``:

.. code:: bash

    $ ${get} -d 'driver=pool' ${server_url}/attribute/attrpool1
    []
    HTTP: 200
    Content-type: application/json

Will show all the attributes from the object ``attrpool1`` **if** the driver
for ``attrpool1`` is ``pool``. In the same vein this code:

.. code:: bash

    $ ${get} -d 'driver=basicserver' ${server_url}/attribute/attrpool1
    ...
    HTTP: 409
    ...

Should fail, because the ``attrpool1`` object is of type ``pool``,
**not** ``basicserver``

Example:

.. code:: bash

    $ ${get} ${server_url}/attribute/attrpool1/owner
    []
    HTTP: 200
    Content-type: application/json

Will show the attributes for ``server1`` if their key is ``owner``.
"""

    attrs = []
    kwargs = dict(request.params.items())
    driver = kwargs.get('driver', None)
    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)

    qkwargs = {}
    if key:
        qkwargs['key'] = key
    if subkey:
        qkwargs['subkey'] = subkey
    if number:
        qkwargs['number'] = number
    for attr in obj.attrs(**qkwargs):
        attrs.append(util.unclusto(attr))
    return util.dumps(attrs)
예제 #18
0
def insert(driver, name):
    """
Inserts the given device from the request parameters into the object

Example:

.. code:: bash

    $ ${post} -d 'name=insertpool' ${server_url}/entity/pool
    [
        "/pool/insertpool"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'name=insertserver' ${server_url}/entity/basicserver
    [
        "/basicserver/insertserver"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${put} -d 'device=insertserver' ${server_url}/entity/pool/insertpool
    {
        "attrs": [],
        "contents": [
            "/basicserver/insertserver"
        ],
        "driver": "pool",
        "name": "insertpool",
        "parents": []
    }
    HTTP: 200
    Content-type: application/json

Will:

#.  Create a pool entity called ``insertpool``
#.  Create a basicserver entity called ``insertserver``
#.  Insert the entity ``insertserver`` into the entity ``insertpool``

Examples:

.. code:: bash

    $ ${post} -d 'name=insertpool2' ${server_url}/entity/pool
    [
        "/pool/insertpool2"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'name=insertserver2' -d 'name=insertserver3' ${server_url}/entity/basicserver
    [
        "/basicserver/insertserver2",
        "/basicserver/insertserver3"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${put} -d 'device=insertserver2' -d 'device=insertserver3' ${server_url}/entity/pool/insertpool2
    {
        "attrs": [],
        "contents": [
            "/basicserver/insertserver2",
            "/basicserver/insertserver3"
        ],
        "driver": "pool",
        "name": "insertpool2",
        "parents": []
    }
    HTTP: 200
    Content-type: application/json

The above will:

#.  Create a pool entity called ``insertpool2``
#.  Create twp basicserver entities called ``insertserver2`` and ``insertserver3``
#.  Insert both basicserver entities into the pool entity

"""

    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)
    devices = request.params.getall('device')

    devobjs = []
    notfound = []
    for device in devices:
        try:
            devobjs.append(clusto.get_by_name(device))
        except LookupError:
            notfound.append(device)

    if notfound:
        bottle.abort(404, 'Objects %s do not exist and cannot be inserted into "%s"' % (','.join(notfound), name,))

    for devobj in devobjs:
        if devobj not in obj:
            obj.insert(devobj)

    return show(driver, name)
예제 #19
0
def create(driver):
    """
Creates a new object of the given driver.

 *  Requires HTTP parameters ``name``

Example:

.. code:: bash

    $ ${post} -d 'name=createpool1' ${server_url}/entity/pool
    [
        "/pool/createpool1"
    ]
    HTTP: 201
    Content-type: application/json

Will create a new ``pool1`` object with a ``pool`` driver. If the
``pool1`` object already exists, the status code returned will be 202,
and you will see whatever warnings in the ``Warnings`` header:

.. code:: bash

    $ ${post_i} -d 'name=createpool1' ${server_url}/entity/pool
    HTTP/1.0 202 Accepted
    ...
    Warnings: Entity(s) /pool/createpool1 already exist(s)...
    [
        "/pool/createpool1"
    ]

If you try to create a server of an unknown driver, you should receive
a 412 status code back:

.. code:: bash

    $ ${post} -d 'name=createobject' ${server_url}/entity/nondriver
    "Requested driver \"nondriver\" does not exist"
    HTTP: 412
    Content-type: application/json

The following example:

.. code:: bash

    $ ${post_i} -d 'name=createpool1' -d 'name=createpool2' ${server_url}/entity/pool
    HTTP/1.0 202 Accepted
    ...
    Warnings: Entity(s) /pool/createpool1 already exist(s)...
    [
        "/pool/createpool1",
        "/pool/createpool2"
    ]

Will attempt to create new objects ``createpool1`` and ``createpool2`` with
a ``pool`` driver. As all objects are validated prior to creation, if any of
them already exists the return code will be 202 (Accepted) and you will get
an extra header ``Warnings`` with the message.

"""

    if driver not in clusto.driverlist:
        return util.dumps('Requested driver "%s" does not exist' % (driver, ),
                          412)
    cls = clusto.driverlist[driver]
    names = request.params.getall('name')
    request.params.pop('name')

    found = []
    for name in names:
        try:
            found.append(util.unclusto(clusto.get_by_name(name)))
        except LookupError:
            pass

    result = []
    for name in names:
        result.append(util.unclusto(clusto.get_or_create(name, cls)))

    headers = {}
    if found:
        headers['Warnings'] = 'Entity(s) %s already exist(s)' % (
            ','.join(found), )

    code = 201
    if found:
        code = 202
    return util.dumps(result, code, headers=headers)
예제 #20
0
def create(driver):
    """
This differs from the standard way of creating entities is that resource
managers can have a number of extra parameters added to them that not
necessarily match any of the other entities. These parameters are defined
by each resource manager driver and are pretty much arbitrary. Seems like
a good idea to separate these crucial differences.

Examples:

.. code:: bash

    $ ${post} -d 'name=nameman1' ${server_url}/resourcemanager/simplenamemanager
    {
        "attrs": [
            ...
        ],
        "contents": [],
        "count": 0,
        "driver": "simplenamemanager",
        "name": "nameman1",
        "parents": [],
        "type": "resourcemanager"
    }
    HTTP: 201
    Content-type: application/json

Will create a ``SimpleNameManager`` resource manager named ``namemgr1`` with
all default values set.

.. code:: bash

    $ ${post} -d 'name=ipman1' -d 'gateway=192.168.1.1' -d 'netmask=255.255.255.0' -d 'baseip=192.168.1.10' ${server_url}/resourcemanager/ipmanager
    {
        "attrs": [
            {
                "datatype": "string",
                "key": "baseip",
                "number": null,
                "subkey": "property",
                "value": "192.168.1.10"
            },
            {
                "datatype": "string",
                "key": "gateway",
                "number": null,
                "subkey": "property",
                "value": "192.168.1.1"
            },
            {
                "datatype": "string",
                "key": "netmask",
                "number": null,
                "subkey": "property",
                "value": "255.255.255.0"
            }
        ],
        "contents": [],
        "count": 0,
        "driver": "ipmanager",
        "name": "ipman1",
        "parents": [],
        "type": "resourcemanager"
    }
    HTTP: 201
    Content-type: application/json

Will create a  ``IPManager`` resource manager named ``ipman1`` with some
additional arguments such as ``netmask``, ``gateway`` and ``baseip``

"""
    if driver not in clusto.driverlist:
        return util.dumps('Requested driver "%s" does not exist' % (driver,), 412)
    cls = clusto.driverlist[driver]
    name = request.params.get('name')
    request.params.pop('name')

#   Pass any additional parameters as is to the constructor
    kwargs = {}
    for param, value in request.params.items():
        kwargs[param] = value

    found = None
    try:
        found = util.unclusto(clusto.get_by_name(name))
    except LookupError:
        pass

    obj = clusto.get_or_create(name, cls, **kwargs)

    headers = {}
    if found:
        headers['Warnings'] = 'Resource manager "%s" already exists' % (found,)

    code = 201
    if found:
        code = 202
    return util.dumps(util.show(obj), code, headers=headers)
예제 #21
0
def list(driver=None):
    """
Returns all entities, or (optionally) all entities of the given driver

Example:

.. code:: bash

    $ ${get} ${server_url}/entity/
    [
        ...
    ]
    HTTP: 200
    Content-type: application/json

Will list all entities

Example:

.. code:: bash

    $ ${get} ${server_url}/entity/clustometa
    [
        "/clustometa/clustometa"
    ]
    HTTP: 200
    Content-type: application/json

Will list all entities that match the driver ``clustometa``

The following example should fail because there is no driver ``nondriver``:

.. code:: bash

    $ ${get} ${server_url}/entity/nondriver
    "The requested driver \"nondriver\" does not exist"
    HTTP: 412
    Content-type: application/json

"""

    result = []
    kwargs = {}
    mode = bottle.request.headers.get('Clusto-Mode', default='compact')
    headers = {}
    try:
        # Assignments are moved into the try block because of the int casting.
        current = int(bottle.request.headers.get('Clusto-Page', default='0'))
        per = int(bottle.request.headers.get('Clusto-Per-Page', default='50'))
    except TypeError as ve:
        return util.dumps('%s' % (ve,), 400)

    for param in request.params.keys():
        kwargs[param] = request.params.getall(param)
    if driver:
        if driver in clusto.driverlist:
            kwargs['clusto_drivers'] = [clusto.driverlist[driver]]
        else:
            return util.dumps('The requested driver "%s" does not exist' % (driver,), 412)
    ents = clusto.get_entities(**kwargs)
    if current:
        ents, total = util.page(ents, current=current, per=per)
        headers['Clusto-Pages'] = total
        headers['Clusto-Per-Page'] = per
        headers['Clusto-Page'] = current

    for ent in ents:
        result.append(util.show(ent, mode))
    return util.dumps(result, headers=headers)
예제 #22
0
def allocate(driver, manager):
    """
This allocates a new *resource* to a given *thing*. Said thing can be either
a *driver* (and the result will be a newly created object subclasses from this
driver) or an *object*, and the resource manager will allocate (bind) a
resource to it.

Examples:

.. code:: bash

    $ ${post} -d 'name=allocator' ${server_url}/resourcemanager/simpleentitynamemanager
    {
        "attrs": [
            ...
        ],
        "contents": [],
        "count": 0,
        "driver": "simpleentitynamemanager",
        "name": "allocator",
        "parents": [],
        "type": "resourcemanager"
    }
    HTTP: 201
    Content-type: application/json

    $ ${post} -d 'driver=basicserver' ${server_url}/resourcemanager/simpleentitynamemanager/allocator
    "/basicserver/01"
    HTTP: 201
    Content-type: application/json

Will request a new name from the object ``allocator`` (which is an object
of ``SimpleEntityManager`` that we just created with default values) and then
it will create a new ``BasicServer`` object.

.. code:: bash

    $ ${post} -d 'driver=basicserver' -d 'resource=99' ${server_url}/resourcemanager/simpleentitynamemanager/allocator
    "/basicserver/99"
    HTTP: 201
    Content-type: application/json

Will create a new ``BasicServer`` object from the ``testnames`` resource
manager with the specific name of ``s99``.
"""

    obj, status, msg = _get_resource_manager(manager, driver)
    if not obj:
        return util.dumps(msg, status)
    else:
        d = request.params.get('driver')
        o = request.params.get('object')
        thing = d or o
        if not thing:
            return util.dumps(
                'Cannot allocate an empty thing, send one of '
                '"driver", "object"', 404
            )
        if d:
            thing = clusto.driverlist.get(thing)
        else:
            thing = clusto.get_by_name(thing)
        if not thing:
            return util.dumps('Thing was "%s" not found' % (d or o,), 404)
        resource = request.params.get('resource', default=())
        r = obj.allocate(thing, resource)
#       The returned value can be anything such a string, number, or attribute
        return util.dumps(util.unclusto(r), 201)
예제 #23
0
def action(driver, name):
    """
Inserts/removes the given device from the request parameters into/from the object

Example:

.. code:: bash

    $ ${post} -d 'name=pool1' ${server_url}/entity/pool
    [
        "/pool/pool1"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'name=server1' ${server_url}/entity/basicserver
    [
        "/basicserver/server1"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'device=server1' -d 'action=insert' ${server_url}/entity/pool/pool1
    {
        "attrs": [],
        "contents": [
            "/basicserver/server1"
        ],
        "driver": "pool",
        "name": "pool1",
        "parents": [],
        "type": "pool"
    }
    HTTP: 200
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'device=server1' -d 'action=remove' ${server_url}/entity/pool/pool1
    {
        "attrs": [],
        "contents": [],
        "driver": "pool",
        "name": "pool1",
        "parents": [],
        "type": "pool"
    }
    HTTP: 200
    Content-type: application/json

Will:

#.  Create a pool entity called ``pool1``
#.  Create a basicserver entity called ``server1``
#.  Insert the entity ``server1`` into the entity ``pool1``
#.  Remove the entity ``server1`` from the entity ``pool1``

Examples:

.. code:: bash

    $ ${post} -d 'name=pool2' ${server_url}/entity/pool
    [
        "/pool/pool2"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'name=server2' -d 'name=server3' ${server_url}/entity/basicserver
    [
        "/basicserver/server2",
        "/basicserver/server3"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'device=server2' -d 'device=server3' -d 'action=insert' ${server_url}/entity/pool/pool2
    {
        "attrs": [],
        "contents": [
            "/basicserver/server2",
            "/basicserver/server3"
        ],
        "driver": "pool",
        "name": "pool2",
        "parents": [],
        "type": "pool"
    }
    HTTP: 200
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'device=server2' -d 'device=server3' -d 'action=remove' ${server_url}/entity/pool/pool2
    {
        "attrs": [],
        "contents": [],
        "driver": "pool",
        "name": "pool2",
        "parents": [],
        "type": "pool"
    }
    HTTP: 200
    Content-type: application/json

The above will:

#.  Create a pool entity called ``pool2``
#.  Create two basicserver entities called ``server2`` and ``server3``
#.  Insert both basicserver entities into the pool entity
#.  Remove both basicserver entities from the pool entity

"""

    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)
    devices = request.params.getall('device')
    action = request.params.get('action')

    if not action:
        bottle.abort(400, 'Parameter \'action\' is required.')

    devobjs = []
    notfound = []
    for device in devices:
        try:
            devobjs.append(clusto.get_by_name(device))
        except LookupError:
            notfound.append(device)

    if notfound:
        bottle.abort(404, 'Objects %s do not exist and cannot be used with "%s"' % (','.join(notfound), name,))

    if action == 'insert':
        for devobj in devobjs:
            if devobj not in obj:
                obj.insert(devobj)

    elif action == 'remove':
        for devobj in devobjs:
            if devobj in obj:
                obj.remove(devobj)

    else:
        bottle.abort(400, '%s is not a valid action.' % (action))

    return show(driver, name)
예제 #24
0
def list(driver=None):
    """
Lists all resource managers found in the clusto database. Optionally you can
list all resource managers that match the given ``driver``

Examples:

.. code:: bash

    $ ${post} -d 'name=zmanager' ${server_url}/resourcemanager/simplenamemanager
    {
        "attrs": [
            ...
        ],
        "contents": [],
        "count": 0,
        "driver": "simplenamemanager",
        "name": "zmanager",
        "parents": [],
        "type": "resourcemanager"
    }
    HTTP: 201
    Content-type: application/json

The above will create a simple name manager called "zmanager"

.. code:: bash

    $ ${get} ${server_url}/resourcemanager/
    [
        "/simpleentitynamemanager/testnames",
        "/simplenamemanager/zmanager"
    ]
    HTTP: 200
    Content-type: application/json

The above will list all resource managers in clusto, which should have "zmanager"

.. code:: bash

    $ ${get} ${server_url}/resourcemanager/simpleentitynamemanager
    [
        "/simpleentitynamemanager/testnames"
    ]
    HTTP: 200
    Content-type: application/json

Will list all resource managers of driver ``SimpleNameManager``

.. code:: bash

    $ ${get} ${server_url}/resourcemanager/notadriver
    "Not a valid driver \"notadriver\" (driver name notadriver doesn't exist.)"
    HTTP: 404
    Content-type: application/json

Will return a ``404`` error because that resource manager driver doesn't exist
"""

    result = []

    if driver:
        try:
            ents = clusto.get_entities(clusto_drivers=[driver])
        except NameError as ne:
            return util.dumps(
                'Not a valid driver "%s" (%s)' % (driver, ne,), 404
            )
    else:
        # Until we fix the ipmanager snafu, gotta check for both types
        ents = clusto.get_entities(clusto_types=['resourcemanager'])

    for ent in ents:
        # Kind of shitty way, but have to make sure these are all resource managers
        if issubclass(ent.__class__, drivers.resourcemanagers.ResourceManager):
            result.append(util.unclusto(ent))
    return util.dumps(result)
예제 #25
0
def add_attr(name):
    """
Add an attribute to this object.

 *  Requires HTTP parameters ``name``, ``key``, and ``value``
 *  Optional parameters are ``subkey`` and ``number``

Example:

.. code:: bash

    $ ${post} -d 'name=addattrserver' ${server_url}/entity/basicserver
    [
        "/basicserver/addattrserver"
    ]
    HTTP: 201
    Content-type: application/json

.. code:: bash

    $ ${post} -d 'key=group' -d 'value=web' ${server_url}/attribute/addattrserver
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": null,
            "value": "web"
        }
    ]
    HTTP: 201
    Content-type: application/json

Will:

#.  Create an entity called ``addattrserver``
#.  Add the attribute with ``key=group`` and ``value=web`` to it

Example:

.. code:: bash

    $ ${post} -d 'key=group' -d 'subkey=owner' -d 'value=web' ${server_url}/attribute/addattrserver
    [
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": null,
            "value": "web"
        },
        {
            "datatype": "string",
            "key": "group",
            "number": null,
            "subkey": "owner",
            "value": "web"
        }
    ]
    HTTP: 201
    Content-type: application/json

Will add the attribute with key ``group`` *and* subkey ``owner`` *and*
value ``joe`` to the previously created entity ``addattrserver``

"""

    kwargs = dict(request.params.items())
    driver = kwargs.get('driver', None)
    obj, status, msg = util.get(name, driver)
    if not obj:
        return util.dumps(msg, status)

    for k in ('key', 'value'):
        if k not in kwargs.keys():
            bottle.abort(412, 'Provide at least "key" and "value"')

    if 'number' in kwargs:
        kwargs['number'] = int(kwargs['number'])

    obj.add_attr(**kwargs)

    return util.dumps([util.unclusto(_) for _ in obj.attrs()], 201)