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
               client. Those scenarios are addressed by the Flexible Identifiers
               hook application. It allows defining an expression, similar to
               hook application. It allows defining an expression, similar to
               the one used in client classification,
               the one used in client classification,
-	      e.g. substring(relay6[0].option[37],0,6). Each incoming packet is
+              e.g. substring(relay6[0].option[37],0,6). Each incoming packet is
-	      evaluated against that expression and its value is then searched
+              evaluated against that expression and its value is then searched
-	      in the reservations database.
+              in the reservations database.
               </entry>
               </entry>
             </row>
             </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>
           </tbody>
           </tgroup>
           </tgroup>
           </table>
           </table>
@@ -547,7 +564,7 @@ link address: 3001::1, hop count: 1, identified by remote-id:
         </section>
         </section>
       </section>
       </section>
 
 
-      <section>
+      <section id="flex-id">
         <title>flex_id: Flexible Identifiers for Host Reservations</title>
         <title>flex_id: Flexible Identifiers for Host Reservations</title>
         <para>
         <para>
           This section describes a hook application dedicated to generate
           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
           options that mentioned above, uses part of specific options or perhaps
           even a combination of several options and fields to uniquely identify
           even a combination of several options and fields to uniquely identify
           a client. Those scenarios are addressed by the Flexible Identifiers
           a client. Those scenarios are addressed by the Flexible Identifiers
-          hook application.</para>
+        hook application.</para>
-
+
-	<para>The library allows defining an expression, using notation
+        <para>Currently this library is only available to ISC customers with a
-	initially used for client classification only. See <xref
+        support contract.</para>
-	linkend="classification-using-expressions" /> for detailed description
+
-	of the syntax available. One notable difference is that for client
+        <para>The library allows defining an expression, using notation
-	classification the expression currently has to evaluate to either true
+        initially used for client classification only. See <xref
-	or false, while the flexible identifier expression is expected to
+        linkend="classification-using-expressions" /> for detailed description
-	evaluate to a string that will be used as identifier. It is a valid case
+        of the syntax available. One notable difference is that for client
-	for the expression to evaluate to empty string (e.g. in cases where a
+        classification the expression currently has to evaluate to either true
-	client does not sent specific options). This expression is then
+        or false, while the flexible identifier expression is expected to
-	evaluated for each incoming packet. This evaluation generates an
+        evaluate to a string that will be used as identifier. It is a valid case
-	identifier that is used to identify the client. In particular, there may
+        for the expression to evaluate to empty string (e.g. in cases where a
-	be host reservations that are tied to specific values of the flexible
+        client does not sent specific options). This expression is then
-	identifier.</para>
+        evaluated for each incoming packet. This evaluation generates an
-
+        identifier that is used to identify the client. In particular, there may
-	<para>
+        be host reservations that are tied to specific values of the flexible
-	  The library can be loaded in similar way as other hook libraries. It
+        identifier.</para>
-	  takes one mandatory parameter identifier-expression:
+
+        <para>
+          The library can be loaded in similar way as other hook libraries. It
+          takes one mandatory parameter identifier-expression:
 <screen>
 <screen>
 "Dhcp6": { <userinput>
 "Dhcp6": { <userinput>
     "hooks-libraries": [
     "hooks-libraries": [
@@ -592,26 +612,26 @@ link address: 3001::1, hop count: 1, identified by remote-id:
     ] </userinput>
     ] </userinput>
 }
 }
 </screen>
 </screen>
-	</para>
+        </para>
-
+
-	<para>
+        <para>
-	  The flexible identifier library supports both DHCPv4 and DHCPv6.
+          The flexible identifier library supports both DHCPv4 and DHCPv6.
-	</para>
+        </para>
-
+
-	<para>
+        <para>
-	  EXAMPLE: Let's consider a case of an IPv6 network that has an
+          EXAMPLE: Let's consider a case of an IPv6 network that has an
-	  independent interface for each of the connected customers. Customers
+          independent interface for each of the connected customers. Customers
-	  are able to plug in whatever device they want, so any type of
+          are able to plug in whatever device they want, so any type of
-	  identifier (e.g. a client-id) is unreliable. Therefore the operator
+          identifier (e.g. a client-id) is unreliable. Therefore the operator
-	  may decide to use an option inserted by a relay agent to differentiate
+          may decide to use an option inserted by a relay agent to differentiate
-	  between clients. In this particular deployment, the operator verified
+          between clients. In this particular deployment, the operator verified
-	  that the interface-id is unique for each customer facing
+          that the interface-id is unique for each customer facing
-	  interface. Therefore it is suitable for usage as reservation. However,
+          interface. Therefore it is suitable for usage as reservation. However,
-	  only the first 6 bytes of the interface-id are interesting, because
+          only the first 6 bytes of the interface-id are interesting, because
-	  remaining bytes are either randomly changed or not unique between
+          remaining bytes are either randomly changed or not unique between
-	  devices. Therefore the customer decided to use first 6 bytes of the
+          devices. Therefore the customer decided to use first 6 bytes of the
-	  interface-id option inserted by the relay agent. This could be
+          interface-id option inserted by the relay agent. This could be
-	  achieved by using the following configuration:
+          achieved by using the following configuration:
 <screen>
 <screen>
 "Dhcp6": {
 "Dhcp6": {
     "subnet6": [{ ..., // subnet definition starts here
     "subnet6": [{ ..., // subnet definition starts here
@@ -631,27 +651,327 @@ link address: 3001::1, hop count: 1, identified by remote-id:
     ]
     ]
 }
 }
 </screen>
 </screen>
-	</para>
+        </para>
-
+
-	<para>
+        <para>
-	  NOTE: Care should be taken when adjusting the expression. If the
+          NOTE: Care should be taken when adjusting the expression. If the
-	  expression changes, then all the flex-id values may change, possibly
+          expression changes, then all the flex-id values may change, possibly
-	  rendering all reservations based on flex-id unusable until they're
+          rendering all reservations based on flex-id unusable until they're
-	  manually updated. Therefore it is strongly recommended to start with
+          manually updated. Therefore it is strongly recommended to start with
-	  the expression and a handful reservations, adjust the expression as
+          the expression and a handful reservations, adjust the expression as
-	  needed and only after it was confirmed the expression does exactly
+          needed and only after it was confirmed the expression does exactly
-	  what is expected out of it go forward with host reservations on any
+          what is expected out of it go forward with host reservations on any
-	  broader scale.
+          broader scale.
-	</para>
+        </para>
-
+
-	<para>
+        <para>
-	  flex-id values in host reservations can be specified in two
+          flex-id values in host reservations can be specified in two
-	  ways. First, they can be expressed as hex string, e.g. bar string
+          ways. First, they can be expressed as hex string, e.g. bar string
-	  can be represented as 626174. Alternatively, it can be expressed
+          can be represented as 626174. Alternatively, it can be expressed
-	  as quoted value (using double and single quotes), e.g. "'bar'".
+          as quoted value (using double and single quotes), e.g. "'bar'".
-	  The former is more convenient for printable characters, while hex
+          The former is more convenient for printable characters, while hex
-	  string values are more convenient for non-printable characters.
+          string values are more convenient for non-printable characters.
-	</para>
+        </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>
 
 
     </section>
     </section>

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

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