[Freeipa-devel] DHCP support - Request for review

William Brown william at firstyear.id.au
Wed Jun 27 13:32:20 UTC 2012


Hi,

I have been working on adding support for FreeIPA to support
configuration storage for ISC-DHCP 4.X servers. I have added the schema
which is included at installation, added the template / empty files that
will be filled in and used for the installation and created the ipalib
plugin for this. At this stage, this feature is still far from done. I
would appreciate a review of the work I have done to ensure I am on the
right track.

I would like to know if there is a better way to add ACLs than by
manually updating ldap by hand (IE, using the ACL libraries) (See
/install/share/dhcpd.ldif).

-- 
Sincerely,

William Brown

pgp.mit.edu
http://pgp.mit.edu:11371/pks/lookup?op=vindex&search=0x3C0AC6DAB2F928A2

-------------- next part --------------
From 6ea88fce9cde90e357164b77933591b7a6bacd1b Mon Sep 17 00:00:00 2001
From: William Brown <william at firstyear.id.au>
Date: Mon, 7 May 2012 14:28:15 +0930
Subject: [PATCH] Create patch for review of DHCP support

---
 .gitignore                        |    1 +
 TODO.DHCP                         |   41 +++
 install/share/60dhcpd.ldif        |  550 +++++++++++++++++++++++++++++++++
 install/share/Makefile.am         |    2 +
 install/share/dhcpd.ldif          |   90 ++++++
 install/tools/Makefile.am         |    1 +
 install/tools/ipa-dhcp-install    |   24 ++
 ipalib/constants.py               |    1 +
 ipalib/plugins/dhcp.py            |  601 +++++++++++++++++++++++++++++++++++++
 ipaserver/install/Makefile.am     |    1 +
 ipaserver/install/dhcpinstance.py |  134 +++++++++
 ipaserver/install/dsinstance.py   |    1 +
 ipaserver/install/service.py      |    2 +
 13 files changed, 1449 insertions(+)
 create mode 100644 TODO.DHCP
 create mode 100644 install/share/60dhcpd.ldif
 create mode 100644 install/share/dhcpd.ldif
 create mode 100644 install/tools/ipa-dhcp-install
 create mode 100644 ipalib/plugins/dhcp.py
 create mode 100644 ipaserver/install/dhcpinstance.py

diff --git a/.gitignore b/.gitignore
index d20747c04b22a30866a8996ee2bcdf10ca4d471b..fb4fd402153430587bd496cd302c9ece12ff297d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@ Makefile.in
 *.lo
 *.o
 *.pyc
+*.swp
 .bzr
 freeipa2-dev-doc
 build
