Browse Source

[5208a] Doc written, exception messages are now better formed.

Tomek Mrugalski 8 years ago
parent
commit
d22beff70d
2 changed files with 390 additions and 70 deletions
  1. 384 64
      doc/guide/hooks.xml
  2. 6 6
      src/lib/dhcpsrv/host_mgr.cc

+ 384 - 64
doc/guide/hooks.xml

@@ -219,11 +219,28 @@
               client. Those scenarios are addressed by the Flexible Identifiers
               hook application. It allows defining an expression, similar to
               the one used in client classification,
-	      e.g. substring(relay6[0].option[37],0,6). Each incoming packet is
-	      evaluated against that expression and its value is then searched
-	      in the reservations database.
+              e.g. substring(relay6[0].option[37],0,6). Each incoming packet is
+              evaluated against that expression and its value is then searched
+              in the reservations database.
               </entry>
             </row>
+            <row>
+              <entry>Host Commands</entry>
+              <entry>Support customers</entry>
+              <entry>Kea 1.2.0</entry>
+              <entry>Kea provides a way to store host reservations in a
+              database. In many larger deployments it is useful to be able to
+              manage that information while the server is running. This library
+              provides management commands for adding, querying and deleting
+              host reservations in a safe way without restarting the server.
+              In particular, it validates the parameters, so an attempt to
+              insert incorrect data, e.g. add a host with conflicting identifier
+              in the same subnet will be rejected. Those commands are
+              exposed via command channel (JSON over unix sockets) and Control
+              Agent (JSON over RESTful interface). Additional commands and
+              capabilities related to host reservations will be added in the
+              future.</entry>
+            </row>
           </tbody>
           </tgroup>
           </table>
@@ -547,7 +564,7 @@ link address: 3001::1, hop count: 1, identified by remote-id:
         </section>
       </section>
 
-      <section>
+      <section id="flex-id">
         <title>flex_id: Flexible Identifiers for Host Reservations</title>
         <para>
           This section describes a hook application dedicated to generate
@@ -560,25 +577,28 @@ link address: 3001::1, hop count: 1, identified by remote-id:
           options that mentioned above, uses part of specific options or perhaps
           even a combination of several options and fields to uniquely identify
           a client. Those scenarios are addressed by the Flexible Identifiers
-          hook application.</para>
-
-	<para>The library allows defining an expression, using notation
-	initially used for client classification only. See <xref
-	linkend="classification-using-expressions" /> for detailed description
-	of the syntax available. One notable difference is that for client
-	classification the expression currently has to evaluate to either true
-	or false, while the flexible identifier expression is expected to
-	evaluate to a string that will be used as identifier. It is a valid case
-	for the expression to evaluate to empty string (e.g. in cases where a
-	client does not sent specific options). This expression is then
-	evaluated for each incoming packet. This evaluation generates an
-	identifier that is used to identify the client. In particular, there may
-	be host reservations that are tied to specific values of the flexible
-	identifier.</para>
-
-	<para>
-	  The library can be loaded in similar way as other hook libraries. It
-	  takes one mandatory parameter identifier-expression:
+        hook application.</para>
+
+        <para>Currently this library is only available to ISC customers with a
+        support contract.</para>
+
+        <para>The library allows defining an expression, using notation
+        initially used for client classification only. See <xref
+        linkend="classification-using-expressions" /> for detailed description
+        of the syntax available. One notable difference is that for client
+        classification the expression currently has to evaluate to either true
+        or false, while the flexible identifier expression is expected to
+        evaluate to a string that will be used as identifier. It is a valid case
+        for the expression to evaluate to empty string (e.g. in cases where a
+        client does not sent specific options). This expression is then
+        evaluated for each incoming packet. This evaluation generates an
+        identifier that is used to identify the client. In particular, there may
+        be host reservations that are tied to specific values of the flexible
+        identifier.</para>
+
+        <para>
+          The library can be loaded in similar way as other hook libraries. It
+          takes one mandatory parameter identifier-expression:
 <screen>
 "Dhcp6": { <userinput>
     "hooks-libraries": [
@@ -592,26 +612,26 @@ link address: 3001::1, hop count: 1, identified by remote-id:
     ] </userinput>
 }
 </screen>
