Exemple #1
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)
Exemple #2
0
def _get_resource_manager(manager, driver):
    "A wrapper because an extra check has to be made :("

    obj, status, msg = util.get(manager, driver)
    if obj:
        if not issubclass(obj.__class__, drivers.resourcemanagers.ResourceManager):
            msg = 'The object "%s" is not a resource manager' % (manager,)
            status = 409
            obj = None
        else:
            pass
    else:
        pass

    return obj, status, msg
Exemple #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))
Exemple #4
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))
Exemple #5
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)
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)
Exemple #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)
Exemple #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()])
Exemple #9
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)
Exemple #10
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)
Exemple #11
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)
Exemple #12
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()])
Exemple #13
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)
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()])
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)