diff --git a/TODO.DHCP b/TODO.DHCP
new file mode 100644
index 0000000000000000000000000000000000000000..c09790af7a67bb60bb22f4943833f6d347cf8ce2
--- /dev/null
+++ b/TODO.DHCP
@@ -0,0 +1,41 @@
+DHCP server integration todo list 
+=================================
+
+See http://www.freeipa.org/page/DHCP_Integration_Design
+
+Stage 1)
+
+- Add DHCPD schema files to be installed as part of the IPA server installation. (DONE, AWAITING TEST)
+- Add DHCP installation option. This option can be modeled off the DNS option, as they are both "optional". 
+	- An installer file must be created into ipaserver/install/dhcpinstance.py  (DONE, needs CODING)
+		- This installation should populate some basic information into the LDAP tree (This is done in freeipa/install/share/dhcpd.ldif). There is an example of how to do this in ./ipaserver/install/bindinstance.py:509. (DONE, ADD TO dhcpinstance.py, INCLUDES INDICIES)
+		    - This should also create the necesarry anonymous service accounts and keys.
+            - Support multiple locations for the installation. Each install can support two server in failover mode.
+	        - We need to also setup DHCP 389ds permissions 
+                - DHCP admin permission, that should be able to modify and read the contents of cn=dhcp
+                - Dhcp viewer permission.
+                - DHCP server permission. This can read the server information, but it can write to the leases subtree. 
+		    - This should create the dhcpd.conf, dhcpd6.conf and dhrelay.conf.
+                - What do we do about radvd.conf?
+            -For the installer to work, we need to create the public api in ipalib/plugins/dhcp.py. We also need to register some constants into contstants.py in the same DIR
+- The manpage for this should be updated. ./install/tools/man/ipa-dhcp-install.1
+- Add support for IPA admin tool to interact with the ldap dhcp information.
+
+Stage 1.5)
+
+- Add 60dhcpd.ldif to the ISC-DHCP source tree for maintenence.  (DONE, AWAITING APPROVAL)
+- Add support for ISC-DHCP to authenticate with GSSAPI to the LDAP server.
+	- Update configure.ac at line 631 to support GSSAPI flag
+	- This should check for the relevant GSSAPI libaries
+	- GSSAPI support should be added to ldap_rebind_cb. This handles all the auth.
+	- We need to add the KRB5 config options to be parsed in ldap_start 
+		- How do we add options? Stables.c?
+
+Stage 2)
+
+- Add support for IPA admin tool to create a dhcpd.conf, or rather, dhcrelay on a machine joined to the domain.
+
+Stage 3)
+
+- Work on the WEB UI components. 
+
diff --git a/install/share/60dhcpd.ldif b/install/share/60dhcpd.ldif
new file mode 100644
index 0000000000000000000000000000000000000000..ecdd78f57f23ea7ebe617c5265c7bc56d42ce914
--- /dev/null
+++ b/install/share/60dhcpd.ldif
@@ -0,0 +1,550 @@
+dn: cn=schema
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.1
+  NAME 'dhcpPrimaryDN'
+  DESC 'The DN of the dhcpServer which is the primary server for the configuration.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.2
+  NAME 'dhcpSecondaryDN'
+  DESC 'The DN of dhcpServer(s) which provide backup service for the configuration.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.3
+  NAME 'dhcpStatements'
+  DESC 'Flexible storage for specific data depending on what object this exists in. Like conditional statements, server parameters, etc. This allows the standard to evolve without needing to adjust the schema.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.4
+  NAME 'dhcpRange'
+  DESC 'The starting & ending IP Addresses in the range (inclusive), separated by a hyphen; if the range only contains one address, then just the address can be specified with no hyphen. Each range is defined as a separate value.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.5
+  NAME 'dhcpPermitList'
+  DESC 'This attribute contains the permit lists associated with a pool. Each permit list is defined as a separate value.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.6
+  NAME 'dhcpNetMask'
+  DESC 'The subnet mask length for the subnet. The mask can be easily computed from this length.'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.7
+  NAME 'dhcpOption'
+  DESC 'Encoded option values to be sent to clients. Each value represents a single option and contains (OptionTag, Length, OptionValue) encoded in the format used by DHCP.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.8
+  NAME 'dhcpClassData'
+  DESC 'Encoded text string or list of bytes expressed in hexadecimal, separated by colons. Clients match subclasses based on matching the class data with the results of match or spawn with statements in the class name declarations.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.9
+  NAME 'dhcpOptionsDN'
+  DESC 'The distinguished name(s) of the dhcpOption objects containing the configuration options provided by the server.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.10
+  NAME 'dhcpHostDN'
+  DESC 'the distinguished name(s) of the dhcpHost objects.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.11
+  NAME 'dhcpPoolDN'
+  DESC 'The distinguished name(s) of pools.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.12
+  NAME 'dhcpGroupDN'
+  DESC 'The distinguished name(s) of the groups.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.13
+  NAME 'dhcpSubnetDN'
+  DESC 'The distinguished name(s) of the subnets.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.14
+  NAME 'dhcpLeaseDN'
+  DESC 'The distinguished name of a client address.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.15
+  NAME 'dhcpLeasesDN'
+  DESC 'The distinguished name(s) client addresses.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.16
+  NAME 'dhcpClassesDN'
+  DESC 'The distinguished name(s) of a class(es) in a subclass.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.17
+  NAME 'dhcpSubclassesDN'
+  DESC 'The distinguished name(s) of subclass(es).'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.18
+  NAME 'dhcpSharedNetworkDN'
+  DESC 'The distinguished name(s) of sharedNetworks.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.19
+  NAME 'dhcpServiceDN'
+  DESC 'The DN of dhcpService object(s)which contain the configuration information. Each dhcpServer object has this attribute identifying the DHCP configuration(s) that the server is associated with.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.20
+  NAME 'dhcpVersion'
+  DESC 'The version attribute of this object.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.21
+  NAME 'dhcpImplementation'
+  DESC 'Description of the DHCP Server implementation e.g. DHCP Servers vendor.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.22
+  NAME 'dhcpAddressState'
+  DESC 'This stores information about the current binding-status of an address. For dynamic addresses managed by DHCP, the values should be restricted to the following: "FREE", "ACTIVE", "EXPIRED", "RELEASED", "RESET", "ABANDONED", "BACKUP". For other addresses, it SHOULD be one of the following: "UNKNOWN", "RESERVED" (an address that is managed by DHCP that is reserved for a specific client), "RESERVED-ACTIVE" (same as reserved, but address is currently in use), "ASSIGNED" (assigned manually or by some other mechanism), "UNASSIGNED", "NOTASSIGNABLE".'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.23
+  NAME 'dhcpExpirationTime'
+  DESC 'This is the time the current lease for an address expires.'
+  EQUALITY generalizedTimeMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.24
+  NAME 'dhcpStartTimeOfState'
+  DESC 'This is the time of the last state change for a leased address.'
+  EQUALITY generalizedTimeMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.25
+  NAME 'dhcpLastTransactionTime'
+  DESC 'This is the last time a valid DHCP packet was received from the client.'
+  EQUALITY generalizedTimeMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.26
+  NAME 'dhcpBootpFlag'
+  DESC 'This indicates whether the address was assigned via BOOTP.'
+  EQUALITY booleanMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.27
+  NAME 'dhcpDomainName'
+  DESC 'This is the name of the domain sent to the client by the server. It is essentially the same as the value for DHCP option 15 sent to the client, and represents only the domain - not the full FQDN. To obtain the full FQDN assigned to the client you must prepend the "dhcpAssignedHostName" to this value with a ".".'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.28
+  NAME 'dhcpDnsStatus'
+  DESC 'This indicates the status of updating DNS resource records on behalf of the client by the DHCP server for this address. The value is a 16-bit bitmask.'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.29
+  NAME 'dhcpRequestedHostName'
+  DESC 'This is the hostname that was requested by the client.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.30
+  NAME 'dhcpAssignedHostName'
+  DESC 'This is the actual hostname that was assigned to a client. It may not be the name that was requested by the client. The fully qualified domain name can be determined by appending the value of "dhcpDomainName" (with a dot separator) to this name.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.31
+  NAME 'dhcpReservedForClient'
+  DESC 'The distinguished name of a "dhcpClient" that an address is reserved for. This may not be the same as the "dhcpAssignedToClient" attribute if the address is being reassigned but the current lease has not yet expired.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.32
+  NAME 'dhcpAssignedToClient'
+  DESC 'This is the distinguished name of a "dhcpClient" that an address is currently assigned to. This attribute is only present in the class when the address is leased.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.33
+  NAME 'dhcpRelayAgentInfo'
+  DESC 'If the client request was received via a relay agent, this contains information about the relay agent that was available from the DHCP request. This is a hex-encoded option value.'
+  EQUALITY octetStringMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.34
+  NAME 'dhcpHWAddress'
+  DESC 'The clients hardware address that requested this IP address.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.35
+  NAME 'dhcpHashBucketAssignment'
+  DESC 'HashBucketAssignment bit map for the DHCP Server, as defined in DHC Load Balancing Algorithm [RFC 3074].'
+  EQUALITY octetStringMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.36
+  NAME 'dhcpDelayedServiceParameter'
+  DESC 'Delay in seconds corresponding to Delayed Service Parameter configuration, as defined in DHC Load Balancing Algorithm [RFC 3074]. '
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.37
+  NAME 'dhcpMaxClientLeadTime'
+  DESC 'Maximum Client Lead Time configuration in seconds, as defined in DHCP Failover Protocol [FAILOVR]'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.38
+  NAME 'dhcpFailOverEndpointState'
+  DESC 'Server (Failover Endpoint) state, as defined in DHCP Failover Protocol [FAILOVR]'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.39
+  NAME 'dhcpErrorLog'
+  DESC 'Generic error log attribute that allows logging error conditions within a dhcpService or a dhcpSubnet, like no IP addresses available for lease.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.40
+  NAME 'dhcpLocatorDN'
+  DESC 'The DN of dhcpLocator object which contain the DNs of all DHCP configuration objects. There will be a single dhcpLocator object in the tree with links to all the DHCP objects in the tree'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.41
+  NAME 'dhcpKeyAlgorithm'
+  DESC 'Algorithm to generate TSIG Key'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.42
+  NAME 'dhcpKeySecret'
+  DESC 'Secret to generate TSIG Key'
+  EQUALITY octetStringMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.43
+  NAME 'dhcpDnsZoneServer'
+  DESC 'Master server of the DNS Zone'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.44
+  NAME 'dhcpKeyDN'
+  DESC 'The DNs of TSIG Key to use in secure dynamic updates. In case of locator object, this will be list of TSIG keys. In case of DHCP Service, Shared Network, Subnet and DNS Zone, it will be a single key.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.45
+  NAME 'dhcpZoneDN'
+  DESC 'The DNs of DNS Zone. In case of locator object, this will be list of DNS Zones in the tree. In case of DHCP Service, Shared Network and Subnet, it will be a single DNS Zone.'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.46
+  NAME 'dhcpFailOverPrimaryServer'
+  DESC 'IP address or DNS name of the server playing primary role in DHC Load Balancing and Fail over.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.47
+  NAME 'dhcpFailOverSecondaryServer'
+  DESC 'IP address or DNS name of the server playing secondary role in DHC Load Balancing and Fail over.'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.48
+  NAME 'dhcpFailOverPrimaryPort'
+  DESC 'Port on which primary server listens for connections from its fail over peer (secondary server)'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.49
+  NAME 'dhcpFailOverSecondaryPort'
+  DESC 'Port on which secondary server listens for connections from its fail over peer (primary server)'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.50
+  NAME 'dhcpFailOverResponseDelay'
+  DESC 'Maximum response time in seconds, before Server assumes that connection to fail over peer has failed'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.51
+  NAME 'dhcpFailOverUnackedUpdates'
+  DESC 'Number of BNDUPD messages that server can send before it receives BNDACK from its fail over peer'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.52
+  NAME 'dhcpFailOverSplit'
+  DESC 'Split between the primary and secondary servers for fail over purpose'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.53
+  NAME 'dhcpFailOverLoadBalanceTime'
+  DESC 'Cutoff time in seconds, after which load balance is disabled'
+  EQUALITY integerMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.54
+  NAME 'dhcpFailOverPeerDN'
+  DESC 'The DNs of Fail over peers. In case of locator object, this will be list of fail over peers in the tree. In case of Subnet and pool, it will be a single Fail Over Peer'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.55
+  NAME 'dhcpServerDN'
+  DESC 'List of all DHCP Servers in the tree. Used by dhcpLocatorObject'
+  EQUALITY distinguishedNameMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+  )
+attributeTypes: (
+  2.16.840.1.113719.1.203.4.56
+  NAME 'dhcpComments'
+  DESC 'Generic attribute that allows coments within any DHCP object'
+  EQUALITY caseIgnoreIA5Match
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+  SINGLE-VALUE
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.1
+  NAME 'dhcpService'
+  DESC 'Service object that represents the actual DHCP Service configuration. This is a container object.'
+  SUP top
+  MUST ( cn )
+  MAY ( dhcpPrimaryDN $ dhcpSecondaryDN $ dhcpServerDN $ dhcpSharedNetworkDN $ dhcpSubnetDN $ dhcpGroupDN $ dhcpHostDN $ dhcpClassesDN $ dhcpOptionsDN $ dhcpZoneDN $ dhcpKeyDN $ dhcpFailOverPeerDN $ dhcpStatements $dhcpComments $ dhcpOption )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.2
+  NAME 'dhcpSharedNetwork'
+  DESC 'This stores configuration information for a shared network.'
+  SUP top
+  MUST cn
+  MAY ( dhcpSubnetDN $ dhcpPoolDN $ dhcpOptionsDN $ dhcpZoneDN $ dhcpStatements $dhcpComments $ dhcpOption )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.3
+  NAME 'dhcpSubnet'
+  DESC 'This class defines a subnet. This is a container object.'
+  SUP top
+  MUST ( cn $ dhcpNetMask )
+  MAY ( dhcpRange $ dhcpPoolDN $ dhcpGroupDN $ dhcpHostDN $ dhcpClassesDN $ dhcpLeasesDN $ dhcpOptionsDN $ dhcpZoneDN $ dhcpKeyDN $ dhcpFailOverPeerDN $ dhcpStatements $ dhcpComments $ dhcpOption )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.4
+  NAME 'dhcpPool'
+  DESC 'This stores configuration information about a pool.'
+  SUP top
+  MUST ( cn $ dhcpRange )
+  MAY ( dhcpClassesDN $ dhcpPermitList $ dhcpLeasesDN $ dhcpOptionsDN $ dhcpZoneDN $dhcpKeyDN $ dhcpStatements $ dhcpComments $ dhcpOption )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.5
+  NAME 'dhcpGroup'
+  DESC 'Group object that lists host DNs and parameters. This is a container object.'
+  SUP top
+  MUST cn
+  MAY ( dhcpHostDN $ dhcpOptionsDN $ dhcpStatements $ dhcpComments $ dhcpOption )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.6
+  NAME 'dhcpHost'
+  DESC 'This represents information about a particular client'
+  SUP top
+  MUST cn
+  MAY ( dhcpLeaseDN $ dhcpHWAddress $ dhcpOptionsDN $ dhcpStatements $ dhcpComments $ dhcpOption )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.7
+  NAME 'dhcpClass'
+  DESC 'Represents information about a collection of related clients.'
+  SUP top
+  MUST cn
+  MAY ( dhcpSubClassesDN $ dhcpOptionsDN $ dhcpStatements $ dhcpComments $ dhcpOption )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.8
+  NAME 'dhcpSubClass'
+  DESC 'Represents information about a collection of related classes.'
+  SUP top
+  MUST cn
+  MAY ( dhcpClassData $ dhcpOptionsDN $ dhcpStatements $ dhcpComments $ dhcpOption )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.9
+  NAME 'dhcpOptions'
+  DESC 'Represents information about a collection of options defined.'
+  SUP top
+  AUXILIARY
+  MUST cn
+  MAY ( dhcpOption $ dhcpComments )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.10
+  NAME 'dhcpLeases'
+  DESC 'This class represents an IP Address, which may or may not have been leased.'
+  SUP top
+  MUST ( cn $ dhcpAddressState )
+  MAY ( dhcpExpirationTime $ dhcpStartTimeOfState $ dhcpLastTransactionTime $ dhcpBootpFlag $ dhcpDomainName $ dhcpDnsStatus $ dhcpRequestedHostName $ dhcpAssignedHostName $ dhcpReservedForClient $ dhcpAssignedToClient $ dhcpRelayAgentInfo $ dhcpHWAddress )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.11
+  NAME 'dhcpLog'
+  DESC 'This is the object that holds past information about the IP address. The cn is the time/date stamp when the address was assigned or released, the address state at the time, if the address was assigned or released.'
+  SUP top
+  MUST ( cn )
+  MAY ( dhcpAddressState $ dhcpExpirationTime $ dhcpStartTimeOfState $ dhcpLastTransactionTime $ dhcpBootpFlag $ dhcpDomainName $ dhcpDnsStatus $ dhcpRequestedHostName $ dhcpAssignedHostName $ dhcpReservedForClient $ dhcpAssignedToClient $ dhcpRelayAgentInfo $ dhcpHWAddress $ dhcpErrorLog )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.12
+  NAME 'dhcpServer'
+  DESC 'DHCP Server Object'
+  SUP top
+  MUST ( cn )
+  MAY ( dhcpServiceDN $ dhcpLocatorDN $ dhcpVersion $ dhcpImplementation $ dhcpHashBucketAssignment $ dhcpDelayedServiceParameter $ dhcpMaxClientLeadTime $ dhcpFailOverEndpointState $ dhcpStatements $ dhcpComments $ dhcpOption )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.13
+  NAME 'dhcpTSigKey'
+  DESC 'TSIG key for secure dynamic updates'
+  SUP top
+  MUST ( cn $ dhcpKeyAlgorithm $ dhcpKeySecret )
+  MAY ( dhcpComments )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.14
+  NAME 'dhcpDnsZone'
+  DESC 'DNS Zone for updating leases'
+  SUP top
+  MUST ( cn $ dhcpDnsZoneServer )
+  MAY ( dhcpKeyDN $ dhcpComments )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.15
+  NAME 'dhcpFailOverPeer'
+  DESC 'This class defines the Fail over peer'
+  SUP top
+  MUST ( cn $ dhcpFailOverPrimaryServer $ dhcpFailOverSecondaryServer $ dhcpFailoverPrimaryPort $ dhcpFailOverSecondaryPort )
+  MAY ( dhcpFailOverResponseDelay $ dhcpFailOverUnackedUpdates $ dhcpMaxClientLeadTime $ dhcpFailOverSplit $ dhcpHashBucketAssignment $ dhcpFailOverLoadBalanceTime $ dhcpComments )
+  )
+objectClasses: (
+  2.16.840.1.113719.1.203.6.16
+  NAME 'dhcpLocator'
+  DESC 'Locator object for DHCP configuration in the tree. There will be a single dhcpLocator object in the tree with links to all the DHCP objects in the tree'
+  SUP top
+  MUST ( cn )
+  MAY ( dhcpServiceDN $dhcpServerDN $ dhcpSharedNetworkDN $ dhcpSubnetDN $ dhcpPoolDN $ dhcpGroupDN $ dhcpHostDN $ dhcpClassesDN $ dhcpKeyDN $ dhcpZoneDN $ dhcpFailOverPeerDN $ dhcpOption $ dhcpComments )
+  )
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index 68c98e05a9986a4fff1a2070bb9e3c104937b21b..7d9c9288fbc114657824cc6c00990827ad1daa36 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -10,6 +10,7 @@ app_DATA =				\
 	60basev3.ldif			\
 	60ipadns.ldif			\
 	61kerberos-ipav3.ldif		\
