Browse Source

Add documentation on extending Coin

Baptiste Jonglez 10 years ago
parent
commit
56c73f3576
2 changed files with 169 additions and 7 deletions
  1. 146 0
      EXTENDING.md
  2. 23 7
      README.md

+ 146 - 0
EXTENDING.md

@@ -0,0 +1,146 @@
+How to extend Coin
+==================
+
+Coin can be extended by writing your own backends, so that you can support
+various access technologies by using the tools you want.
+
+The common part of Coin already handles the administrative details of
+subscriptions: members, subscriptions cost and billing strategy,
+generating bills, etc.
+
+It also handles the IP allocation process.  The administrator can define
+pools of IP addresses, in which subnets are automatically allocated to
+subscribers.  Each subscription can be attached any number of IPv4 or IPv6
+subnets, which somehow get routed to the subscriber (the actual way of doing
+this depends on the backend).  Management of reverse DNS is an upcoming
+feature.
+
+All the rest is up to you, that is, the technical side of subscriptions.
+You will probably want to handle:
+
+- authentication (e.g. Radius login and password, TLS certificates...)
+
+- accounting (e.g. collecting and displaying graphs of user traffic)
+
+- routing (e.g. inserting static routes, or signalling a routing daemon
+  about new routes)
+
+- technology-specific information (e.g. phone number associated to a DSL
+  line, MAC address of a CPE, GPS coordinates for wireless subscribers)
+
+- stuff we didn't think about when writing this
+
+
+This can be done in three steps:
+
+- write a Django application, whose models describe the data you need
+
+- optionally, implement views for presenting some of this information to users
+
+- write a backend to distribute needed configuration data to the rest of
+  the infrastructure (routers, switches, log servers, accounting backend...)
+
+How you implement the actual backend is completely up to you.  It can be a
+SQL database (useful for Radius), a LDAP database, simply inserting static
+routes in the kernel (if Coin runs on one of your routers, which is
+probably not a good idea), writing configuration to text files, relying on
+an orchestration tool such as Puppet or Ansible, etc.
+
+
+Simple example: no view, no backend
+-----------------------------------
+
+A very simple application is provided with Coin: it's called `simple_dsl`.
+
+This application provides a simple model for DSL subscribers (just a phone
+number, no authentication), and doesn't use any backend.  It is intended
+more as a demonstration, but it is perfectly usable, and should fulfil the
+needs of small ISPs selling "white label" DSL lines.
+
+It is probably a good starting point for writing your own application.  If
+you need more features, read on.
+
+More complex example with views and a LDAP backend
+--------------------------------------------------
+
+See `coin/vpn` for a much more complex application: OpenVPN access with
+login/password and an arbitrary number of subnets routed to the user.  The
+user has an interface for generating a password and for choosing which IP
+addresses it wants to use.  All this configuration data is pushed to a
+LDAP database, which is then used by the OpenVPN server.  OpenVPN
+interfaces with LDAP both natively (for authenticating users) and through
+shell scripts (for routes and IP addresses).
+
+
+Complete specification
+======================
+
+Models
+------
+
+Your model must inherit from `coin.configuration.models.Configuration`.
+This way, it will be automatically integrated in the generic admin
+interface, and will gain the ability to be associated to IP subnets.
+
+If you define a Meta class with a `verbose_name` attribute, it will be
+used to identify your configuration backend in the interface (otherwise
+the name of the class will be used).
+
+If you want to provide views for your model, you must define an
+`url_namespace` attribute, which is a string defining the URL namespace
+associated to your view.  By default, the (lowercased) name of the class
+will be used.
+
+You should also define a `subnet_event(self)` method, which will be called
+whenever the IP subnets associated to a configuration object have changed
+(new subnet, deleted subnet, modified subnet).  You can use the
+`ip_subnet` related name to have access to all IP subnets associated to
+the object (for instance, `self.ip_subnet.all()` will give you a list of
+`coin.resources.models.IPSubnet` objects).
+
+Note that, like all Django models, you should define a `__unicode__`
+method to describe an object of your class.
+
+
+Admin
+-----
+
+Your admin model must inherit from
+`coin.configuration.admin.ConfigurationAdminFormMixin` and
+`polymorphic.admin.PolymorphicChildModelAdmin` (in this order).
+Otherwise, it's a perfectly regular admin model (see `simple_dsl`), except
+for the specificities described below.
+
+You must define a `inline` attribute, set to an inline admin model for
+your model (for instance, built on `admin.StackedInline` or
+`admin.TabularInline`; again, see `simple_dsl`).  This inline model will
+be used in the generic admin interface, so that administrators can edit
+the backend details directly from a subscription object.
+
+If you don't have any view, remember to set the `view_on_site` attribute
+to `False`, so that Django's admin will not show a "View on site" button.
+
+
+Views
+-----
+
+If you want to provide views for your model, you must provide at least a
+"details" view, which will be used to display information about your
+configuration objects to end-users.  For instance, you can inherit from
+`django.views.generic.detail.DetailView`, or
+`django.views.generic.edit.UpdateView` if you want users to edit some of
+the fields (see `coin/vpn/views.py`).
+
+Here is an example URL pattern to be used in your `urls.py`:
+
+    url(r'^(?P<id>\d+)$', VPNView.as_view(template_name="vpn/vpn.html"), name="details")
+
+Note that this pattern **must** be called "details".  The global `urls.py`
+should contain a pattern of the form:
+
+    url(r'^vpn/', include('coin.vpn.urls', namespace='vpn'))
+
+where the value of "namespace" is the URL namespace defined in your
+original model (see above).
+
+Of course, you can add as many additional views as you want.

+ 23 - 7
README.md

@@ -4,12 +4,11 @@ The COIN project
 `Coin` is Illyse's Information System, designed to manage both members
 and Internet accesses, such as through DSL, VPN, wireless…
 
-It is written in Django, and makes an heavy use of LDAP (for
-authentication, and to store configuration information).
-
-It features a generic configuration interface, which allows to implement
-custom backends for different technologies.  Currently implemented is a
-LDAP-based backend for OpenVPN.
+It is written in Django, and features a generic configuration interface,
+which allows to implement custom backends for different technologies.
+Currently implemented is a LDAP-based backend for OpenVPN, and a very
+simple DSL backend, without any authentication (useful for "white label"
+DSL).
 
 Coin currently only works with python2, because `python-ldap` is (as of
 2013) not compatible with python3.
@@ -18,11 +17,21 @@ The project page (issue, wiki, etc) is here:
 
   https://www.illyse.org/projects/ils-si/
 
-A mirror of the code is available at:
+The code is available at:
+
+  git://git.illyse.org:coin
+
+A mirror of the code, with a web interface, is also available at:
 
   https://code.ffdn.org/zorun/coin/
 
 
+Extending Coin
+==============
+
+If you want to write your own backend, see `EXTENDING.md`.
+
+
 Quickstart
 ==========
 
@@ -98,6 +107,13 @@ Configuration
 You should first setup the `sites` application, in the admin.  The domain name
 configured there is used for outgoing emails.
 
+LDAP
+----
+
+By default, LDAP support is disabled.  If you want to use LDAP (for
+instance for the OpenVPN/LDAP backend, or for your own backend), see the
+configuration file `coin/settings_local.example-illyse.py`.
+
 ISP-specific configuration
 --------------------------