-	</para>
-
-	<para>
-	  The flexible identifier library supports both DHCPv4 and DHCPv6.
-	</para>
-
-	<para>
-	  EXAMPLE: Let's consider a case of an IPv6 network that has an
-	  independent interface for each of the connected customers. Customers
-	  are able to plug in whatever device they want, so any type of
-	  identifier (e.g. a client-id) is unreliable. Therefore the operator
-	  may decide to use an option inserted by a relay agent to differentiate
-	  between clients. In this particular deployment, the operator verified
-	  that the interface-id is unique for each customer facing
-	  interface. Therefore it is suitable for usage as reservation. However,
-	  only the first 6 bytes of the interface-id are interesting, because
-	  remaining bytes are either randomly changed or not unique between
-	  devices. Therefore the customer decided to use first 6 bytes of the
-	  interface-id option inserted by the relay agent. This could be
-	  achieved by using the following configuration:
+        </para>
+
+        <para>
+          The flexible identifier library supports both DHCPv4 and DHCPv6.
+        </para>
+
+        <para>
+          EXAMPLE: Let's consider a case of an IPv6 network that has an
+          independent interface for each of the connected customers. Customers
+          are able to plug in whatever device they want, so any type of
+          identifier (e.g. a client-id) is unreliable. Therefore the operator
+          may decide to use an option inserted by a relay agent to differentiate
+          between clients. In this particular deployment, the operator verified
+          that the interface-id is unique for each customer facing
+          interface. Therefore it is suitable for usage as reservation. However,
+          only the first 6 bytes of the interface-id are interesting, because
+          remaining bytes are either randomly changed or not unique between
+          devices. Therefore the customer decided to use first 6 bytes of the
+          interface-id option inserted by the relay agent. This could be
+          achieved by using the following configuration:
 <screen>
 "Dhcp6": {
     "subnet6": [{ ..., // subnet definition starts here
@@ -631,27 +651,327 @@ link address: 3001::1, hop count: 1, identified by remote-id:
     ]
 }
 </screen>
-	</para>
-
-	<para>
-	  NOTE: Care should be taken when adjusting the expression. If the
-	  expression changes, then all the flex-id values may change, possibly
-	  rendering all reservations based on flex-id unusable until they're
-	  manually updated. Therefore it is strongly recommended to start with
-	  the expression and a handful reservations, adjust the expression as
-	  needed and only after it was confirmed the expression does exactly
-	  what is expected out of it go forward with host reservations on any
-	  broader scale.
-	</para>
-
-	<para>
-	  flex-id values in host reservations can be specified in two
-	  ways. First, they can be expressed as hex string, e.g. bar string
-	  can be represented as 626174. Alternatively, it can be expressed
-	  as quoted value (using double and single quotes), e.g. "'bar'".
-	  The former is more convenient for printable characters, while hex
-	  string values are more convenient for non-printable characters.
-	</para>
+        </para>
+
+        <para>
+          NOTE: Care should be taken when adjusting the expression. If the
+          expression changes, then all the flex-id values may change, possibly
+          rendering all reservations based on flex-id unusable until they're
+          manually updated. Therefore it is strongly recommended to start with
+          the expression and a handful reservations, adjust the expression as
+          needed and only after it was confirmed the expression does exactly
+          what is expected out of it go forward with host reservations on any
+          broader scale.
+        </para>
+
+        <para>
+          flex-id values in host reservations can be specified in two
+          ways. First, they can be expressed as hex string, e.g. bar string
+          can be represented as 626174. Alternatively, it can be expressed
+          as quoted value (using double and single quotes), e.g. "'bar'".
+          The former is more convenient for printable characters, while hex
+          string values are more convenient for non-printable characters.
+        </para>
+      </section>
+
+      <section id="host-cmds">
+        <title>host_cmds: Host Commands</title>
+        <para>
+          This section describes a hook application that offers a number of new
+          commands used to query and manipulate host reservations. Kea provides
+          a way to store host reservations in a database. In many larger
+          deployments it is useful to be able to manage that information while
+          the server is running. This library provides management commands for
+          adding, querying and deleting host reservations in a safe way without
+          restarting the server.  In particular, it validates the parameters, so
+          an attempt to insert incorrect data e.g. add a host with conflicting
+          identifier in the same subnet will be rejected. Those commands are
+          exposed via command channel (JSON over unix sockets) and Control Agent
+          (JSON over RESTful interface). Additional commands and capabilities
+          related to host reservations will be added in the future.
+        </para>
+
+        <para>Currently this library is only available to ISC customers with a
+        support contract.</para>
+        
+        <para>
+          Currently three commands are supported: reservation-add (which adds
+          new host reservation), reservation-get (which returns existing
+          reservation if specified criteria are matched) and reservation-del
+          (which attempts to delete a reservation matching specified
+          criteria). To use commands that change the reservation information
+          (currently these are reservation-add and reservation-del, but this
+          rule applies to other commands that may be implemented in the future),
+          hosts database must be specified (see hosts-database description in
+          <xref linkend="hosts-database-configuration4"/> and <xref
+          linkend="hosts-database-configuration6"/>) and it must not operate in
+          read-only mode. If the hosts-database is not specified or is running
+          in read-only mode, the host_cmds library will load, but any attempts
+          to use reservation-add or reservation-del will fail.
+        </para>
+
+        <para>
+          Additional host reservation commands are planned in the future. For
+          a description of envisaged commands, see
+<ulink url="http://kea.isc.org/wiki/ControlAPIRequirements">Control API
+Requirements </ulink> document.</para>
+
+        <para>
+          All commands are using JSON syntax. They can be issued either using
+          control channel (see <xref linkend="ctrl-channel"/>) or via Control
+          Agent (see <xref linkend="kea-ctrl-agent"/>). 
+        </para>
+
+        <para>
+          The library can be loaded in similar way as other hook libraries. It
+          does not take any parameters. It supports both DHCPv4 and DHCPv6
+          servers.
+<screen>
+"Dhcp6": { <userinput>
+    "hooks-libraries": [
+        {
+            "library": "/path/libdhcp_host_cmds.so"
+        }
+        ...
+    ] </userinput>
+}
+</screen>
+        </para>
+
+        <section>
+          <title>reservation-add command</title>
+        <para>
+          <command>reservation-add</command> allows insertion of a new host.  It
+          takes a set of arguments that vary depending on the nature of the host
+          reservation. Any parameters allowed in the configuration file that
+          pertain to host reservation are permitted here. For details regarding
+          IPv4 reservations, see <xref linkend="host-reservation-v4"/> and <xref
+          linkend="host-reservation-v6"/>. There is one notable addition. A
+          <command>subnet-id</command> must be specified.  This parameter is
+          mandatory, because reservations specified in the configuration file
+          are always defined within a subnet, so the subnet they belong to is
+          clear. This is not the case with reservation-add, therefore the
+          subnet-id must be specified explicitly. An example command can be as
+          simple as:
+<screen>{
+    "command": "reservation-add",
+    "arguments": {
+        <userinput>"reservation": {
+            "subnet-id": 1,
+            "hw-address": "1a:1b:1c:1d:1e:1f",
+            "ip-address": "192.0.2.202"
+        }</userinput>
+    }
+}</screen> but can also take many more parameters, for example:
+
+<screen>
+{
+    "command": "reservation-add",
+    "arguments": {
+        <userinput>"reservation": {
+            {
+                "client-id": "01:0a:0b:0c:0d:0e:0f",
+                "ip-address": "192.0.2.205",
+                "next-server": "192.0.2.1",
+                "server-hostname": "hal9000",
+                "boot-file-name": "/dev/null",
+                "option-data": [
+                    {
+                        "name": "domain-name-servers",
+                        "data": "10.1.1.202,10.1.1.203"
+                    }
+                ],
+                "client-classes": [ "special_snowflake", "office" ]
+            }
+        }</userinput>
+    }
+}</screen>
+    
+Here is an example of complex IPv6 reservation:
+<screen>
+{
+    "command": "reservation-add",
+    "arguments": {
+        <userinput>"reservation": {
+            {
+                "duid": "01:02:03:04:05:06:07:08:09:0A",
+                "ip-addresses": [ "2001:db8:1:cafe::1" ],
+                "prefixes": [ "2001:db8:2:abcd::/64" ],
+                "hostname": "foo.example.com",
+                "option-data": [
+                    {
+                        "name": "vendor-opts",
+                        "data": "4491"
+                    },
+                    {
+                        "name": "tftp-servers",
+                        "space": "vendor-4491",
+                        "data": "3000:1::234"
+                    }
+                ]
+            }
+        }</userinput>
+    }
+}</screen>
+        </para>          
+
+        <para>
+          The command returns a status that indicates either a success (result
+          0) or a failure (result 1). Failed command always includes text
+          parameter that explains the cause of failure. Example results:
+          <screen>{ "result": 0, "text": "Host added." }</screen> Example failure:
+          <screen>{ "result": 1, "text": "Mandatory 'subnet-id' parameter missing." }</screen>
+        </para>
+
+        <para>
+          As <command>reservation-add</command> is expected to store the host,
+          hosts-database parameter must be specified in your configuration and
+          the database must not run in read-only mode. In the future versions
+          it will be possible to modify the reservations read from a
+          configuration file. Please contact ISC if you are interested in this
+          functionality.
+        </para>
+        </section>
+
+        <section>
+          <title>reservation-get command</title>
+          <para><command>reservation-get</command> can be used to query the host
+          database and retrieve existing reservations. There are two types of
+          parameters this command supports: (subnet-id, address) or (subnet-id,
+          identifier-type, identifier). The first type of query is used when the
+          address (either IPv4 or IPv6) is known, but the details of the
+          reservation aren't. One common use case of this type of query is to
+          find out whether a given address is reserved or not. The second query
+          uses identifiers. For maximum flexibility, Kea stores the host
+          identifying information as a pair of values: type and the actual
+          identifier. Currently supported identifiers are "hw-address", "duid",
+          "circuit-id", "client-id" and "flex-id", but additional types may be
+          added in the future. If any new identifier types are defined in the
+          future, reservation-get command will support them
+          automatically.</para>
+
+          <para>
+            An example command for getting a host reservation by (subnet-id,
+            address) pair looks as follows:
+<screen>
+{
+    "command": "reservation-get",
+    "arguments": {
+        "subnet-id": 1,
+        "ip-address": "192.0.2.202"
+    }
+}</screen>
+
+An example query by (subnet-id, identifier-type, identifier) looks as follows:
+<screen>
+{
+    "command": "reservation-get",
+    "arguments":
+        "subnet-id": 4,
+        "identifier-type": "hw-address",
+        "identifier": "01:02:03:04:05:06"
+    }
+}</screen>
+
+          </para>
+          <para><command>reservation-get</command> typically returns result 0
+          when the query was conducted properly. In particular, 0 is returned
+          when the host was not found. If the query was successful a number
+          of host parameters will be returned. An example of a query that
+          did not find the host looks as follows:
+<screen>{ "result": 0, "text": "Host not found." }</screen>
+
+An example result returned when the host was found:
+<screen>{
+  "arguments": {
+    "boot-file-name": "bootfile.efi",
+    "client-classes": [
+      
+    ],
+    "hostname": "somehost.example.org",
+    "hw-address": "01:02:03:04:05:06",
+    "ip-address": "192.0.2.100",
+    "next-server": "192.0.0.2",
+    "option-data": [
+      
+    ],
+    "server-hostname": "server-hostname.example.org"
+  },
+  "result": 0,
+  "text": "Host found."
+}</screen>
+
+An example result returned when the query was malformed:<screen>
+{ "result": 1, "text": "No 'ip-address' provided and 'identifier-type'
+                        is either missing or not a string." }</screen>
+</para>
+            
+        </section>
+
+        <section>
+          <title>reservation-del command</title>
+          <para><command>reservation-del</command> can be used to delete a
+          reservation from the host database. There are two types of parameters
+          this command supports: (subnet-id, address) or (subnet-id,
+          identifier-type, identifier). The first type of query is used when the
+          address (either IPv4 or IPv6) is known, but the details of the
+          reservation aren't. One common use case of this type of query is to
+          remove a reservation (e.g. you want a specific address to no longer be
+          reserved). The second query uses identifiers. For maximum flexibility,
+          Kea stores the host identifying information as a pair of values: type
+          and the actual identifier. Currently supported identifiers are
+          "hw-address", "duid", "circuit-id", "client-id" and "flex-id", but
+          additional types may be added in the future. If any new identifier
+          types are defined in the future, reservation-get command will support
+          them automatically.</para>
+
+          <para>
+            An example command for deleting a host reservation by (subnet-id,
+            address) pair looks as follows:
+<screen>
+{
+    "command": "reservation-del",
+    "arguments": {
+        "subnet-id": 1,
+        "ip-address": "192.0.2.202"
+    }
+}</screen>
+
+An example deletion by (subnet-id, identifier-type, identifier) looks as follows:
+<screen>
+{
+    "command": "reservation-del",
+    "arguments":
+        "subnet-id": 4,
+        "identifier-type": "hw-address",
+        "identifier": "01:02:03:04:05:06"
+    }
+}</screen>
+          </para>
+          <para>
+            <command>reservation-del</command> returns result 0 when the host
+            deletion was successul or 1 if it was not. A descriptive text is
+            provided in case of error. Example results look as follows:
+<screen>
+{
+    "result": 1,
+    "text": "Host not deleted (not found)."
+}</screen>
+
+<screen>          
+{
+    "result": 0,
+    "text": "Host deleted."
+}</screen>
+
+<screen>
+{
+    "result": 1,
+    "text": "Unable to delete a host because there is no hosts-database
+             configured."
+}</screen>
+          </para>
+        </section>
       </section>
 
     </section>

