macaddress is a multi-valued attribute and we allow multiple entries. This is from the objectclass ieee802device. This is added manually when doing a mod or add and not as a default to support existing host entries that do not have this objectclass. If this were added to the defaults then existing hosts missing this objectclass would not be found by host-find.

It is possible to get ethers data out of nss by configuring nsswitch.conf to use ldap for ethers and running getent ethers <hostname>

I tested nslcd and it only returned one macaddress value. I don't know if this is a deficiency in nslcd or expected behavior.

https://fedorahosted.org/freeipa/ticket/1132

rob
>From 029414cf5787c0def05ecae8430ec4763908780a Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcrit...@redhat.com>
Date: Fri, 20 Jan 2012 15:10:44 -0500
Subject: [PATCH] Add support for storing MAC address in host entries.

macaddress is a multi-valued attribute and we allow multiple entries.
This is from the objectclass ieee802device. This is added manually when
doing a mod or add and not as a default to support existing host entries
that do not have this objectclass. If this were added to the defaults
then existing hosts missing this objectclass would not be found by
host-find.

It is possible to get ethers data out of nss by configuring nsswitch.conf
to use ldap for ethers and running getent ethers <hostname>

I tested nslcd and it only returned one macaddress value.

https://fedorahosted.org/freeipa/ticket/1132
---
 API.txt                               |    9 +++--
 VERSION                               |    2 +-
 ipalib/plugins/host.py                |   20 ++++++++++-
 tests/test_xmlrpc/objectclasses.py    |    1 +
 tests/test_xmlrpc/test_host_plugin.py |   65 +++++++++++++++++++++++++++++++++
 5 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/API.txt b/API.txt
index c260753ec69d726ea0d16cd51ffa72e750ba961b..7ff0183055b81aee99831d34983bdc395b672acb 100644
--- a/API.txt
+++ b/API.txt
@@ -1654,7 +1654,7 @@ output: Output('notmatched', (<type 'list'>, <type 'tuple'>, <type 'NoneType'>),
 output: Output('error', (<type 'list'>, <type 'tuple'>, <type 'NoneType'>), None)
 output: Output('value', <type 'bool'>, None)
 command: host_add
-args: 1,14,3
+args: 1,15,3
 arg: Str('fqdn', attribute=True, cli_name='hostname', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9][a-zA-Z0-9-\\.]{0,254}$', pattern_errmsg='may only include letters, numbers, and -', primary_key=True, required=True)
 option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=False)
 option: Str('l', attribute=True, cli_name='locality', multivalue=False, required=False)
@@ -1664,6 +1664,7 @@ option: Str('nsosversion', attribute=True, cli_name='os', multivalue=False, requ
 option: Str('userpassword', attribute=True, cli_name='password', multivalue=False, required=False)
 option: Flag('random', attribute=False, autofill=True, cli_name='random', default=False, multivalue=False, required=False)
 option: Bytes('usercertificate', attribute=True, cli_name='certificate', multivalue=False, required=False)
+option: Str('macaddress', attribute=True, cli_name='macaddress', multivalue=True, pattern='^([a-fA-F0-9]{2}[:|\\-]?){5}[a-fA-F0-9]{2}$', pattern_errmsg='Must be of the form HH:HH:HH:HH:HH:HH, where each H is a hexadecimal character.', required=False)
 option: Flag('force', autofill=True, default=False)
 option: Flag('no_reverse', autofill=True, default=False)
 option: Str('ip_address?')
@@ -1697,7 +1698,7 @@ output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('result', <type 'bool'>, None)
 output: Output('value', <type 'unicode'>, None)
 command: host_find
-args: 1,28,4
+args: 1,29,4
 arg: Str('criteria?', noextrawhitespace=False)
 option: Str('fqdn', attribute=True, autofill=False, cli_name='hostname', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9][a-zA-Z0-9-\\.]{0,254}$', pattern_errmsg='may only include letters, numbers, and -', primary_key=True, query=True, required=False)
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False)
@@ -1707,6 +1708,7 @@ option: Str('nshardwareplatform', attribute=True, autofill=False, cli_name='plat
 option: Str('nsosversion', attribute=True, autofill=False, cli_name='os', multivalue=False, query=True, required=False)
 option: Str('userpassword', attribute=True, autofill=False, cli_name='password', multivalue=False, query=True, required=False)
 option: Bytes('usercertificate', attribute=True, autofill=False, cli_name='certificate', multivalue=False, query=True, required=False)
+option: Str('macaddress', attribute=True, autofill=False, cli_name='macaddress', multivalue=True, pattern='^([a-fA-F0-9]{2}[:|\\-]?){5}[a-fA-F0-9]{2}$', pattern_errmsg='Must be of the form HH:HH:HH:HH:HH:HH, where each H is a hexadecimal character.', query=True, required=False)
 option: Int('timelimit?', autofill=False, minvalue=0)
 option: Int('sizelimit?', autofill=False, minvalue=0)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
@@ -1732,7 +1734,7 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
 output: Output('count', <type 'int'>, None)
 output: Output('truncated', <type 'bool'>, None)
 command: host_mod
-args: 1,16,3
+args: 1,17,3
 arg: Str('fqdn', attribute=True, cli_name='hostname', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9][a-zA-Z0-9-\\.]{0,254}$', pattern_errmsg='may only include letters, numbers, and -', primary_key=True, query=True, required=True)
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False)
 option: Str('l', attribute=True, autofill=False, cli_name='locality', multivalue=False, required=False)
