func (c *DebugHooksCommand) validateHooks(unit *state.Unit) error { if len(c.hooks) == 0 { return nil } service, err := unit.Service() if err != nil { return err } eps, err := service.Endpoints() if err != nil { return err } validHooks := make(map[string]bool) for _, hook := range hooks.UnitHooks() { validHooks[string(hook)] = true } for _, ep := range eps { for _, hook := range hooks.RelationHooks() { hook := fmt.Sprintf("%s-%s", ep.Relation.Name, hook) validHooks[hook] = true } } for _, hook := range c.hooks { if !validHooks[hook] { return fmt.Errorf("unit %q does not contain hook %q", unit.Name(), hook) } } return nil }
func (context *statusContext) processUnit(unit *state.Unit) (status unitStatus) { status.PublicAddress, _ = unit.PublicAddress() for _, port := range unit.OpenedPorts() { status.OpenedPorts = append(status.OpenedPorts, port.String()) } if unit.IsPrincipal() { status.Machine, _ = unit.AssignedMachineId() } status.Life, status.AgentVersion, status.AgentState, status.AgentStateInfo, status.Err = processAgent(unit) if subUnits := unit.SubordinateNames(); len(subUnits) > 0 { status.Subordinates = make(map[string]unitStatus) for _, name := range subUnits { subUnit := context.unitByName(name) // subUnit may be nil if subordinate was filtered out. if subUnit != nil { status.Subordinates[name] = context.processUnit(subUnit) } } } return }
func waitForUnitStarted(stateConn *state.State, unit *state.Unit, c *C) { timeout := time.After(5 * time.Second) for { select { case <-timeout: c.Fatalf("no activity detected") case <-time.After(testing.ShortWait): err := unit.Refresh() c.Assert(err, IsNil) st, info, err := unit.Status() c.Assert(err, IsNil) switch st { case params.StatusPending, params.StatusInstalled: c.Logf("waiting...") continue case params.StatusStarted: c.Logf("started!") return case params.StatusDown: stateConn.StartSync() c.Logf("unit is still down") default: c.Fatalf("unexpected status %s %s", st, info) } } } }
// matchUnit attempts to match a state.Unit to one of // a set of patterns, taking into account subordinate // relationships. func (m unitMatcher) matchUnit(u *state.Unit) bool { if m.matchesAny() { return true } // Keep the unit if: // (a) its name matches a pattern, or // (b) it's a principal and one of its subordinates matches, or // (c) it's a subordinate and its principal matches. // // Note: do *not* include a second subordinate if the principal is // only matched on account of a first subordinate matching. if m.matchString(u.Name()) { return true } if u.IsPrincipal() { for _, s := range u.SubordinateNames() { if m.matchString(s) { return true } } return false } principal, valid := u.PrincipalName() if !valid { panic("PrincipalName failed for subordinate unit") } return m.matchString(principal) }
// Resolved marks the unit as having had any previous state transition // problems resolved, and informs the unit that it may attempt to // reestablish normal workflow. The retryHooks parameter informs // whether to attempt to reexecute previous failed hooks or to continue // as if they had succeeded before. func (conn *Conn) Resolved(unit *state.Unit, retryHooks bool) error { status, _, err := unit.Status() if err != nil { return err } if status != state.UnitError { return fmt.Errorf("unit %q is not in an error state", unit) } mode := state.ResolvedNoHooks if retryHooks { mode = state.ResolvedRetryHooks } return unit.SetResolved(mode) }
func (s *AssignSuite) assertAssignedUnit(c *C, unit *state.Unit) string { // Check the machine on the unit is set. machineId, err := unit.AssignedMachineId() c.Assert(err, IsNil) // Check that the principal is set on the machine. machine, err := s.State.Machine(machineId) c.Assert(err, IsNil) machineUnits, err := machine.Units() c.Assert(err, IsNil) c.Assert(machineUnits, HasLen, 1) // Make sure it is the right unit. c.Assert(machineUnits[0].Name(), Equals, unit.Name()) return machineId }
func newUnitToolWaiter(u *state.Unit) *toolsWaiter { w := u.Watch() waiter := &toolsWaiter{ changes: make(chan struct{}, 1), watcher: w, tooler: u, } go func() { for _ = range w.Changes() { waiter.changes <- struct{}{} } close(waiter.changes) }() return waiter }
func processUnit(unit *state.Unit) (map[string]interface{}, error) { r := m() if addr, ok := unit.PublicAddress(); ok { r["public-address"] = addr } if id, err := unit.AssignedMachineId(); err == nil { // TODO(dfc) we could make this nicer, ie machine/0 r["machine"] = id } processVersion(r, unit) processStatus(r, unit) return r, nil }
func assertUnitRemoved(c *C, unit *state.Unit) { err := unit.Refresh() c.Assert(err, checkers.Satisfies, errors.IsNotFoundError) err = unit.Destroy() c.Assert(err, IsNil) err = unit.EnsureDead() c.Assert(err, IsNil) err = unit.Remove() c.Assert(err, IsNil) }
// remove will remove the supplied unit from state. It will panic if it // observes inconsistent internal state. func (d *Deployer) remove(unit *state.Unit) error { if d.deployed.Contains(unit.Name()) { panic("must not remove a deployed unit") } else if unit.Life() == state.Alive { panic("must not remove an Alive unit") } logger.Infof("removing unit %q", unit) if err := unit.EnsureDead(); err != nil { return err } return unit.Remove() }
func (c *NatCommand) UnitContainment(u *state.Unit) (*UnitContainment, error) { machineId, err := u.AssignedMachineId() if err != nil { return nil, err } host, ok := c.MachineMap[machineId] if !ok { return nil, fmt.Errorf("machine not found: %q", machineId) } gatewayId := state.ParentId(machineId) if gatewayId == "" { // Ignore machines not in containers return nil, ErrNoContainer } gateway, ok := c.MachineMap[gatewayId] if !ok { return nil, fmt.Errorf("parent machine %q not found", gatewayId) } return &UnitContainment{Unit: u, GatewayMachine: gateway, HostMachine: host}, nil }
// startUnit creates a new data value for tracking details of the // unit and starts watching the unit for port changes. The provided // machineId must be the id for the machine the unit was last observed // to be assigned to. func (fw *Firewaller) startUnit(unit *state.Unit, machineId string) error { service, err := unit.Service() if err != nil { return err } serviceName := service.Name() unitName := unit.Name() unitd := &unitData{ fw: fw, unit: unit, ports: unit.OpenedPorts(), } fw.unitds[unitName] = unitd unitd.machined = fw.machineds[machineId] unitd.machined.unitds[unitName] = unitd if fw.serviceds[serviceName] == nil { err := fw.startService(service) if err != nil { delete(fw.unitds, unitName) return err } } unitd.serviced = fw.serviceds[serviceName] unitd.serviced.unitds[unitName] = unitd ports := make([]instance.Port, len(unitd.ports)) copy(ports, unitd.ports) go unitd.watchLoop(ports) return nil }
// remove will remove the supplied unit from state. It will panic if it // observes inconsistent internal state. func (d *Deployer) remove(unit *state.Unit) error { if d.deployed[unit.Name()] { panic("must not remove a deployed unit") } else if unit.Life() == state.Alive { panic("must not remove an Alive unit") } log.Printf("worker/deployer: removing unit %q", unit) if err := unit.EnsureDead(); err != nil { return err } service, err := unit.Service() if err != nil { return err } return service.RemoveUnit(unit) }
func (context *statusContext) processUnit(unit *state.Unit) (status unitStatus) { status.PublicAddress, _ = unit.PublicAddress() if unit.IsPrincipal() { status.Machine, _ = unit.AssignedMachineId() } status.Life, status.AgentVersion, status.AgentState, status.AgentStateInfo, status.Err = processAgent(unit) if subUnits := unit.SubordinateNames(); len(subUnits) > 0 { status.Subordinates = make(map[string]unitStatus) for _, name := range subUnits { subUnit := context.unitByName(name) status.Subordinates[name] = context.processUnit(subUnit) } } return }
// deploy will deploy the supplied unit with the deployer's manager. It will // panic if it observes inconsistent internal state. func (d *Deployer) deploy(unit *state.Unit) error { unitName := unit.Name() if d.deployed.Contains(unit.Name()) { panic("must not re-deploy a deployed unit") } logger.Infof("deploying unit %q", unit) initialPassword, err := utils.RandomPassword() if err != nil { return err } if err := unit.SetPassword(initialPassword); err != nil { return fmt.Errorf("cannot set password for unit %q: %v", unit, err) } if err := unit.SetMongoPassword(initialPassword); err != nil { return fmt.Errorf("cannot set mongo password for unit %q: %v", unit, err) } if err := d.ctx.DeployUnit(unitName, initialPassword); err != nil { return err } d.deployed.Add(unitName) return nil }
// deploy will deploy the supplied unit with the deployer's manager. It will // panic if it observes inconsistent internal state. func (d *Deployer) deploy(unit *state.Unit) error { unitName := unit.Name() if d.deployed[unit.Name()] { panic("must not re-deploy a deployed unit") } log.Printf("worker/deployer: deploying unit %q", unit) initialPassword, err := trivial.RandomPassword() if err != nil { return err } if err := unit.SetMongoPassword(initialPassword); err != nil { return err } if err := d.mgr.DeployUnit(unitName, initialPassword); err != nil { return err } d.deployed[unitName] = true return nil }
func (s *UnitSuite) newAgent(c *C, unit *state.Unit) *UnitAgent { a := &UnitAgent{} s.initAgent(c, a, "--unit-name", unit.Name()) return a }
func (s *assignCleanSuite) assignUnit(unit *state.Unit) (*state.Machine, error) { if s.policy == state.AssignCleanEmpty { return unit.AssignToCleanEmptyMachine() } return unit.AssignToCleanMachine() }
func assertUnitLife(c *C, unit *state.Unit, life state.Life) { c.Assert(unit.Refresh(), IsNil) c.Assert(unit.Life(), Equals, life) }