commit fc627daa6d1aa24b39626c49f1d8c0fcbba50867
Author: Christos Stavrakakis <cstavr@grnet.gr>
Date:   Thu Oct 3 13:27:08 2013 +0300

    Add draft design doc for Cyclades networking

diff --git a/docs/design/cyclades-networking.rst b/docs/design/cyclades-networking.rst
new file mode 100644
index 0000000..17c2ac1
--- /dev/null
+++ b/docs/design/cyclades-networking.rst
@@ -0,0 +1,355 @@
+===================
+Cyclades Networking
+===================
+
+Networks
+========
+
+A Cyclades network is a virtual network that can be, depending on it's Network
+Flavor, either an isolated Layer-2 broadcast domain or an Layer-3 network.
+Networks can either be private or public. Private networks are reserved for the
+user who created it, while public networks are created by the administrator and
+are visible to all users. Also, networks can be marked with the
+`--router:external` attribute to indicate that are external networks (public
+interner)
+
+Currently there are four available Networks Flavors:
+
+* IP_ONLY: A Layer-3 network where host routes traffic to the external network.
+* PHYSICAL_VLAN: A Layer-2 network where a physical VLAN is assigned to the
+  network.
+* MAC_FILTERED: A Layer-2 network. All networks of this type share the same
+  physical VLAN, but isolation is achieved by filtering rules based on a
+  unique MAC prefix that is assigned to each network.
+
+The administrator can limit which networks can be created via API with the
+`API_ENABLED_NETOWRK_FLAVORS` setting.
+
+The attributes for network objects are the following:
+
+* id: A string represeting the UUID for the network.
+* name: A human readable name
+* status: String represetng the state of the network. Possible values for the
+  state include: ACTIVE, DOWN, BUILD, ERROR
+* subnets: List of subnet UUIDs that are associated with this network
+* public: Whether network is visible to other users or not.
+* user_id/tenant_id: The UUID of the owner of the network.
+* admin_state_up: Boolean value indicating the administrative state of the
+  network. If 'down' the network does not forward packets.
+
+Note: The 'admin_state_up' value is used only for compatibility with Neutron
+API. It will be read-only, and will always be True.
+
+Create a new network
+^^^^^^^^^^^^^^^^^^^^
+
+Method: POST
+
+URI: /networks
+
+The body of the request must contain the 'type' of the network. Also it can
+a 'name' attribute.
+
+List Networks
+^^^^^^^^^^^^^
+
+Method: GET
+
+URI: /networks
+
+Get details about a network
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+METHOD: GET
+
+URI:  /networks/$(network_id)
+
+Example response:
+
++-----------------+-----------------------------------+
+| Field           | Value                             |
++=================+===================================+
+| admin_state_up  | True                              |
++-----------------+-----------------------------------+
+| id              | 42                                |
++-----------------+-----------------------------------+
+| name            | Test_network                      |
++-----------------+-----------------------------------+
+| network_type    | MAC_FILTERED                      |
++-----------------+-----------------------------------+
+| router:external | False                             |
++-----------------+-----------------------------------+
+| public          | False                             |
++-----------------+-----------------------------------+
+| status          | ACTIVE                            |
++-----------------+-----------------------------------+
+| subnets         | []                                |
++-----------------+-----------------------------------+
+| user_id         | 1012fd8c72284c00b133832cd179f896  |
++-----------------+-----------------------------------+
+| tenant_id       | 1012fd8c72284c00b133832cd179f896  |
++-----------------+-----------------------------------+
+
+Delete a network
+^^^^^^^^^^^^^^^^
+
+METHOD: DELETE
+
+URI:  /networks/$(network_id)
+
+The network can not be deleted if there are any Ports connected to it or
+any FloatingIPs reserved from this network. The subnets that are connected
+to this network are automatically deleted upon network deletion.
+
+Update a network
+^^^^^^^^^^^^^^^^
+
+METHOD: PUT
+
+URI:  /networks/$(network_id)
+
+Only the name of the network can be updated.
+
+
+Subnets
+=======
+
+A subnet represents L3-Layer characteristics of the network that is
+associated with. Specifically it represents an IP address block that is
+used it assign addresses to virtual machines. A subnet is associated with
+a network when created.
+
+
+The attributes for subnet objects are the following:
+
+* id: A string represeting the UUID for the subnet.
+* name: A human readable name
+* network_id: The UUID of the network that the subnet is associated with.
+* ip_version: The IP version of the subnet. Can either be 4 or 6.
+* cidr: cidr representing IP range for this subnet, based on the IP version
+* gateway: Default gateway used by devices in this subnet. If not specified
+  the gateway will be the first available IP address. Set to None in order to
+  get no gateway.
+* enable_dhcp(CR): Boolean value indicating whether nfdhcpd is enabled for this
+  subnet or not .
+* allocation_pools(CR): Subranges of cidr available for dynamic allocation.
+  A list of dictionaries of the form {"start": "192.168.2.0", "end": 192.168.2.10"}
+* user_id/tenant_id: The UUID of the owner of the network.
+* host_routes(R): List of routes that should be used by devices with IPs from this
+                  subnet
+* dns_nameservers(R): List of DNS name servers used by hosts in this subnet.
+
+Note: 'host_routes' and 'dns_nameservers' is used only for compatibility with
+Neutron. These values will be read-only and always be [].
+
+
+Create a Subnet
+^^^^^^^^^^^^^^^
+
+METHOD: POST
+
+URI:  /subnets/
+
+To create a subnet the used must specify the network_id and the cidr for the
+subnet. If the CIDR is IPv6 subnet, the user must set the ip_version to 6.
+If allocation pools overlap, or gateway overlaps with allocation_pools then 409
+conflict is returned.
+
+Finally, the user can create maximum 1 subnet of each ip_version, meaning that
+a network can have no subnets, or one IPv4 subnet or one IPv6 subnet, or one
+IPv4 and one IPv6 subnet. Also the user can not create a subnet for a network
+that has or had a port connected to it.
+
+List user subnets
+^^^^^^^^^^^^^^^^^
+
+METHOD: GET
+
+URI:  /subnets/
+
+Get details about a subnet
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+METHOD: GET
+
+URI:  /subnets/$(subnet_id)
+
+Example response:
+
++------------------+--------------------------------------------------+
+| Field            | Value                                            |
++==================+==================================================+
+| allocation_pools | {"start": "192.168.2.2", "end": "192.168.2.254"} |
++------------------+--------------------------------------------------+
+| cidr             | 192.168.2.0/24                                   |
++------------------+--------------------------------------------------+
+| dns_nameservers  | []                                               |
++------------------+--------------------------------------------------+
+| enable_dhcp      | False                                            |
++------------------+--------------------------------------------------+
+| gateway_ip       | 192.168.2.1                                      |
++------------------+--------------------------------------------------+
+| host_routes      | []                                               |
++------------------+--------------------------------------------------+
+| id               | 49ce3872-446c-43e9-aa22-68dbc2bac0b5             |
++------------------+--------------------------------------------------+
+| ip_version       | 4                                                |
++------------------+--------------------------------------------------+
+| name             | test1                                            |
++------------------+--------------------------------------------------+
+| network_id       | 8fc5e2bf-9c1b-4458-8f71-e38177ed23a5             |
++------------------+--------------------------------------------------+
+| tenant_id        | 11a65261147d462b998eafb7f696f0ba                 |
++------------------+--------------------------------------------------+
+| user_id          | 11a65261147d462b998eafb7f696f0ba                 |
++------------------+--------------------------------------------------+
+
+
+Delete a subnet
+^^^^^^^^^^^^^^^^
+
+METHOD: DELETE
+
+URI:  /subnets/$(subnet_id)
+
+We will not allow deletion of subnets. Subnets will be deleted when network
+is deleted. This call will return 400 (badRequest).
+
+
+Update a subnet
+^^^^^^^^^^^^^^^^
+
+METHOD: PUT
+
+URI:  /subnets/$(subnet_id)
+
+
+Only the name of the subnet can be updated. This call will return 400 (badRequest)
+if the user tries to update any other field.
+
+
+Ports
+=====
+
+A port represent a virtual switch port on a network switch. Virtual machines
+attach their interefaces to ports. A port that is connected to a network
+gets an IP address for each subnet that is associated with the network. If the
+network has no subnets, then the port will have no IP.
+
+The attributes for port objects are the following:
+
+* id: A string represeting the UUID for the port.
+* network_id: The UUID of the network that this port is associated with.
+* name: A human readable name
+* status: String represetng the state of the port. Possible values for the
+  state include: ACTIVE, DOWN, BUILD, ERROR
+* mac_address: MAC address
+* fixed_ips(R): List of dictionaries subnet_id->ip_address.
+* device_id(CR): Device using this port (VM id or Router id)
+* device_owner(CR): Entity using this port. e.g network:router,
+  network:router_gateway
+* user_id/tenant_id: The UUID of the owner of the port.
+* security_groups(CRUD): List of security groups IDs associated with this port
+* admin_state_up: Boolean value indicating the administrative state of the
+  port. If 'down' the port does not forward packets.
+
+
+Note: The 'admin_state_up' value is used only for compatibility with Neutron
+API. It will be read-only, and will always be True.
+
+Create a new Port
+^^^^^^^^^^^^^^^^^^^^
+
+Method: POST
+
+URI: /ports
+
+The body of the request must contain the 'network_id' of the network that
+this port will be associated with and the 'device_id' that the port will
+be connected to. Also it can contain the following optional
+attributes:
+* security_groups
+* name
+
+The port will not have a MAC address and an IPv6 address until the
+corresponding NIC goes to ACTIVE state. This will be fixed when Cyclades
+will do MAC allocation. If MAC allocation is implemented, we will also
+be able to create a Port without specified a device_id.
+
+List ports
+^^^^^^^^^^^^^
+
+Method: GET
+
+URI: /ports
+
+Get details about a port
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+METHOD: GET
+
+URI:  /ports/$(port_id)
+
+Example response:
+
++-----------------------+---------------------------------------------------------------------------------+
+| Field                 | Value                                                                           |
++=======================+=================================================================================+
+| admin_state_up        | True                                                                            |
++-----------------------+---------------------------------------------------------------------------------+
+| device_id             | 39a02a66-33be-478a-8e9f-012141258678                                            |
++-----------------------+---------------------------------------------------------------------------------+
+| device_owner          | network:router_interface                                                        |
++-----------------------+---------------------------------------------------------------------------------+
+| fixed_ips             | {"subnet_id": "2313705f-68c1-4e16-80e3-c9fd8c0a5170", "ip_address": "10.0.2.1"} |
++-----------------------+---------------------------------------------------------------------------------+
+| id                    | ff15e3fe-7b39-4adc-ae98-a7e29588977e                                            |
++-----------------------+---------------------------------------------------------------------------------+
+| mac_address           | fa:16:3e:c1:63:06                                                               |
++-----------------------+---------------------------------------------------------------------------------+
+| name                  | "test_port"                                                                     |
++-----------------------+---------------------------------------------------------------------------------+
+| network_id            | 2f04b49f-ca49-4b93-9139-11a4eca35fdd                                            |
++-----------------------+---------------------------------------------------------------------------------+
+| security_groups       | []                                                                              |
++-----------------------+---------------------------------------------------------------------------------+
+| status                | DOWN                                                                            |
++-----------------------+---------------------------------------------------------------------------------+
+| tenant_id             | 1012fd8c72284c00b133832cd179f896                                                |
++-----------------------+---------------------------------------------------------------------------------+
+| user_id               | 1012fd8c72284c00b133832cd179f896                                                |
++-----------------------+---------------------------------------------------------------------------------+
+
+Delete a port
+^^^^^^^^^^^^^^^^
+
+METHOD: DELETE
+
+URI:  /ports/$(port_id)
+
+Update a port
+^^^^^^^^^^^^^^^^
+
+METHOD: PUT
+
+URI:  /ports/$(port_id)
+
+Only the name of the port can be updated.
+
+General Implementation Details
+==============================
+
+Creation of a network corresponds to only creating a Network object in Cyclades
+DB. Also, creation of a subnet corresponds to creation of a Subnet in Cyclades
+DB and the corresponding allocation pools. The Ganeti network will only be
+created in the Ganeti backend when a port is connected to this network.
+Updating fields of Ganeti networks is really hard (e.g. changing the dhcp
+option) or impossible (e.g. changing the subnet). For this reason, if the
+network has been created in a Ganeti backend, then it will be marked as
+read-only!
+
+A port is directly mapped to a Ganeti NIC. The port will be created in DB in
+"BUILD" state and an OP_INSTANCE_MODIFY will be issued to Ganeti to create the
+NIC in the specified VM. When the job successfully completes, the NIC will be
+updated in DB to state "ACTIVE". Also the MAC address that was allocated from
+Ganeti will be stored in the updated NIC.
