Add support for Open and NetBSD platforms for user and group modules, including a new login_class parameter for FreeBSD, OpenBSD and NetBSD.

reviewable/pr18780/r1
trbs 11 years ago
parent 373e4ee7d4
commit a31ba582b4

@ -61,8 +61,8 @@ import platform
class Group(object): class Group(object):
""" """
This is a generic Group manipulation class that is subclassed This is a generic Group manipulation class that is subclassed
based on platform. based on platform.
A subclass may wish to override the following action methods:- A subclass may wish to override the following action methods:-
- group_del() - group_del()
- group_add() - group_add()
@ -96,7 +96,7 @@ class Group(object):
def group_del(self): def group_del(self):
cmd = [self.module.get_bin_path('groupdel', True), self.name] cmd = [self.module.get_bin_path('groupdel', True), self.name]
return self.execute_command(cmd) return self.execute_command(cmd)
def group_add(self, **kwargs): def group_add(self, **kwargs):
cmd = [self.module.get_bin_path('groupadd', True)] cmd = [self.module.get_bin_path('groupadd', True)]
for key in kwargs: for key in kwargs:
@ -107,7 +107,7 @@ class Group(object):
cmd.append('-r') cmd.append('-r')
cmd.append(self.name) cmd.append(self.name)
return self.execute_command(cmd) return self.execute_command(cmd)
def group_mod(self, **kwargs): def group_mod(self, **kwargs):
cmd = [self.module.get_bin_path('groupmod', True)] cmd = [self.module.get_bin_path('groupmod', True)]
info = self.group_info() info = self.group_info()
@ -122,14 +122,14 @@ class Group(object):
return (True, '', '') return (True, '', '')
cmd.append(self.name) cmd.append(self.name)
return self.execute_command(cmd) return self.execute_command(cmd)
def group_exists(self): def group_exists(self):
try: try:
if grp.getgrnam(self.name): if grp.getgrnam(self.name):
return True return True
except KeyError: except KeyError:
return False return False
def group_info(self): def group_info(self):
if not self.group_exists(): if not self.group_exists():
return False return False
@ -162,7 +162,7 @@ class SunOS(Group):
cmd.append(kwargs[key]) cmd.append(kwargs[key])
cmd.append(self.name) cmd.append(self.name)
return self.execute_command(cmd) return self.execute_command(cmd)
# =========================================== # ===========================================
@ -228,25 +228,111 @@ class FreeBsdGroup(Group):
cmd = [self.module.get_bin_path('pw', True), 'groupdel', self.name] cmd = [self.module.get_bin_path('pw', True), 'groupdel', self.name]
return self.execute_command(cmd) return self.execute_command(cmd)
def group_add(self,**kwargs): def group_add(self, **kwargs):
cmd = [self.module.get_bin_path('pw', True), 'groupadd', self.name] cmd = [self.module.get_bin_path('pw', True), 'groupadd', self.name]
if self.gid is not None: if self.gid is not None:
cmd.append('-g %d' % int(self.gid)) cmd.append('-g %d' % int(self.gid))
return self.execute_command(cmd) return self.execute_command(cmd)
def group_mod(self,**kwargs): def group_mod(self, **kwargs):
cmd = [self.module.get_bin_path('pw', True), 'groupmod', self.name] cmd = [self.module.get_bin_path('pw', True), 'groupmod', self.name]
info = self.group_info() info = self.group_info()
cmd_len = len(cmd) cmd_len = len(cmd)
if self.gid is not None and int(self.gid) != info[2]: if self.gid is not None and int(self.gid) != info[2]:
cmd.append('-g %d' % int(self.gid)) cmd.append('-g %d' % int(self.gid))
# modify the group if cmd will do anything # modify the group if cmd will do anything
if cmd_len != len(cmd): if cmd_len != len(cmd):
if self.module.check_mode:
return (True, '', '')
return self.execute_command(cmd) return self.execute_command(cmd)
return (None, '', '') return (None, '', '')
# =========================================== # ===========================================
class OpenBsdGroup(Group):
"""
This is a OpenBSD Group manipulation class.
This overrides the following methods from the generic class:-
- group_del()
- group_add()
- group_mod()
"""
platform = 'OpenBSD'
distribution = None
GROUPFILE = '/etc/group'
def group_del(self):
cmd = [self.module.get_bin_path('groupdel', True), self.name]
return self.execute_command(cmd)
def group_add(self, **kwargs):
cmd = [self.module.get_bin_path('groupadd', True)]
if self.gid is not None:
cmd.append('-g')
cmd.append('%d' % int(self.gid))
cmd.append(self.name)
return self.execute_command(cmd)
def group_mod(self, **kwargs):
cmd = [self.module.get_bin_path('groupmod', True)]
info = self.group_info()
cmd_len = len(cmd)
if self.gid is not None and int(self.gid) != info[2]:
cmd.append('-g')
cmd.append('%d' % int(self.gid))
if len(cmd) == 1:
return (None, '', '')
if self.module.check_mode:
return (True, '', '')
cmd.append(self.name)
return self.execute_command(cmd)
# ===========================================
class NetBsdGroup(Group):
"""
This is a NetBSD Group manipulation class.
This overrides the following methods from the generic class:-
- group_del()
- group_add()
- group_mod()
"""
platform = 'NetBSD'
distribution = None
GROUPFILE = '/etc/group'
def group_del(self):
cmd = [self.module.get_bin_path('groupdel', True), self.name]
return self.execute_command(cmd)
def group_add(self, **kwargs):
cmd = [self.module.get_bin_path('groupadd', True)]
if self.gid is not None:
cmd.append('-g')
cmd.append('%d' % int(self.gid))
cmd.append(self.name)
return self.execute_command(cmd)
def group_mod(self, **kwargs):
cmd = [self.module.get_bin_path('groupmod', True)]
info = self.group_info()
cmd_len = len(cmd)
if self.gid is not None and int(self.gid) != info[2]:
cmd.append('-g')
cmd.append('%d' % int(self.gid))
if len(cmd) == 1:
return (None, '', '')
if self.module.check_mode:
return (True, '', '')
cmd.append(self.name)
return self.execute_command(cmd)
# ===========================================
def main(): def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec = dict( argument_spec = dict(

@ -106,6 +106,10 @@ options:
description: description:
- When used with C(state=absent), behavior is as with - When used with C(state=absent), behavior is as with
C(userdel --force). C(userdel --force).
login_class:
required: false
description:
- Optionally sets the user's login class for FreeBSD, OpenBSD and NetBSD systems.
remove: remove:
required: false required: false
default: "no" default: "no"
@ -215,6 +219,7 @@ class User(object):
self.remove = module.params['remove'] self.remove = module.params['remove']
self.createhome = module.params['createhome'] self.createhome = module.params['createhome']
self.system = module.params['system'] self.system = module.params['system']
self.login_class = module.params['login_class']
self.append = module.params['append'] self.append = module.params['append']
self.sshkeygen = module.params['generate_ssh_key'] self.sshkeygen = module.params['generate_ssh_key']
self.ssh_bits = module.params['ssh_key_bits'] self.ssh_bits = module.params['ssh_key_bits']
@ -526,7 +531,7 @@ class FreeBsdUser(User):
This is a FreeBSD User manipulation class - it uses the pw command This is a FreeBSD User manipulation class - it uses the pw command
to manipulate the user database, followed by the chpass command to manipulate the user database, followed by the chpass command
to change the password. to change the password.
This overrides the following methods from the generic class:- This overrides the following methods from the generic class:-
- create_user() - create_user()
- remove_user() - remove_user()
@ -554,7 +559,7 @@ class FreeBsdUser(User):
self.module.get_bin_path('pw', True), self.module.get_bin_path('pw', True),
'useradd', 'useradd',
'-n', '-n',
self.name self.name,
] ]
if self.uid is not None: if self.uid is not None:
@ -590,6 +595,10 @@ class FreeBsdUser(User):
cmd.append('-s') cmd.append('-s')
cmd.append(self.shell) cmd.append(self.shell)
if self.login_class is not None:
cmd.append('-L')
cmd.append(self.login_class)
# system cannot be handled currently - should we error if its requested? # system cannot be handled currently - should we error if its requested?
# create the user # create the user
(rc, out, err) = self.execute_command(cmd) (rc, out, err) = self.execute_command(cmd)
@ -645,6 +654,10 @@ class FreeBsdUser(User):
cmd.append('-s') cmd.append('-s')
cmd.append(self.shell) cmd.append(self.shell)
if self.login_class is not None:
cmd.append('-L')
cmd.append(self.login_class)
if self.groups is not None: if self.groups is not None:
current_groups = self.user_group_membership() current_groups = self.user_group_membership()
groups = self.get_groups_set() groups = self.get_groups_set()
@ -690,6 +703,308 @@ class FreeBsdUser(User):
# =========================================== # ===========================================
class OpenBSDUser(User):
"""
This is a OpenBSD User manipulation class.
Main differences are that OpenBSD:-
- has no concept of "system" account.
- has no force delete user
This overrides the following methods from the generic class:-
- create_user()
- remove_user()
- modify_user()
"""
platform = 'OpenBSD'
distribution = None
SHADOWFILE = '/etc/master.passwd'
def create_user(self):
cmd = [self.module.get_bin_path('useradd', True)]
if self.uid is not None:
cmd.append('-u')
cmd.append(self.uid)
if self.non_unique:
cmd.append('-o')
if self.group is not None:
if not self.group_exists(self.group):
self.module.fail_json(msg="Group %s does not exist" % self.group)
cmd.append('-g')
cmd.append(self.group)
if self.groups is not None:
groups = self.get_groups_set()
cmd.append('-G')
cmd.append(','.join(groups))
if self.comment is not None:
cmd.append('-c')
cmd.append(self.comment)
if self.home is not None:
cmd.append('-d')
cmd.append(self.home)
if self.shell is not None:
cmd.append('-s')
cmd.append(self.shell)
if self.login_class is not None:
cmd.append('-L')
cmd.append(self.login_class)
if self.password is not None:
cmd.append('-p')
cmd.append(self.password)
if self.createhome:
cmd.append('-m')
cmd.append(self.name)
return self.execute_command(cmd)
def remove_user_userdel(self):
cmd = [self.module.get_bin_path('userdel', True)]
if self.remove:
cmd.append('-r')
cmd.append(self.name)
return self.execute_command(cmd)
def modify_user(self):
cmd = [self.module.get_bin_path('usermod', True)]
info = self.user_info()
if self.uid is not None and info[2] != int(self.uid):
cmd.append('-u')
cmd.append(self.uid)
if self.non_unique:
cmd.append('-o')
if self.group is not None:
if not self.group_exists(self.group):
self.module.fail_json(msg="Group %s does not exist" % self.group)
ginfo = self.group_info(self.group)
if info[3] != ginfo[2]:
cmd.append('-g')
cmd.append(self.group)
if self.groups is not None:
current_groups = self.user_group_membership()
groups_need_mod = False
groups_option = '-G'
groups = []
if self.groups == '':
if current_groups and not self.append:
groups_need_mod = True
else:
groups = self.get_groups_set()
group_diff = set(current_groups).symmetric_difference(groups)
if group_diff:
if self.append:
for g in groups:
if g in group_diff:
groups_option = '-S'
groups_need_mod = True
break
else:
groups_need_mod = True
if groups_need_mod:
cmd.append(groups_option)
cmd.append(','.join(groups))
if self.comment is not None and info[4] != self.comment:
cmd.append('-c')
cmd.append(self.comment)
if self.home is not None and info[5] != self.home:
cmd.append('-d')
cmd.append(self.home)
if self.shell is not None and info[6] != self.shell:
cmd.append('-s')
cmd.append(self.shell)
if self.login_class is not None:
cmd.append('-L')
cmd.append(self.login_class)
if self.password is not None and info[1] != self.password:
cmd.append('-p')
cmd.append(self.password)
# skip if no changes to be made
if len(cmd) == 1:
return (None, '', '')
elif self.module.check_mode:
return (0, '', '')
cmd.append(self.name)
return self.execute_command(cmd)
# ===========================================
class NetBSDUser(User):
"""
This is a NetBSD User manipulation class.
Main differences are that NetBSD:-
- has no concept of "system" account.
- has no force delete user
This overrides the following methods from the generic class:-
- create_user()
- remove_user()
- modify_user()
"""
platform = 'NetBSD'
distribution = None
SHADOWFILE = '/etc/master.passwd'
def create_user(self):
cmd = [self.module.get_bin_path('useradd', True)]
if self.uid is not None:
cmd.append('-u')
cmd.append(self.uid)
if self.non_unique:
cmd.append('-o')
if self.group is not None:
if not self.group_exists(self.group):
self.module.fail_json(msg="Group %s does not exist" % self.group)
cmd.append('-g')
cmd.append(self.group)
if self.groups is not None:
groups = self.get_groups_set()
if len(groups) > 16:
self.module.fail_json(msg="Too many groups (%d) NetBSD allows for 16 max." % len(groups))
cmd.append('-G')
cmd.append(','.join(groups))
if self.comment is not None:
cmd.append('-c')
cmd.append(self.comment)
if self.home is not None:
cmd.append('-d')
cmd.append(self.home)
if self.shell is not None:
cmd.append('-s')
cmd.append(self.shell)
if self.login_class is not None:
cmd.append('-L')
cmd.append(self.login_class)
if self.password is not None:
cmd.append('-p')
cmd.append(self.password)
if self.createhome:
cmd.append('-m')
cmd.append(self.name)
return self.execute_command(cmd)
def remove_user_userdel(self):
cmd = [self.module.get_bin_path('userdel', True)]
if self.remove:
cmd.append('-r')
cmd.append(self.name)
return self.execute_command(cmd)
def modify_user(self):
cmd = [self.module.get_bin_path('usermod', True)]
info = self.user_info()
if self.uid is not None and info[2] != int(self.uid):
cmd.append('-u')
cmd.append(self.uid)
if self.non_unique:
cmd.append('-o')
if self.group is not None:
if not self.group_exists(self.group):
self.module.fail_json(msg="Group %s does not exist" % self.group)
ginfo = self.group_info(self.group)
if info[3] != ginfo[2]:
cmd.append('-g')
cmd.append(self.group)
if self.groups is not None:
current_groups = self.user_group_membership()
groups_need_mod = False
groups = []
if self.groups == '':
if current_groups and not self.append:
groups_need_mod = True
else:
groups = self.get_groups_set()
group_diff = set(current_groups).symmetric_difference(groups)
if group_diff:
if self.append:
for g in groups:
if g in group_diff:
groups = set(current_groups).union(groups)
groups_need_mod = True
break
else:
groups_need_mod = True
if groups_need_mod:
if len(groups) > 16:
self.module.fail_json(msg="Too many groups (%d) NetBSD allows for 16 max." % len(groups))
cmd.append('-G')
cmd.append(','.join(groups))
if self.comment is not None and info[4] != self.comment:
cmd.append('-c')
cmd.append(self.comment)
if self.home is not None and info[5] != self.home:
cmd.append('-d')
cmd.append(self.home)
if self.shell is not None and info[6] != self.shell:
cmd.append('-s')
cmd.append(self.shell)
if self.login_class is not None:
cmd.append('-L')
cmd.append(self.login_class)
if self.password is not None and info[1] != self.password:
cmd.append('-p')
cmd.append(self.password)
# skip if no changes to be made
if len(cmd) == 1:
return (None, '', '')
elif self.module.check_mode:
return (0, '', '')
cmd.append(self.name)
return self.execute_command(cmd)
# ===========================================
class SunOS(User): class SunOS(User):
""" """
This is a SunOS User manipulation class - The main difference between This is a SunOS User manipulation class - The main difference between
@ -1024,6 +1339,7 @@ def main():
home=dict(default=None, type='str'), home=dict(default=None, type='str'),
shell=dict(default=None, type='str'), shell=dict(default=None, type='str'),
password=dict(default=None, type='str'), password=dict(default=None, type='str'),
login_class=dict(default=None, type='str'),
# following options are specific to userdel # following options are specific to userdel
force=dict(default='no', type='bool'), force=dict(default='no', type='bool'),
remove=dict(default='no', type='bool'), remove=dict(default='no', type='bool'),

Loading…
Cancel
Save