+ 6 - 6
src/lib/dhcpsrv/host_mgr.cc

@@ -216,8 +216,8 @@ HostMgr::get6(const SubnetID& subnet_id,
 void
 HostMgr::add(const HostPtr& host) {
     if (!alternate_source_) {
-        isc_throw(NoHostDataSourceManager, "unable to add new host because there is "
-                  "no alternate host data source present");
+        isc_throw(NoHostDataSourceManager, "Unable to add new host because there is "
+                  "no hosts-database configured.");
     }
     alternate_source_->add(host);
 }
@@ -225,8 +225,8 @@ HostMgr::add(const HostPtr& host) {
 bool
 HostMgr::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
     if (!alternate_source_) {
-        isc_throw(NoHostDataSourceManager, "unable to delete a host because there is "
-                  "no alternate host data source present");
+        isc_throw(NoHostDataSourceManager, "Unable to delete a host because there is "
+                  "no hosts-database configured.");
     }
 
     return (alternate_source_->del(subnet_id, addr));
@@ -236,8 +236,8 @@ bool
 HostMgr::del4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
               const uint8_t* identifier_begin, const size_t identifier_len) {
     if (!alternate_source_) {
-        isc_throw(NoHostDataSourceManager, "unable to delete a host because there is "
-                  "no alternate host data source present");
+        isc_throw(NoHostDataSourceManager, "Unable to delete a host because there is "
+                  "no hosts-database configured.");
     }
 
     return (alternate_source_->del4(subnet_id, identifier_type,