[Interop-dev] Common API

Ralf Schlatterbeck (spam-protected)
Thu Nov 1 19:29:43 CET 2012


On Tue, Oct 30, 2012 at 06:23:59AM -0300, Nicolás Echániz wrote:
> On 10/23/12 13:33, Federico Capoano wrote:
[I've edited for brevety]
> > 
> > {
> > 
> >   *
> >     meta: {
> >         limit: 1000,
> >         next: null,
> >         offset: 0,
> >         previous: null,
> >         total_count: 1
> >     },
> >   *
> >     objects: [
> >         {
> >             id: 1,
> >             status: 3, name: "Fusolab Rome",
> >             slug: "fusolab",
> >             description: "Fusolab",
> >             lat: 41.8720419277,
> >             lng: 12.5822391919,
> >             elev: 80,
> >             is_hotspot: true
> >         },
> > 
> > }
> 
> This is our current minimal JSON representation of a node.
> 
> 
> {
>    "network": "quintanalibre.org.ar",
>    "zone": "",
>    "name": "Tikita"
>    "elevation": 490,
>    "coords": {
>        "lat": "-31.8109526125",
>        "lon": "-64.4124984741"
>    },
> }
> 
> 
> A more complete version could look something like this:
> 
> {
>    "network": "quintanalibre.org.ar",
>    "zone": "",
>    "name": "Tikita"
>    "elevation": 490,
>    "coords": {
>        "lat": "-31.8109526125",
>        "lon": "-64.4124984741"
>    },
>    "devices": [
>        {
>            "hostname": "tikita",
>            "hardware": "Atheros AR7241 rev 1 / TP-LINK TL-MR3220",
>            "software": "OpenWrt r33390",
>            "interfaces": [
>                {
>                    "name": "wlan0"
>                    "mac": "92:F6:52:C6:08:AD",
>                    "phy": "phy0",
>                }
>            ]
>        }
>    ]
> }
> 
> 
> Comparing your model to ours: "hotspot", "description" and "status" are
> the important differences. Yours is actually a super-set of ours.
> 
> What about the others? do you have a different/contradictory minimal
> node data representation in mind or at work?

Thanks for sharing your designs, so let me show our current status of
the new Funkfeuer Database.

You can test our current implementation (notably the api) here:

http://ffm.gg32.com/api

The data in it is taken from Guifi.net, I've written an importer for the
guifi.net CNML (Community network markup language), an XML
representation. The data we imported can be downloaded from
http://guifi.net/pt-pt/guifi/cnml/2441/detail
(we're using an older local copy, guifi.net request that downloads
should be kept to a minimum due to performance issues).

following the /api link above you will get a list of all the classes in
the current object model.
You can then select a class and will get links to all the objects in
that class:
http://ffm.gg32.com/api/FFM-Node

Federico's concern about size is taken care of by just showing the links
to all the Node objects not the full representation -- although you *can*
get that if you add the parameter 'verbose=True', e.g.:
http://ffm.gg32.com/api/FFM-Node?verbose=True

We also have a query language (with additional parameters after the base
URL) for the REST API with which you can limit the number of returned
items but I'll defer this for another time.

For a single node an example would be the link
http://ffm.gg32.com/api/FFM-Node/103

and the json representation of it:

{
  "attributes": {
    "manager": {
      "pid": 102, 
      "url": "/api/PAP-Person/102"
    }, 
    "name": "alella-22464", 
    "owner": {
      "pid": 102, 
      "url": "/api/PAP-Person/102"
    }, 
    "position": {
      "lat": 41.512718999999997, 
      "lon": 2.2898309999999999
    }
  }, 
  "cid": 102, 
  "pid": 103, 
  "type_name": "FFM.Node", 
  "url": "/api/FFM-Node/103"
}

Note that similar to Federico we keep all the "essential" attributes in
a dictionary named "attributes".

An essential attribute of a class is something that has a representation
in the real world and is necessary for our modelling. Contrary to
non-essential (or accidental) attributes that come from the
implementation. For a discussion see 
http://en.wikipedia.org/wiki/Essence

Under this definition the id (called "permanent ID" or "pid" in our
implementation) is not essential. It can -- and will differ from
implementation to implementation. We also have an ID of the last change
called the Change-ID or cid.
This doesn't mean we don't need an id property for building links to
objects. So a common API *should* standardize on handles for objects.

Modelling:

You can view our current object model included in the README at github:
https://github.com/FFM/FFM

This is auto-generated from the object model using a hints file for
placement. 

We have a navigatable documentation at 
http://ffm.gg32.com/Doc
this is not the latest version (compared to github), the github version
already has the Wired_Interface and Wired_Link in the diagram.

We try to model all aspects that do not concern a class itself as links.
I'll have to dig up a reference why this is a good idea in an object
oriented design. Note that this will also make our life easier for
supporting different optional parts of an object model in a common API.

Links in our model come in several variants. A "Link2" is used to model
N:M relations. Each Link2 class has a "left" and a "right" attribute
(these are the default names that will always work, it is possible to
define aliases in the class).

An example is Wireless_Interface_uses_Wireless_Channel, in the diagram
this link object is displayed as _uses_ between the FFM.Wireless_Channel
and FFM.Wireless_Interface. The black arrows connecting these are
labelled left and right which indicates how this should be read. Note
that in this case the left attribute is on the right side in the
diagram. A two-way link like this has an identity and can have
additional attributes besides left and right.

There are also unary links with only a left side, the base class is
Link1. An example is the Device which cannot exist without its left
attribute, the Device_Type.  There can be several devices with the same
device type. This relationship is inherited by Antenna and Antenna_Type
and Net_Device and Net_Device_Type.

The association of Node and Zone is not yet modelled. In our analysis
we've found too many differing notions on what a Zone really is. So I'd
appreciate your definition of a Zone and what a Zone is used for.

In our implementation a Device has a Node attribute, so you get the
Node-to-Device (named Net_Device, the Device is the Parent class of
Net_Device and Antenna in our implementation) association via the
Net_Device class:

{
  "attributes": {
    "left": {
      "pid": 106, 
      "url": "/api/FFM-Net_Device_Type/106"
    }, 
    "name": "alemasnou12rd1", 
    "node": {
      "pid": 105, 
      "url": "/api/FFM-Node/105"
    }
  }, 
  "cid": 106, 
  "pid": 107, 
  "type_name": "FFM.Net_Device", 
  "url": "/api/FFM-Net_Device/107"
}

Naming:
You will have noticed that currently in our model all the NodeDB
specific classes contain the FFM- Namespace-Prefix in our API. This is
just for the auto-generated API. We have a mapping mechanism where we
can rename class-names and attribute names. When standardizing on a
common API we will provide an API that fits a common node-DB standard.

Raw vs Cooked values:
In our model everything the user enters via the web-interface is a "raw"
value. All raw values are strings. For computation the value must be
"cooked". For some attributes we retain the raw *and* the cooked value
in the database.
An example is the specification of a frequency: The user can enter "2.4
GHz" or "2400 MHz" and the cooked representation will be a
floating-point value in Hz. The user will see the raw value she entered
when visiting the node page again.

You can get the raw values via the API by
adding ?raw=True to the URL. You can get both by adding
?raw=True&ckd=True e.g.:
http://ffm.gg32.com/api/FFM-Node/105?raw=True&ckd=True
Another example are names: We use Node, Device, and Interface names for
generating DNS names. So these are required to adher to the DNS
specification and the cooked value is the lowercase variant. This avoids
name clashes (the cooked value is stored in the DB and we can generate a
uniqueness constraint).
A third example are GPS positions. The user can enter e.g., a latitude
as a floating-point value in degree or in degree minutes and seconds.
The cooked value is the floating point value.

Some remarks:
- Our model is still work in progress. If you find any problems or have
  suggestions, feel free to share them. This also means we can still
  adapt to better representations or change names.
- The elev in the Node in Federicos model is the height of the Node
  above ground? We also have this as an optional attribute "height" in
  "position". Nicolás also has this as elevation.
  The term "elevation" might clash with the term "elevation angle" for
  antennas... we name this "elevation" and it is an attribute of the
  Antenna. (But it might mean we should rename our antenna attribute)
- I don't understand the slug in Federicos Node
- In our model we might model Federicos hotspot parameter as a Link1 to
  node -- this link will be optional (and there would be at most one of
  it) and it could contain further parameters for the hotspot
- On the other hand we have an "show_in_map" attribute of the Node that
  by this argument should be a Link...
- I think that it's a good idea to allow additional attributes in a
  common API that should be ignored by a client not needing the
  attribute.
- Node status: Guifi.net also has this and I've seen other networks use
  this concept, too, so we probably should define node stati in a common
  API. I think these should be strings and we should try to get a list
  of supported stati into an API. Not every implementation would use all
  of them, though.
  Note that guifi.net also has stati for a (wireless) Link and for
  Devices I think. See the CNML link above.

-- 
Dr. Ralf Schlatterbeck                  Tel:   +43/2243/26465-16
Open Source Consulting                  www:   http://www.runtux.com
Reichergasse 131, A-3411 Weidling       email: (spam-protected)
osAlliance member                       email: (spam-protected)




More information about the Interop-dev mailing list