+	60dhcpd.ldif			\
 	65ipasudo.ldif			\
 	anonymous-vlv.ldif		\
 	bootstrap-template.ldif		\
@@ -20,6 +21,7 @@ app_DATA =				\
 	replica-acis.ldif		\
 	ds-nfiles.ldif			\
 	dns.ldif			\
+	dhcpd.ldif 				\
 	kerberos.ldif			\
 	indices.ldif			\
 	bind.named.conf.template	\
diff --git a/install/share/dhcpd.ldif b/install/share/dhcpd.ldif
new file mode 100644
index 0000000000000000000000000000000000000000..6995f44dd1495bdc2a8ebf1d2cabe4244856ab6b
--- /dev/null
+++ b/install/share/dhcpd.ldif
@@ -0,0 +1,90 @@
+dn: cn=dhcpHWAddress,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+changetype: add
+objectClass:top
+objectClass:nsIndex
+cn:dhcpHWAddress
+nsSystemIndex:false
+nsIndexType:eq
+
+dn: cn=dhcpClassData,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+changetype: add
+objectClass:top
+objectClass:nsIndex
+cn:dhcpClassData
+nsSystemIndex:false
+nsIndexType:eq
+
+dn: $SUFFIX
+changetype: modify
+add: aci
+#aci: (target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "permission:add dns entries";allow (add) groupdn = "ldap:///cn=add dns entries,cn=permissions,cn=pbac,$SUFFIX";)
+#aci: (target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "permission:remove dns entries";allow (delete) groupdn = "ldap:///cn=remove dns entries,cn=permissions,cn=pbac,$SUFFIX";)
+#aci: (targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "permission:update dns entries";allow (write) groupdn = "ldap:///cn=update dns entries,cn=permissions,cn=pbac,$SUFFIX";)
+#aci: (targetattr = "idnsforwardpolicy || idnsforwarders || idnsallowsyncptr || idnszonerefresh || idnspersistentsearch")(target = "ldap:///cn=dns,$SUFFIX")(version 3.0;acl "permission:Write DNS Configuration";allow (write) groupdn = "ldap:///cn=Write DNS Configuration,cn=permissions,cn=pbac,$SUFFIX";)
+
+dn: cn=DHCP Administrators,cn=privileges,cn=pbac,$SUFFIX
+changeType: add
+objectClass: groupofnames
+objectClass: nestedgroup
+objectClass: top
+cn: DHCP Administrators
+
+dn: cn=DHCP Servers,cn=privileges,cn=pbac,$SUFFIX
+changeType: add
+objectClass: groupofnames
+objectClass: nestedgroup
+objectClass: top
+cn: DHCP Servers
+
+dn: cn=Read DHCP configuration,cn=permissions,cn=pbac,$SUFFIX
+changeType: add
+objectClass: groupofnames
+objectClass: nestedgroup
+objectClass: top
+cn: Read DHCP configuration
+member: cn=DHCP Servers,cn=privileges,cn=pbac,$SUFFIX
+member: cn=DHCP Administrators,cn=privileges,cn=pbac,$SUFFIX
+
+dn: cn=Read DHCP leases,cn=permissions,cn=pbac,$SUFFIX
+changeType: add
+objectClass: groupofnames
+objectClass: nestedgroup
+objectClass: top
+cn: Read DHCP leases
+member: cn=DHCP Servers,cn=privileges,cn=pbac,$SUFFIX
+member: cn=DHCP Administrators,cn=privileges,cn=pbac,$SUFFIX
+
+dn: cn=Write DHCP configuration,cn=permissions,cn=pbac,$SUFFIX
+changeType: add
+objectClass: groupofnames
+objectClass: nestedgroup
+objectClass: top
+cn: Write DHCP configuration
+member: cn=DHCP Administrators,cn=privileges,cn=pbac,$SUFFIX
+
+dn: cn=Write DHCP leases,cn=permissions,cn=pbac,$SUFFIX
+changeType: add
+objectClass: groupofnames
+objectClass: nestedgroup
+objectClass: top
+cn: Write DHCP leases
+member: cn=DHCP Servers,cn=privileges,cn=pbac,$SUFFIX
+
+dn: cn=dhcp,dc=dev,$SUFFIX
+changeType: add
+objectclass: nsContainer
+objectclass: top
+cn: dhcp
+
+dn: cn=v4servers,cn=dhcp,$SUFFIX
+changeType: add
+objectclass: nsContainer
+objectclass: top
+cn: v4
+
+dn: cn=v6servers,cn=dhcp,$SUFFIX
+changeType: add
+objectclass: nsContainer
+objectclass: top
+cn: v6
+
diff --git a/install/tools/Makefile.am b/install/tools/Makefile.am
index 7f1504cd59f7959d25ee291bbe7bc4d461f22c8c..e9aae9915cfaaa6b009343715a08a5f21991603f 100644
--- a/install/tools/Makefile.am
+++ b/install/tools/Makefile.am
@@ -7,6 +7,7 @@ SUBDIRS = 			\
 sbin_SCRIPTS =			\
 	ipa-ca-install		\
 	ipa-dns-install		\
