func (r *Reboot) Handle(_ <-chan struct{}) error { rAction, err := r.st.GetRebootAction() if err != nil { return errors.Trace(err) } logger.Debugf("Reboot worker got action: %v", rAction) // NOTE: Here we explicitly avoid stopping on the abort channel as we are // wanting to make sure that we grab the lock and return an error // sufficiently heavyweight to get the agent to restart. spec := mutex.Spec{ Name: r.machineLockName, Clock: r.clock, Delay: 250 * time.Millisecond, } switch rAction { case params.ShouldReboot: logger.Debugf("acquiring mutex %q for reboot", r.machineLockName) if _, err := mutex.Acquire(spec); err != nil { return errors.Trace(err) } logger.Debugf("mutex %q acquired, won't release", r.machineLockName) return worker.ErrRebootMachine case params.ShouldShutdown: logger.Debugf("acquiring mutex %q for shutdown", r.machineLockName) if _, err := mutex.Acquire(spec); err != nil { return errors.Trace(err) } logger.Debugf("mutex %q acquired, won't release", r.machineLockName) return worker.ErrShutdownMachine default: return nil } }
func (h *hookLock) acquire() *hookStep { return &hookStep{stepFunc: func(c *gc.C, ctx *context) { releaser, err := mutex.Acquire(hookLockSpec()) c.Assert(err, jc.ErrorIsNil) h.releaser = releaser }} }
// runInitialiser runs the container initialiser with the initialisation hook held. func (cs *ContainerSetup) runInitialiser(abort <-chan struct{}, containerType instance.ContainerType, initialiser container.Initialiser) error { logger.Debugf("running initialiser for %s containers", containerType) spec := mutex.Spec{ Name: cs.initLockName, Clock: clock.WallClock, // If we don't get the lock straigh away, there is no point trying multiple // times per second for an operation that is likelty to take multiple seconds. Delay: time.Second, Cancel: abort, } logger.Debugf("acquire lock %q for container initialisation", cs.initLockName) releaser, err := mutex.Acquire(spec) if err != nil { return errors.Annotate(err, "failed to acquire initialization lock") } logger.Debugf("lock %q acquired", cs.initLockName) defer logger.Debugf("release lock %q for container initialisation", cs.initLockName) defer releaser.Release() if err := initialiser.Initialise(); err != nil { return errors.Trace(err) } return nil }
func (c *RunCommand) executeNoContext() (*exec.ExecResponse, error) { // Acquire the uniter hook execution lock to make sure we don't // stomp on each other. spec := mutex.Spec{ Name: c.MachineLockName, Clock: clock.WallClock, Delay: 250 * time.Millisecond, } logger.Debugf("acquire lock %q for juju-run", c.MachineLockName) releaser, err := mutex.Acquire(spec) if err != nil { return nil, errors.Trace(err) } logger.Debugf("lock %q acquired", c.MachineLockName) // Defer the logging first so it is executed after the Release. LIFO. defer logger.Debugf("release lock %q for juju-run", c.MachineLockName) defer releaser.Release() runCmd := c.appendProxyToCommands() return exec.RunCommands( exec.RunParams{ Commands: runCmd, }) }
func (s *store) acquireLock() (mutex.Releaser, error) { const lockName = "store-lock" spec := mutex.Spec{ Name: lockName, Clock: clock.WallClock, Delay: 20 * time.Millisecond, Timeout: lockTimeout, } releaser, err := mutex.Acquire(spec) if err != nil { return nil, errors.Trace(err) } return releaser, nil }
// acquireExecutionLock acquires the machine-level execution lock and returns a function to be used // to unlock it. func (w *hookRunner) acquireExecutionLock(interrupt <-chan struct{}) (mutex.Releaser, error) { spec := mutex.Spec{ Name: w.machineLockName, Clock: w.clock, Delay: 250 * time.Millisecond, Cancel: interrupt, } logger.Debugf("acquire lock %q for meter status hook execution", w.machineLockName) releaser, err := mutex.Acquire(spec) if err != nil { return nil, errors.Trace(err) } logger.Debugf("lock %q acquired", w.machineLockName) return releaser, nil }
// acquireExecutionLock acquires the machine-level execution lock, and // returns a func that must be called to unlock it. It's used by operation.Executor // when running operations that execute external code. func (u *Uniter) acquireExecutionLock() (mutex.Releaser, error) { // We want to make sure we don't block forever when locking, but take the // Uniter's catacomb into account. spec := mutex.Spec{ Name: u.hookLockName, Clock: u.clock, Delay: 250 * time.Millisecond, Cancel: u.catacomb.Dying(), } logger.Debugf("acquire lock %q for uniter hook execution", u.hookLockName) releaser, err := mutex.Acquire(spec) if err != nil { return nil, errors.Trace(err) } logger.Debugf("lock %q acquired", u.hookLockName) return releaser, nil }
func (s waitHooks) step(c *gc.C, ctx *context) { if len(s) == 0 { // Give unwanted hooks a moment to run... ctx.s.BackingState.StartSync() time.Sleep(coretesting.ShortWait) } ctx.hooks = append(ctx.hooks, s...) c.Logf("waiting for hooks: %#v", ctx.hooks) match, overshoot := ctx.matchHooks(c) if overshoot && len(s) == 0 { c.Fatalf("ran more hooks than expected") } waitExecutionLockReleased := func() { spec := hookLockSpec() spec.Timeout = worstCase releaser, err := mutex.Acquire(spec) if err != nil { c.Fatalf("failed to acquire execution lock: %v", err) } releaser.Release() } if match { if len(s) > 0 { // only check for lock release if there were hooks // run; hooks *not* running may be due to the lock // being held. waitExecutionLockReleased() } return } timeout := time.After(worstCase) for { ctx.s.BackingState.StartSync() select { case <-time.After(coretesting.ShortWait): if match, _ = ctx.matchHooks(c); match { waitExecutionLockReleased() return } case <-timeout: c.Fatalf("never got expected hooks") } } }
func (s *RunTestSuite) TestNoContextWithLock(c *gc.C) { spec := mutex.Spec{ Name: testLockName, Clock: clock.WallClock, Delay: 250 * time.Millisecond, } releaser, err := mutex.Acquire(spec) c.Assert(err, jc.ErrorIsNil) defer releaser.Release() // in case of failure channel := s.startRunAsync(c, []string{"--no-context", "echo done"}) ctx, err := waitForResult(channel, testing.ShortWait) c.Assert(err, gc.ErrorMatches, "timeout") releaser.Release() ctx, err = waitForResult(channel, testing.LongWait) c.Assert(err, jc.ErrorIsNil) c.Assert(strings.TrimRight(testing.Stdout(ctx), "\r\n"), gc.Equals, "done") }