@@ -1742,6 +1744,7 @@ option: Str('nsosversion', attribute=True, autofill=False, cli_name='os', multiv
 option: Str('userpassword', attribute=True, autofill=False, cli_name='password', multivalue=False, required=False)
 option: Flag('random', attribute=False, autofill=True, cli_name='random', default=False, multivalue=False, required=False)
 option: Bytes('usercertificate', attribute=True, autofill=False, cli_name='certificate', multivalue=False, required=False)
+option: Str('macaddress', attribute=True, autofill=False, cli_name='macaddress', multivalue=True, pattern='^([a-fA-F0-9]{2}[:|\\-]?){5}[a-fA-F0-9]{2}$', pattern_errmsg='Must be of the form HH:HH:HH:HH:HH:HH, where each H is a hexadecimal character.', required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
 option: Str('delattr*', cli_name='delattr', exclude='webui')
diff --git a/VERSION b/VERSION
index 1f973908c75f0986b4e2858e1c07e5facac94c33..3f6a25f5999c3fce4bfa8981c708aeaf9db7a49e 100644
--- a/VERSION
+++ b/VERSION
@@ -79,4 +79,4 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=22
+IPA_API_VERSION_MINOR=23
diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py
index 33d60ad1c421e5bdd79a61518c3a809d30f6cae1..0ac08ca166d2fde2b628dfe1c92d42fc5ffba792 100644
--- a/ipalib/plugins/host.py
+++ b/ipalib/plugins/host.py
@@ -224,7 +224,7 @@ class host(LDAPObject):
     default_attributes = [
         'fqdn', 'description', 'l', 'nshostlocation', 'krbprincipalname',
         'nshardwareplatform', 'nsosversion', 'usercertificate', 'memberof',
-        'managedby', 'memberindirect', 'memberofindirect',
+        'managedby', 'memberindirect', 'memberofindirect', 'macaddress',
     ]
     uuid_attribute = 'ipauniqueid'
     attribute_members = {
@@ -306,6 +306,12 @@ class host(LDAPObject):
             label=_('Principal name'),
             flags=['no_create', 'no_update', 'no_search'],
         ),
+        Str('macaddress*',
+            pattern='^([a-fA-F0-9]{2}[:|\-]?){5}[a-fA-F0-9]{2}$',
+            pattern_errmsg='Must be of the form HH:HH:HH:HH:HH:HH, where each H is a hexadecimal character.',
+            label=_('MAC Address'),
+            doc=_('Hardware MAC address(es) on this host'),
+        ),
     )
 
     def get_dn(self, *keys, **options):
@@ -442,6 +448,7 @@ class host_add(LDAPCreate):
             x509.verify_cert_subject(ldap, keys[-1], cert)
             entry_attrs['usercertificate'] = cert
         entry_attrs['managedby'] = dn
+        entry_attrs['objectclass'].append('ieee802device')
         return dn
 
     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
@@ -681,6 +688,17 @@ class host_mod(LDAPUpdate):
         if options.get('random'):
             entry_attrs['userpassword'] = ipa_generate_password()
             setattr(context, 'randompassword', entry_attrs['userpassword'])
+        if 'macaddress' in entry_attrs:
+            if 'objectclass' in entry_attrs:
+                obj_classes = entry_attrs['objectclass']
+            else:
+                (_dn, _entry_attrs) = ldap.get_entry(
+                    dn, ['objectclass']
+                )
+                obj_classes = _entry_attrs['objectclass']
+            if 'ieee802device' not in obj_classes:
+                obj_classes.append('ieee802device')
+                entry_attrs['objectclass'] = obj_classes
 
         return dn
 
diff --git a/tests/test_xmlrpc/objectclasses.py b/tests/test_xmlrpc/objectclasses.py
index 3569579ef6b2a4bfc5c7bbe385ca5c19c3401fa1..cdcc6420c8cc359465a8eb81cc42b08c5be50443 100644
--- a/tests/test_xmlrpc/objectclasses.py
+++ b/tests/test_xmlrpc/objectclasses.py
@@ -44,6 +44,7 @@ group = [
 ]
 
 host = [
+    u'ieee802device',
     u'ipaobject',
     u'nshost',
     u'ipahost',
diff --git a/tests/test_xmlrpc/test_host_plugin.py b/tests/test_xmlrpc/test_host_plugin.py
index 5e71370600a31727d5d3907d465c14370489f7d8..9459aec39b815f9ca9a2b2f1bdaad14c4ca64f5a 100644
--- a/tests/test_xmlrpc/test_host_plugin.py
+++ b/tests/test_xmlrpc/test_host_plugin.py
@@ -431,6 +431,71 @@ class test_host(Declarative):
 
 
         dict(
+            desc='Add MAC address to %r' % fqdn1,
+            command=('host_mod', [fqdn1], dict(macaddress=u'00:50:56:30:F6:5F')),
+            expected=dict(
+                value=fqdn1,
+                summary=u'Modified host "%s"' % fqdn1,
+                result=dict(
+                    description=[u'Updated host 1'],
+                    fqdn=[fqdn1],
+                    l=[u'Undisclosed location 1'],
+                    krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+                    managedby_host=[u'%s' % fqdn1],
+                    usercertificate=[base64.b64decode(servercert)],
+                    valid_not_before=fuzzy_date,
+                    valid_not_after=fuzzy_date,
+                    subject=lambda x: DN(x) == \
+                        DN(('CN',api.env.host),('O',api.env.realm)),
+                    serial_number=fuzzy_digits,
+                    md5_fingerprint=fuzzy_hash,
+                    sha1_fingerprint=fuzzy_hash,
+                    macaddress=[u'00:50:56:30:F6:5F'],
+                    issuer=fuzzy_issuer,
+                    has_keytab=False,
+                    has_password=False,
+                ),
+            ),
+        ),
+
+
+        dict(
+            desc='Add another MAC address to %r' % fqdn1,
+            command=('host_mod', [fqdn1], dict(macaddress=[u'00:50:56:30:F6:5F', u'00:50:56:2C:8D:82'])),
+            expected=dict(
+                value=fqdn1,
+                summary=u'Modified host "%s"' % fqdn1,
+                result=dict(
+                    description=[u'Updated host 1'],
+                    fqdn=[fqdn1],
+                    l=[u'Undisclosed location 1'],
+                    krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+                    managedby_host=[u'%s' % fqdn1],
+                    usercertificate=[base64.b64decode(servercert)],
+                    valid_not_before=fuzzy_date,
+                    valid_not_after=fuzzy_date,
+                    subject=lambda x: DN(x) == \
+                        DN(('CN',api.env.host),('O',api.env.realm)),
+                    serial_number=fuzzy_digits,
+                    md5_fingerprint=fuzzy_hash,
+                    sha1_fingerprint=fuzzy_hash,
+                    macaddress=[u'00:50:56:30:F6:5F', u'00:50:56:2C:8D:82'],
+                    issuer=fuzzy_issuer,
+                    has_keytab=False,
+                    has_password=False,
+                ),
+            ),
+        ),
+
+
+        dict(
+            desc='Add an illegal MAC address to %r' % fqdn1,
+            command=('host_mod', [fqdn1], dict(macaddress=[u'xx'])),
+            expected=errors.ValidationError(name='macaddress', error='invalid \'macaddress\': Must be of the form HH:HH:HH:HH:HH:HH, where each H is a hexadecimal character.'),
+        ),
+
+
+        dict(
             desc='Delete %r' % fqdn1,
             command=('host_del', [fqdn1], {}),
             expected=dict(
-- 
1.7.6

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to