+	ipa-dhcp-install	\
 	ipa-server-install	\
 	ipa-adtrust-install	\
 	ipa-replica-conncheck	\
diff --git a/install/tools/ipa-dhcp-install b/install/tools/ipa-dhcp-install
new file mode 100644
index 0000000000000000000000000000000000000000..0a2ffcaba6eb3349b2efdb20b5d370d5b73141d8
--- /dev/null
+++ b/install/tools/ipa-dhcp-install
@@ -0,0 +1,24 @@
+#! /usr/bin/python -E
+# Authors: William Brown <william at firstyear.id.au>
+# Based on ipa-server-install by Karl MacMillan <kmacmillan at mentalrootkit.com>
+#
+# Copyright (C) 2007 - 2009  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+#Setup options parsing.
+
+#Pass the options to our DHCP instance setup tool.
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 8f87a18eef80e9824203aedf50e29e9819ae7c18..8c63bf796b0ea47f78a53aefcdea7448000e3355 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -104,6 +104,7 @@ DEFAULT_CONFIG = (
     ('container_cifsdomains', 'cn=ad,cn=etc'),
     ('container_trusts', 'cn=trusts'),
     ('container_adtrusts', 'cn=ad,cn=trusts'),
+    ('container_dhcp', 'cn=dhcp'),
  
     # Ports, hosts, and URIs:
     # FIXME: let's renamed xmlrpc_uri to rpc_xml_uri
diff --git a/ipalib/plugins/dhcp.py b/ipalib/plugins/dhcp.py
new file mode 100644
index 0000000000000000000000000000000000000000..8999624b3b91a391e9706568e4bfb21e91335a2d
--- /dev/null
+++ b/ipalib/plugins/dhcp.py
@@ -0,0 +1,601 @@
+# Authors: William Brown <william at firstyear.id.au>
+#
+# Copyright (C) 2007  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+from ipalib.plugins.baseldap import *
+from ipalib import _, api, errors
+
+__doc__ = _("""
+""")
+
+
+
+class dhcpserver(LDAPObject):
+    container_dn = api.env.container_dhcp
+    object_name = _('Dhcp Server')
+    object_name_plural = _('Dhcp Servers')
+    object_class = ['dhcpServer', 'top']
+    default_attributes = ['cn']
+    #uuid_attribute
+    #rdn_attribute
+    #attributer_members
+    label = _('Dhcp Servers')
+    label_singular = _('Dhcp Server')
+    takes_params = (
+        Str('cn',
+            cli_name='dhcp_server_name',
+            label=_('Dhcp Server name'),
+            primary_key=True,
+        ),
+        Str('dhcpservicedn',
+            cli_name='dhcp_server_service_dn',
+            label=_('Dhcp Server Service DN'),
+            primary_key=False,
+        ),
+        Str('dhcplocatordn',
+            cli_name='dhcp_server_locator_dn',
+            label=_('Dhcp Server Locator DN'),
+            primary_key=False,
+        ),
+        Str('dhcpversion',
+            cli_name='dhcp_server_version',
+            label=_('Dhcp Server Version'),
+            primary_key=False,
+        ),
+        Str('dhcpimplementation',
+            cli_name='dhcp_server_implementation',
+            label=_('Dhcp Server implementation'),
+            primary_key=False,
+        ),
+        Str('dhcphashbucketassignment',
+            cli_name='dhcp_server_hash_bucket_assignment',
+            label=_('Dhcp Server Hash bucket assignment'),
+            primary_key=False,
+        ),
+        Str('dhcpdelayedserviceparameter',
+            cli_name='dhcp_server_delayed_service_parameter',
+            label=_('Dhcp Server Delayed Service Parameter'),
+            primary_key=False,
+        ),
+        Str('dhcpmaxclientleadtime',
+            cli_name='dhcp_server_max_client_lead_time',
+            label=_('Dhcp Server Max Client Lead Time'),
+            primary_key=False,
+        ),
+        Str('dhcpfailoverendpointstate',
+            cli_name='dhcp_server_fail_over_endpoint_state',
+            label=_('Dhcp Server Fail Over Endpoint State'),
+            primary_key=False,
+        ),
+        Str('dhcpstatements',
+            cli_name='dhcp_server_statements',
+            label=_('Dhcp Server Statements'),
+            primary_key=False,
+        ),
+        Str('dhcpcomments',
+            cli_name='dhcp_server_comments',
+            label=_('Dhcp Server Comments'),
+            primary_key=False,
+        ),
+        Str('dhcpoption',
+            cli_name='dhcp_server_option',
+            label=_('Dhcp Server Option'),
+            primary_key=False,
+        ),
+
+    )
+
+api.register(dhcpserver)
+    
+class dhcpservice(LDAPObject):
+    container_dn = api.env.container_dhcp
+    object_name = _('Dhcp Service')
+    object_name_plural = _('Dhcp Servicess')
+    object_class = ['dhcpService', 'top']
+    default_attributes = ['cn']
+    #uuid_attribute
+    #rdn_attribute
+    #attributer_members
+    label = _('Dhcp Services')
+    label_singular = _('Dhcp Service')
+    takes_params = (
+        Str('cn',
+            cli_name='dhcp_service_name',
+            label=_('Dhcp Service Name'),
+            primary_key=True,
+        ),
+        Str('dhcpprimarydn',
+            cli_name='dhcp_service_primary_dn',
+            label=_('Dhcp Service Primary DN'),
+            primary_key=False,
+        ),
+        Str('dhcpsecondarydn',
+            cli_name='dhcp_service_secondary_dn',
+            label=_('Dhcp Service Secondary DN'),
+            primary_key=False,
+        ),
+        Str('dhcpserverdn',
+            cli_name='dhcp_service_server_dn',
+            label=_('Dhcp Service Server DN'),
+            primary_key=False,
+        ),
+        Str('dhcpsharednetworkdn',
+            cli_name='dhcp_service_shared_network_dn',
+            label=_('Dhcp Service Shared Network DN'),
+            primary_key=False,
+        ),
+        Str('dhcpsubnetdn',
+            cli_name='dhcp_service_subnet_dn',
+            label=_('Dhcp Service Subnet DN'),
+            primary_key=False,
+        ),
+        Str('dhcpgroupdn',
+            cli_name='dhcp_service_group_dn',
+            label=_('Dhcp Service Group DN'),
+            primary_key=False,
+        ),
+        Str('dhcphostdn',
+            cli_name='dhcp_service_host_dn',
+            label=_('Dhcp Service Host DN'),
+            primary_key=False,
+        ),
+        Str('dhcpclassesdn',
+            cli_name='dhcp_service_classes_dn',
+            label=_('Dhcp Service Classes DN'),
+            primary_key=False,
+        ),
+        Str('dhcpoptionsdn',
+            cli_name='dhcp_service_options_dn',
+            label=_('Dhcp Service Options DN'),
+            primary_key=False,
+        ),
+        Str('dhcpzonedn',
+            cli_name='dhcp_service_zone_dn',
+            label=_('Dhcp Service Zone DN'),
+            primary_key=False,
+        ),
+        Str('dhcpkeydn',
+            cli_name='dhcp_service_key_dn',
+            label=_('Dhcp Service Key DN'),
+            primary_key=False,
+        ),
+        Str('dhcpfailoverpeerdn',
+            cli_name='dhcp_service_fail_over_peer_dn',
+            label=_('Dhcp Service Fail Over Peer DN'),
+            primary_key=False,
+        ),
+        Str('dhcpstatements',
+            cli_name='dhcp_service_statements',
+            label=_('DHcp Service Statements'),
+            primary_key=False,
+        ),
+        Str('dhcpcomments',
+            cli_name='dhcp_service_comments',
+            label=_('Dhcp Service Comments'),
+            primary_key=False,
+        ),
+        Str('dhcpoption',
+            cli_name='dhcp_service_option',
+            label=_('Dhcp Service Option'),
+            primary_key=False,
+        ),
+
+    )
+
+api.register(dhcpservice)
+
+class dhcpfailoverpeer(LDAPObject):
+    container_dn = api.env.container_dhcp
+    object_name = _('Dhcp Fail Over Peer')
+    object_name_plural = _('Dhcp Fail Over Peers')
+    object_class = ['dhcpServer', 'top']
+    default_attributes = ['cn', 
+                        'dhcpFailOverPrimaryServer', 
+                        'dhcpFailOverSecondaryServer',
+                        'dhcpFailOverPrimaryPort',
+                        'dhcpFailOvreSecondaryPort',]
+    #uuid_attribute
+    #rdn_attribute
+    #attributer_members
+    label = _('Dhcp Fail Over Peers')
+    label_singular = _('Dhcp Fail Over Peer')
+    takes_params = (
+        Str('cn',
+            cli_name='dhcp_fail_over_peer_name',
+            label=_('Dhcp Fail Over Peer Name'),
+            primary_key=True,
+        ),
+        Str('dhcpfailoverprimaryserver',
+            cli_name='dhcp_fail_over_primary_server',
+            label=_('Dhcp Fail Over Primary Server'),
+            primary_key=False,
+        ),
+        Str('dhcpfailoversecondaryserver',
+            cli_name='dhcp_fail_over_secondary_server',
+            label=_('Dhcp Fail Over Secondary Server'),
+            primary_key=False,
+        ),
+        Str('dhcpfailoverprimaryport',
+            cli_name='dhcp_fail_over_primary_port',
+            label=_('Dhcp Fail Over Primary Port'),
+            primary_key=False,
+        ),
+        Str('dhcpfailoversecondaryport',
+            cli_name='dhcp_fail_over_secondary_port',
+            label=_('Dhcp Fail Over Secondary Port'),
+            primary_key=False,
+        ),
+        Str('dhcpfailoverresponsedelay',
+            cli_name='dhcp_fail_over_response_delay',
+            label=_('Dhcp Fail Over Response Delay'),
+            primary_key=False,
+        ),
+        Str('dhcpfailoverunackedupdates',
+            cli_name='dhcp_fail_over_unacked_updates',
+            label=_('Dhcp Fail Over Unacked Updates'),
+            primary_key=False,
+        ),
+        Str('dhcpmaxclientleadtime',
+            cli_name='dhcp_fail_over_max_client_lead_time',
+            label=_('Dhcp Fail Over Max Client Lead Time'),
+            primary_key=False,
+        ),
+        Str('dhcpfailoversplit',
+            cli_name='dhcp_fail_over_split',
+            label=_('Dhcp Fail Over Split'),
+            primary_key=False,
+        ),
+        Str('dhcphashbucketassignment',
+            cli_name='dhcp_fail_over_hash_bucket_assignment',
+            label=_('Dhcp Fail Over Hash Bucket Assignment'),
+            primary_key=False,
+        ),
+        Str('dhcpfailoverloadbalancetime',
+            cli_name='dhcp_fail_over_load_balance_time',
+            label=_('Dhcp Fail Over Load Balance Time'),
+            primary_key=False,
+        ),
+        Str('dhcpcomments',
+            cli_name='dhcp_fail_over_comments',
+            label=_('Dhcp Fail Over Comments'),
+            primary_key=False,
+        ),
+
+    )
+
+api.register(dhcpfailoverpeer)
+
+class dhcpsharednetwork(LDAPObject):
+    container_dn = api.env.container_dhcp
+    object_name = _('Dhcp Shared Network')
+    object_name_plural = _('Dhcp Shared Networks')
+    object_class = ['dhcpServer', 'top']
+    default_attributes = ['cn']
+    #uuid_attribute
+    #rdn_attribute
+    #attributer_members
+    label = _('Dhcp Shared Networks')
+    label_singular = _('Dhcp Shared Network')
+    takes_params = (
+        Str('cn',
+            cli_name='dhcp_shared_network_name',
+            label=_('Dhcp Shared Network Name'),
+            primary_key=True,
+        ),
+        Str('dhcpsubnetdn',
+            cli_name='dhcp_shared_network_subnet_dn',
+            label=_('Dhcp Shared Network Subnet DN'),
+            primary_key=False,
+        ),
+        Str('dhcppooldn',
+            cli_name='dhcp_shared_network_pool_dn',
+            label=_('Dhcp Shared Network Pool DN'),
+            primary_key=False,
+        ),
+        Str('dhcpoptionsdn',
+            cli_name='dhcp_shared_network_options_dn',
+            label=_('Dhcp Shared Network Options DN'),
+            primary_key=False,
+        ),
+        Str('dhcpzonedn',
+            cli_name='dhcp_shared_network_zone_dn',
+            label=_('Dhcp Shared Network Zone DN'),
+            primary_key=False,
+        ),
+        Str('dhcpstatements',
+            cli_name='dhcp_shared_network_statements',
+            label=_('Dhcp Shared Network Statements'),
+            primary_key=False,
+        ),
+        Str('dhcpcomments',
+            cli_name='dhcp_shared_network_comments',
+            label=_('Dhcp Shared Network Comments'),
+            primary_key=False,
+        ),
+        Str('dhcpoption',
+            cli_name='dhcp_shared_network_option',
+            label=_('Dhcp Shared Network Option'),
+            primary_key=False,
+        ),
+
+    )
+
+api.register(dhcpsharednetwork)
+
+class dhcpsubnet(LDAPObject):
+    container_dn = api.env.container_dhcp
+    object_name = _('Dhcp Subnet')
+    object_name_plural = _('Dhcp Subnets')
+    object_class = ['dhcpSubnet', 'dhcpOptions', 'top']
+    default_attributes = ['cn', 'dhcpNetMask']
+    #uuid_attribute
+    #rdn_attribute
+    #attributer_members
+    label = _('Dhcp Subnets')
+    label_singular = _('Dhcp Subnet')
+    takes_params = (
+        Str('cn',
+            cli_name='dhcp_subnet_name',
+            label=_('Dhcp Subnet Name'),
+            primary_key=True,
+        ),
+        Str('dhcpnetmask',
+            cli_name='dhcp_subnet_netmask',
+            label=_('Dhcp Subnet Netmask'),
+            primary_key=False,
+        ),
+        Str('dhcprange',
+            cli_name='dhcp_subnet_range',
+            label=_('Dhcp Subnet Range'),
+            primary_key=False,
+        ),
+        Str('dhcppooldn',
+            cli_name='dhcp_subnet_pool_dn',
+            label=_('Dhcp Subnet Pool DN'),
+            primary_key=False,
+        ),
+        Str('dhcpgroupdn',
+            cli_name='dhcp_subnet_group_dn',
+            label=_('Dhcp Subnet Group DN'),
+            primary_key=False,
+        ),
+        Str('dhcphostdn',
+            cli_name='dhcp_subnet_host_dn',
+            label=_('Dhcp Subnet Host DN'),
+            primary_key=False,
+        ),
+        Str('dhcpclassesdn',
+            cli_name='dhcp_subnet_classes_dn',
+            label=_('Dhcp Subnet Classes DN'),
+            primary_key=False,
+        ),
+        Str('dhcpleasesdn',
+            cli_name='dhcp_subnet_leases_dn',
+            label=_('Dhcp Subnet Leases DN'),
+            primary_key=False,
+        ),
+        Str('dhcpoptionsdn',
+            cli_name='dhcp_subnet_options_dn',
+            label=_('Dhcp Subnet Options DN'),
+            primary_key=False,
+        ),
+        Str('dhcpzonedn',
+            cli_name='dhcp_subnet_zone_dn',
+            label=_('Dhcp Subnet Zone DN'),
+            primary_key=False,
+        ),
+        Str('dhcpkeydn',
+            cli_name='dhcp_subnet_key_dn',
+            label=_('Dhcp Subnet Key DN'),
+            primary_key=False,
+        ),
+        Str('dhcpfailoverpeerdn',
+            cli_name='dhcp_subnet_fail_over_peer_dn',
+            label=_('Dhcp Subnet Fail Over Peer DN'),
+            primary_key=False,
+        ),
+        Str('dhcpstatements',
+            cli_name='dhcp_subnet_statements',
+            label=_('Dhcp Subnet Statements'),
+            primary_key=False,
+        ),
+        Str('dhcpcomments',
+            cli_name='dhcp_subnet_comments',
+            label=_('Dhcp Subnet Comments'),
+            primary_key=False,
+        ),
+        Str('dhcpoption',
+            cli_name='dhcp_subnet_option',
+            label=_('Dhcp Subnet Option'),
+            primary_key=False,
+        ),
+
+    )
+
+api.register(dhcpsubnet)
+
+class dhcppool(LDAPObject):
+    container_dn = api.env.container_dhcp
+    object_name = _('Dhcp Pool')
+    object_name_plural = _('Dhcp Pools')
+    object_class = ['dhcpPool', 'top']
+    default_attributes = ['cn', 'dhcpRange']
+    #uuid_attribute
+    #rdn_attribute
+    #attributer_members
+    label = _('Dhcp Pools')
+    label_singular = _('Dhcp Pool')
+    takes_params = (
+        Str('cn',
+            cli_name='dhcp_pool_name',
+            label=_('Dhcp Pool Name'),
+            primary_key=True,
+        ),
+        Str('dhcprange',
+            cli_name='dhcp_pool_range',
+            label=_('Dhcp Pool Range'),
+            primary_key=False,
+        ),
+        Str('dhcpclassesdn',
+            cli_name='dhcp_pool_classes_dn',
+            label=_('Dhcp Pool Classes DN'),
+            primary_key=False,
+        ),
+        Str('dhcppermitlist',
+            cli_name='dhcp_pool_permit_list',
+            label=_('Dhcp Pool Permit List'),
+            primary_key=False,
+        ),
+        Str('dhcpleasesdn',
+            cli_name='dhcp_pool_leases_dn',
+            label=_('Dhcp Pool Leases DN'),
+            primary_key=False,
+        ),
+        Str('dhcpoptionsdn',
+            cli_name='dhcp_pool_options_dn',
+            label=_('Dhcp Pool Options DN'),
+            primary_key=False,
+        ),
+        Str('dhcpzonedn',
+            cli_name='dhcp_pool_zone_dn',
+            label=_('Dhcp Pool Zone DN'),
+            primary_key=False,
+        ),
+        Str('dhcpkeydn',
+            cli_name='dhcp_pool_key_dn',
+            label=_('Dhcp Pool Key DN'),
+            primary_key=False,
+        ),
+        Str('dhcpstatements',
+            cli_name='dhcp_pool_statements',
+            label=_('Dhcp Pool Statements'),
+            primary_key=False,
+        ),
+        Str('dhcpcomments',
+            cli_name='dhcp_pool_comments',
+            label=_('Dhcp Pool Comments'),
+            primary_key=False,
+        ),
+        Str('dhcpoption',
+            cli_name='dhcp_pool_option',
+            label=_('Dhcp Pool Option'),
+            primary_key=False,
+        ),
+
+    )
+
+api.register(dhcppool)
+
+class dhcpgroup(LDAPObject):
+    container_dn = api.env.container_dhcp
+    object_name = _('Dhcp Group')
+    object_name_plural = _('Dhcp Groups')
+    object_class = ['dhcpGroup', 'top']
+    default_attributes = ['cn']
+    #uuid_attribute
+    #rdn_attribute
+    #attributer_members
+    label = _('Dhcp Groups')
+    label_singular = _('Dhcp Group')
+    takes_params = (
+        Str('cn',
+            cli_name='dhcp_group_name',
+            label=_('Dhcp Group Name'),
+            primary_key=True,
+        ),
+        Str('dhcphostdn',
+            cli_name='dhcp_group_host_dn',
+            label=_('Dhcp Group Host DN'),
+            primary_key=False,
+        ),
+        Str('dhcpoptionsdn',
+            cli_name='dhcp_group_options_dn',
+            label=_('Dhcp Group Options DN'),
+            primary_key=False,
+        ),
+        Str('dhcpstatements',
+            cli_name='dhcp_group_statements',
+            label=_('Dhcp Group Statements'),
+            primary_key=False,
+        ),
+        Str('dhcpcomments',
+            cli_name='dhcp_group_comments',
+            label=_('Dhcp Group Comments'),
+            primary_key=False,
+        ),
+        Str('dhcpoption',
+            cli_name='dhcp_group_option',
+            label=_('Dhcp Group Option'),
+            primary_key=False,
+        ),
+
+    )
+
+api.register(dhcpgroup)
+    
+class dhcphost(LDAPObject):
+    container_dn = api.env.container_dhcp
+    object_name = _('Dhcp Host')
+    object_name_plural = _('Dhcp Hosts')
+    object_class = ['dhcpHost', 'top']
+    default_attributes = ['cn']
+    #uuid_attribute
+    #rdn_attribute
+    #attributer_members
+    label = _('Dhcp Hosts')
+    label_singular = _('Dhcp Host')
+    takes_params = (
+        Str('cn',
+            cli_name='dhcp_host_name',
+            label=_('Dhcp Host Name'),
+            primary_key=True,
+        ),
+        Str('dhcpleasedn',
+            cli_name='dhcp_host_lease_dn',
+            label=_('Dhcp Host Lease DN'),
+            primary_key=False,
+        ),
+        Str('dhcphwaddress',
+            cli_name='dhcp_host_hwaddress',
+            label=_('Dhcp Host HWAddress'),
+            primary_key=False,
+        ),
+        Str('dhcpoptionsdn',
+            cli_name='dhcp_host_options_dn',
+            label=_('Dhcp Host Options DN'),
+            primary_key=False,
+        ),
+        Str('dhcpstatements',
+            cli_name='dhcp_host_statements',
+            label=_('Dhcp Host Statements'),
+            primary_key=False,
+        ),
+        Str('dhcpcomments',
+            cli_name='dhcp_host_comments',
+            label=_('Dhcp Host Comments'),
+            primary_key=False,
+        ),
+        Str('dhcpoption',
+            cli_name='dhcp_host_option',
+            label=_('Dhcp Host Option'),
+            primary_key=False,
+        ),
+
+    )
+
+api.register(dhcphost)
diff --git a/ipaserver/install/Makefile.am b/ipaserver/install/Makefile.am
index 9fcad4e77c93cf44ed5fcf3ff793233ba35482c1..08829e2ed9622c9e1b8601c1d657fe324bb328d2 100644
--- a/ipaserver/install/Makefile.am
+++ b/ipaserver/install/Makefile.am
@@ -5,6 +5,7 @@ app_PYTHON = 			\
 	__init__.py		\
 	bindinstance.py		\
 	cainstance.py		\
+	dhcpinstance.py		\
 	dsinstance.py		\
 	ipaldap.py		\
 	krbinstance.py		\
diff --git a/ipaserver/install/dhcpinstance.py b/ipaserver/install/dhcpinstance.py
new file mode 100644
index 0000000000000000000000000000000000000000..4c3255cc8efd4a9fbd7a1437d7ebb0c1c83e5003
--- /dev/null
+++ b/ipaserver/install/dhcpinstance.py
@@ -0,0 +1,134 @@
+# Authors: William Brown <william at firstyear.id.au>
+#
+# Copyright (C) 2007  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import installutils
+import ldap
+import service
+
+import ipalib
+from ipalib import api, util, errors
+from ipapython import sysrestore
+
+def _ldap_object_exists(conn, dn):
+    try:
+        conn.search_ext_s(dn, ldap.SCOPE_BASE)
+    except ldap.NO_SUCH_OBJECT:
+        return False
+    else:
+        return True
+
+class DhcpInstance(service.Service):
+    def __init__(self, fstore=None, dm_password=None):
+        service.Service.__init__(self, "dhcpd", dm_password=dm_password)
+        if fstore:
+            self.fstore = fstore
+        else:
+            self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
+
+    def setup(self, fqdn, ipaddress, v4=False, v6=False, location="Default"):
+        self.fqdn = fqdn
+        self.ipaddress = ipaddress
+        self.location = location
+        self.v4 = v4
+        self.v6 = v6
+
+    def create_instance(self):
+        try:
+            self.stop()
+        except:
+            pass
+        
+        #self.ldap_connect()
+        #Check if we already have the DHCP container setup. If not, install it.
+        # This is also a check of the permissions of the use we are running as.
+        if not self._check_dhcp_container():
+            self.step("Creating base DHCP objects", self.__setup_dhcp_ldap)
+        elif self._check_dhcp_preinstalled():
+            #We need to throw an error here.
+            pass
+        # Create the specified location, or create "default" location. Check that there are not 2 servers already in this location with the type of instance we want.
+        if not self._check_dhcp_location():
+            self.step("Creating location %s" % self.location, self.__create_location)
+        #
+        # Now, we check if -v4 was specified. If yes, we install a dhcpv4 server instance on this server.
+        # If -v6 was specificed, we install a dhcp6 instance into this location. 
+        #
+        # If this machine does not yet have a generic account for accessing the DHCP as a server, we need to add it, and add the permission to this account for DHCP server read, and leases write.
+        # 
+        if self.v4:
+            self.step("Creating dhcp instance", self.__create_v4_instance)
+        if self.v6:
+            self.step("Creating dhcp6 instance", self.__create_v6_instance)
+        if self.v4:
+            self.step("Starting dhcp", self.__start_dhcp)
+            self.step("Registering dhcp to start at boot", self.__enable_dhcp)
+        if self.v6:
+            self.step("Starting dhcp6", self.__start_dhcp6)
+            self.step("Resgistering dhcp6 to start at boot", self.__enable_dhcp6)
+        # Post install we need to warn the user about opening certain firewall ports.
+        # If v4, we need port 68 for outbound / inbound for DHCP
+        # If v6, we need port 546 (I think) For ipv6 on a specific fe80::/16 subnet.
+        self.start_creation("Configuring dhcp:")
+
+    def uninstall(self):
+        pass
+
+    def __create_location(self):
+        #This should be calling the ipa.api.command.dhcp_addlocation
+        #This addition of a location adds the v4 and v6 branches 
+        pass
+
+    def __create_v4_instance(self):
+        #This should add the server to the ldap, in the cn=v4,cn=dhcp, with the correct DHCPServer objects.
+        #This should then create the relevant files on disk for this server.
+        pass
+
+    def __create_v6_instance(self):
+        #This should add the server to the ldap in the cn=v6,cn=dhcp container, with the correct DHCP server objects.
+        #This should create the relevant files on disk for this server.
+        pass
+
+    def __start_dhcp(self):
+        pass
+
+    def __start_dhcp6(self):
+        pass
+
+    def __enable_dhcp(self):
+        pass
+
+    def __enable_dhcp6(self):
+        pass
+
+    def _check_dhcp_container(self):
+        #Check that our dhcp container exists cn=dhcp,dc=foo,dc=bar
+        pass
+
+    def _check_dhcp_location(self):
+        #Check the location exists. 
+        #Check that there are not more than 2 servers already in this location. This will need to be done by checking their configuration dns
+        pass
+
+    def _check_dhcp_preinstalled(self):
+        pass
+
+    def __setup_dhcp_ldap(self):
+        #sub_dict is list of WORDS in the ldif to replace.
+        #self._ldap_mod("dhcpd.ldif", self.sub_dict
+        pass
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index fb620a82e0d432d50e6c40ab8a7053ced153965a..e5c2305daa7d5e0fd99e6a33b9beb1d436c972e6 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -389,6 +389,7 @@ class DsInstance(service.Service):
                              "60basev2.ldif",
                              "60basev3.ldif",
                              "60ipadns.ldif",
+                             "60dhcpd.ldif",
                              "61kerberos-ipav3.ldif",
                              "65ipasudo.ldif"):
             target_fname = schema_dirname(self.serverid) + schema_fname
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index a3d09fcd633a851a67ef94b2025f1afb605d3d84..c21598b020639e6cd2c541ab7ff6986d6e825355 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -39,6 +39,8 @@ SERVICE_LIST = {
     'KDC':('krb5kdc', 10),
     'KPASSWD':('kadmin', 20),
     'DNS':('named', 30),
+    'DHCP':('dhcpd', 33),
+    'DHCP6':('dhcpd6', 36),
     'MEMCACHE':('ipa_memcached', 39),
     'HTTP':('httpd', 40),
     'CA':('pki-cad', 50),
-- 
1.7.10.2

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 945 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20120627/f80ef4cb/attachment.sig>


More information about the Freeipa-devel mailing list