$OpenBSD: patch-salt_modules_useradd_py,v 1.6 2015/01/16 13:19:48 ajacoutot Exp $

https://github.com/saltstack/salt/commit/9feb62718a19420054313898b78d36263fb6db7f
https://github.com/saltstack/salt/commit/e7df337b5549309867e672ea3362f63b584d5c98

--- salt/modules/useradd.py.orig	Wed Jan 14 19:38:21 2015
+++ salt/modules/useradd.py	Fri Jan 16 14:12:43 2015
@@ -29,7 +29,7 @@ __virtualname__ = 'user'
 
 def __virtual__():
     '''
-    Set the user module if the kernel is Linux or OpenBSD
+    Set the user module if the kernel is Linux, OpenBSD or NetBSD
     and remove some of the functionality on OS X
     '''
 
@@ -78,7 +78,8 @@ def add(name,
         roomnumber='',
         workphone='',
         homephone='',
-        createhome=True):
+        createhome=True,
+        loginclass=None):
     '''
     Add a user to the minion
 
@@ -96,24 +97,43 @@ def add(name,
     if gid not in (None, ''):
         cmd.extend(['-g', str(gid)])
     elif groups is not None and name in groups:
-        try:
-            for line in salt.utils.fopen('/etc/login.defs'):
-                if 'USERGROUPS_ENAB' not in line[:15]:
-                    continue
+        if __grains__['kernel'] != 'OpenBSD':
+            try:
+                for line in salt.utils.fopen('/etc/login.defs'):
+                    if 'USERGROUPS_ENAB' not in line[:15]:
+                        continue
 
-                if 'yes' in line:
-                    cmd.extend([
-                        '-g', str(__salt__['file.group_to_gid'](name))
-                    ])
+                    if 'yes' in line:
+                        cmd.extend([
+                            '-g', str(__salt__['file.group_to_gid'](name))
+                        ])
 
-                # We found what we wanted, let's break out of the loop
-                break
-        except OSError:
-            log.debug('Error reading /etc/login.defs', exc_info=True)
+                    # We found what we wanted, let's break out of the loop
+                    break
+            except OSError:
+                log.debug('Error reading /etc/login.defs', exc_info=True)
+        else:
+            try:
+                for line in salt.utils.fopen('/etc/usermgmt.conf'):
+                    if 'group' not in line[:5]:
+                        continue
 
+                    for val in line.split(" "):
+                        cmd.extend([
+                            '-g', str(val[1])
+                        ])
+
+                    # We found what we wanted, let's break out of the loop
+                    break
+            except OSError:
+                # /etc/usermgmt.conf not present: defaults will be used
+                pass
+
     if createhome:
         cmd.append('-m')
-    elif createhome is False:
+    elif (createhome is False
+          and __grains__['kernel'] != 'NetBSD'
+          and __grains__['kernel'] != 'OpenBSD'):
         cmd.append('-M')
 
     if home is not None:
@@ -122,9 +142,15 @@ def add(name,
     if not unique:
         cmd.append('-o')
 
-    if system and __grains__['kernel'] != 'NetBSD':
+    if (system
+        and __grains__['kernel'] != 'NetBSD'
+        and __grains__['kernel'] != 'OpenBSD'):
         cmd.append('-r')
 
+    if __grains__['kernel'] == 'OpenBSD':
+        if loginclass is not None:
+            cmd.extend(['-L', loginclass])
+
     cmd.append(name)
 
     ret = __salt__['cmd.run_all'](cmd, python_shell=False)
@@ -168,7 +194,7 @@ def delete(name, remove=False, force=False):
     if remove:
         cmd.append('-r')
 
-    if force:
+    if force and __grains__['kernel'] != 'OpenBSD':
         cmd.append('-f')
 
     cmd.append(name)
@@ -295,7 +321,7 @@ def chhome(name, home, persist=False):
     if home == pre_info['home']:
         return True
     cmd = ['usermod', '-d', home]
-    if persist:
+    if persist and __grains__['kernel'] != 'OpenBSD':
         cmd.append('-m')
     cmd.append(name)
     __salt__['cmd.run'](cmd, python_shell=False)
@@ -322,9 +348,15 @@ def chgroups(name, groups, append=False):
     if ugrps == set(groups):
         return True
     cmd = ['usermod']
-    if append:
-        cmd.append('-a')
-    cmd.extend(['-G', ','.join(groups), name])
+    if __grains__['kernel'] != 'OpenBSD':
+        if append:
+            cmd.append('-a')
+        cmd.extend(['-G', ','.join(groups), name])
+    else:
+        if append:
+            cmd.extend(['-G', ','.join(groups), name])
+        else:
+            cmd.extend(['-S', ','.join(groups), name])
     cmdret = __salt__['cmd.run_all'](cmd, python_shell=False)
     ret = not cmdret['retcode']
     # try to fallback on gpasswd to add user to localgroups
@@ -443,6 +475,29 @@ def chhomephone(name, homephone):
     return False
 
 
+def chloginclass(name, loginclass):
+    '''
+    Change the default login class of the user
+
+    CLI Example:
+
+    .. code-block:: bash
+
+        salt '*' user.chloginclass foo staff
+    '''
+    if __grains__['kernel'] != 'OpenBSD':
+        return False
+    pre_info = get_loginclass(name)
+    if loginclass == pre_info['loginclass']:
+        return True
+    cmd = 'usermod -L {0} {1}'.format(loginclass, name)
+    __salt__['cmd.run'](cmd)
+    post_info = get_loginclass(name)
+    if post_info['loginclass'] != pre_info['loginclass']:
+        return post_info['loginclass'] == loginclass
+    return False
+
+
 def info(name):
     '''
     Return user information
@@ -459,6 +514,29 @@ def info(name):
         return {}
     else:
         return _format_info(data)
+
+
+def get_loginclass(name):
+    '''
+    Get the login class of the user
+
+    CLI Example:
+
+    .. code-block:: bash
+
+        salt '*' user.get_loginclass foo
+    '''
+    if __grains__['kernel'] != 'OpenBSD':
+        return False
+    info = __salt__['cmd.run_stdout']('userinfo {0}'.format(name),
+        output_loglevel='debug')
+    for line in info.splitlines():
+        if line.startswith("class"):
+            loginclass = line.split()
+    if len(loginclass) == 2:
+        return {'loginclass': loginclass[1]}
+    else:
+        return {'loginclass': '""'}
 
 
 def _format_info(data):
