Ask Your Question
1

How do I modify a user, who has a service running?

asked 2015-11-12 06:40:43 -0500

martin.gerdes gravatar image

updated 2015-11-23 09:00:21 -0500

I am just starting out with puppet. I took the https://forge.puppetlabs.com/saz/ntp Package, since it was suggested in the tutorial. After reading about how you should organize your code, I decided I liked the profile/role model: http://www.craigdunn.org/2012/05/239/

So I defined a common profile, and added the ntp module to it. Works, great. But I noticed that the home dir of ntp was not how I have configured our servers until now: Its set to /home/ntp, which does not exist, which tiger complains about. Well, I am just learning, so I think this is a good opportunity to try out the advantages of the profile/role model, leave the ntp module as is, and correct the users home dir afterwards.

However, a simple


user { 'ntp'
  ensure => 'present',
  home => '/var/lib/ntp'
}

results in the error:

change from /home/ntp to /var/cache/ntp failed: Could not set home on user[ntp]: Execution of '/usr/sbin/usermod -d /var/cache/ntp ntp' returned 8: usermod: user ntp is currently used by process 5584
So this does not work because the ntp service is running. A bit of googling found me this bug: https://tickets.puppetlabs.com/browse... Yeah, an "obstruction" parameter would be awesome...

So I now ended up doing this:


class profile::common (
    $ntp_client=true,
    $ntp_client_server_list=["myntpserver.local"]
) {
    if $ntp_client {
        class { '::ntp':
            server_list=>$ntp_client_server_list,
            server_options=>" burst"
        }
        #stop ntp and set its homedir if set to something else ->puppet will restart ntp
        exec { '/etc/init.d/ntp stop && usermod -d /var/lib/ntp ntp':
            unless => '/usr/bin/test "`egrep "^ntp:" /etc/passwd | cut -f 6 -d:`" = /var/lib/ntp'
        }
    }
}

This actually works perfectly well!

However, I am just starting out with puppet, as I said. Is this really the best way to solve this? It does not seem very puppet like to me, I am hard coding the commands and recreating puppets test logic. But I have found no way to trigger a command to be executed before (not after ->notify) a change is made...

So, what is the best practice for something like this?

EDIT:

As suggested, I tried to do it using require (I actually had tried something similar before, relying on ordering):


#the ntp class sets the ntp home dir wrong - fix it (puppet will restart ntp)
user { 'ntp':
    ensure => 'present',
    home => '/var/lib/ntp',
    require => Exec['stop ntp if wrong home dir'],
}
exec { 'stop ntp if wrong home dir':
    command => '/etc/init.d/ntp stop',
    unless => '/usr/bin/test ~ntp = /var/lib/ntp',
}

Starting ntp via exec is both wrong (the suggested condition would not match anymore - the home dir has changed), and unnecessary: puppet notices that ntp has been stopped, and starts it again by itself.

However, this is also the problem preventing me from using this solution.

Executing 'puppet agent -t' on the client gives me:


Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for admintestvm.local
Info: Applying configuration version '1448289413'
Notice ...
(more)
edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
0

answered 2015-11-12 11:14:05 -0500

could you try forcelocal => true under the home entry?

edit flag offensive delete link more

Comments

with

user { 'ntp':
    ensure => 'present',
    home => '/var/lib/ntp',
    forcelocal => true
}
I get
Error: Could not set home on user[ntp]: Execution of '/usr/sbin/usermod -d /var/lib/ntp ntp' returned 8: usermod: user ntp is currently used by process 23653

martin.gerdes gravatar imagemartin.gerdes ( 2015-11-13 02:25:48 -0500 )edit

So no change at all. Which is what I would expect: forcelocal forces puppet to manage the user account - which puppet is already doing, it's just failing at it.

martin.gerdes gravatar imagemartin.gerdes ( 2015-11-13 02:35:34 -0500 )edit
0

answered 2015-11-13 09:05:22 -0500

scoffland gravatar image

updated 2015-11-13 09:09:23 -0500

The least convoluted way I can think of to do this would be with execs, and that is not really the puppet way.

user { 'ntp':
  ensure => 'present',
  home => '/var/lib/ntp',
  require => Exec['/etc/init.d/ntp stop'],
  before => Exec['/etc/init.d/ntp start'],
}

exec { '/etc/init.d/ntp stop':
  unless => '/usr/bin/test "`egrep "^ntp:" /etc/passwd | cut -f 6 -d:`" = /var/lib/ntp',
}
exec { '/etc/init.d/ntp start':
  unless => '/usr/bin/test "`egrep "^ntp:" /etc/passwd | cut -f 6 -d:`" = /var/lib/ntp',
}

Notify the service is the puppet way to do things but this would not stop the service until a task was completed and then restart it after.

edit flag offensive delete link more

Comments

I had already tried this. Tried it again using code close to yours. Works, but I don't think it works safely, but only because of a race condition. I have edited my question to include that possible (but in my opinion unreliable) solution. Still, thanks a lot for your answer!

martin.gerdes gravatar imagemartin.gerdes ( 2015-11-23 08:58:31 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2015-11-12 05:24:13 -0500

Seen: 360 times

Last updated: Nov 23 '15