Example #1
0
// processUnitAndAgentStatus retrieves status information for both unit and unitAgents.
func processUnitAndAgentStatus(unit *state.Unit, status *params.UnitStatus) {
	status.UnitAgent, status.Workload = processUnitStatus(unit)

	// Legacy fields required until Juju 2.0.
	// We only display pending, started, error, stopped.
	var ok bool
	legacyState, ok := state.TranslateToLegacyAgentState(
		state.Status(status.UnitAgent.Status),
		state.Status(status.Workload.Status),
		status.Workload.Info,
	)
	if !ok {
		logger.Warningf(
			"translate to legacy status encounted unexpected workload status %q and agent status %q",
			status.Workload.Status, status.UnitAgent.Status)
	}
	status.AgentState = params.Status(legacyState)
	if status.AgentState == params.StatusError {
		status.AgentStateInfo = status.Workload.Info
	}
	status.AgentVersion = status.UnitAgent.Version
	status.Life = status.UnitAgent.Life
	status.Err = status.UnitAgent.Err

	processUnitLost(unit, status)

	return
}
Example #2
0
func (s *serviceSuite) TestSetServiceStatus(c *gc.C) {
	message := "a test message"
	stat, err := s.wordpressService.Status()

	c.Assert(stat.Status, gc.Not(gc.Equals), state.Status(params.StatusActive))
	c.Assert(stat.Message, gc.Not(gc.Equals), message)

	err = s.apiService.SetStatus(s.wordpressUnit.Name(), params.StatusActive, message, map[string]interface{}{})
	c.Assert(err, gc.ErrorMatches, "this unit is not the leader")

	s.claimLeadership(c, s.wordpressUnit, s.wordpressService)

	err = s.apiService.SetStatus(s.wordpressUnit.Name(), params.StatusActive, message, map[string]interface{}{})
	c.Assert(err, jc.ErrorIsNil)

	stat, err = s.wordpressService.Status()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(stat.Status, gc.Equals, state.Status(params.StatusActive))
	c.Assert(stat.Message, gc.Equals, message)
}
Example #3
0
func (s *StatusSetter) setEntityStatus(tag names.Tag, status params.Status, info string, data map[string]interface{}) error {
	entity, err := s.st.FindEntity(tag)
	if err != nil {
		return err
	}
	switch entity := entity.(type) {
	case state.StatusSetter:
		return entity.SetStatus(state.Status(status), info, data)
	default:
		return NotSupportedError(tag, fmt.Sprintf("setting status, %T", entity))
	}
}
Example #4
0
func (s *StatusModelSuite) TestUnitAgentStatusDocValidation(c *gc.C) {
	unit := s.Factory.MakeUnit(c, nil)
	for i, test := range []struct {
		status state.Status
		info   string
		err    string
	}{{
		status: state.StatusPending,
		err:    `cannot set invalid status "pending"`,
	}, {
		status: state.StatusDown,
		err:    `cannot set invalid status "down"`,
	}, {
		status: state.StatusStarted,
		err:    `cannot set invalid status "started"`,
	}, {
		status: state.StatusStopped,
		err:    `cannot set invalid status "stopped"`,
	}, {
		status: state.StatusAllocating,
		err:    `cannot set status "allocating"`,
	}, {
		status: state.StatusAllocating,
		info:   "any message",
		err:    `cannot set status "allocating"`,
	}, {
		status: state.StatusLost,
		err:    `cannot set status "lost"`,
	}, {
		status: state.StatusLost,
		info:   "any message",
		err:    `cannot set status "lost"`,
	}, {
		status: state.StatusError,
		err:    `cannot set status "error" without info`,
	}, {
		status: state.StatusError,
		info:   "some error info",
	}, {
		status: state.Status("bogus"),
		err:    `cannot set invalid status "bogus"`,
	}} {
		c.Logf("test %d", i)
		err := unit.SetAgentStatus(test.status, test.info, nil)
		if test.err != "" {
			c.Check(err, gc.ErrorMatches, test.err)
		} else {
			c.Check(err, jc.ErrorIsNil)
		}
	}
}
Example #5
0
func matchAgentStatus(patterns []string, status state.Status) (bool, bool, error) {
	oneValidStatus := false
	for _, p := range patterns {
		// If the pattern isn't a known status, ignore it.
		ps := state.Status(p)
		if !ps.KnownAgentStatus() {
			continue
		}

		oneValidStatus = true
		if status.Matches(ps) {
			return true, true, nil
		}
	}
	return false, oneValidStatus, nil
}
Example #6
0
func matchWorkloadStatus(patterns []string, workloadStatus state.Status, agentStatus state.Status) (bool, bool, error) {
	oneValidStatus := false
	for _, p := range patterns {
		// If the pattern isn't a known status, ignore it.
		ps := state.Status(p)
		if !ps.KnownWorkloadStatus() {
			continue
		}

		oneValidStatus = true
		// To preserve current expected behaviour, we only report on workload status
		// if the agent itself is not in error.
		if agentStatus != state.StatusError && workloadStatus.WorkloadMatches(ps) {
			return true, true, nil
		}
	}
	return false, oneValidStatus, nil
}
Example #7
0
func (s *UnitAgentSuite) TestGetSetStatusWhileAlive(c *gc.C) {
	agent := s.unit.Agent().(*state.UnitAgent)
	err := agent.SetStatus(state.StatusError, "", nil)
	c.Assert(err, gc.ErrorMatches, `cannot set status "error" without info`)
	err = agent.SetStatus(state.Status("vliegkat"), "orville", nil)
	c.Assert(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`)

	statusInfo, err := agent.Status()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(statusInfo.Status, gc.Equals, state.StatusAllocating)
	c.Assert(statusInfo.Message, gc.Equals, "")
	c.Assert(statusInfo.Data, gc.HasLen, 0)

	err = agent.SetStatus(state.StatusIdle, "", nil)
	c.Assert(err, jc.ErrorIsNil)
	statusInfo, err = agent.Status()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(statusInfo.Status, gc.Equals, state.StatusIdle)
	c.Assert(statusInfo.Message, gc.Equals, "")
	c.Assert(statusInfo.Data, gc.HasLen, 0)

	err = agent.SetStatus(state.StatusError, "test-hook failed", map[string]interface{}{
		"foo": "bar",
	})
	c.Assert(err, jc.ErrorIsNil)
	// Agent error is reported as unit error.
	statusInfo, err = s.unit.Status()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(statusInfo.Status, gc.Equals, state.StatusError)
	c.Assert(statusInfo.Message, gc.Equals, "test-hook failed")
	c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{
		"foo": "bar",
	})
	// For agents, error is reported as idle.
	statusInfo, err = agent.Status()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(statusInfo.Status, gc.Equals, state.StatusIdle)
	c.Assert(statusInfo.Message, gc.Equals, "")
	c.Assert(statusInfo.Data, gc.DeepEquals, map[string]interface{}{})
}
Example #8
0
func serviceSetStatus(s *ServiceStatusSetter, args params.SetStatus, getService serviceGetter, isLeaderCheck isLeaderFunc) (params.ErrorResults, error) {
	result := params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Entities)),
	}
	if len(args.Entities) == 0 {
		return result, nil
	}
	canModify, err := s.getCanModify()
	if err != nil {
		return params.ErrorResults{}, err
	}
	for i, arg := range args.Entities {
		leader, err := isLeaderCheck(s.st, arg.Tag)
		if err != nil {
			result.Results[i].Error = ServerError(err)
			continue
		}
		if !leader {
			result.Results[i].Error = ServerError(ErrIsNotLeader)
			continue
		}
		service, err := getService(s.st, arg.Tag)
		if err != nil {
			result.Results[i].Error = ServerError(err)
			continue
		}

		if !canModify(service.Tag()) {
			result.Results[i].Error = ServerError(ErrPerm)
			continue
		}

		if err := service.SetStatus(state.Status(arg.Status), arg.Info, arg.Data); err != nil {
			result.Results[i].Error = ServerError(err)
		}

	}
	return result, nil
}
Example #9
0
func (s *FilesystemStatusSuite) TestSetUnknownStatus(c *gc.C) {
	err := s.filesystem.SetStatus(state.Status("vliegkat"), "orville", nil)
	c.Assert(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`)

	s.checkInitialStatus(c)
}
Example #10
0
func (s *StatusUnitAgentSuite) TestSetUnknownStatus(c *gc.C) {
	err := s.agent.SetStatus(state.Status("vliegkat"), "orville", nil)
	c.Check(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`)

	s.checkInitialStatus(c)
}
Example #11
0
// SetStatus sets the status on the service given by the unit in args if the unit is the leader.
func (s *ServiceStatusSetter) SetStatus(args params.SetStatus) (params.ErrorResults, error) {
	result := params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Entities)),
	}
	if len(args.Entities) == 0 {
		return result, nil
	}

	canModify, err := s.getCanModify()
	if err != nil {
		return params.ErrorResults{}, err
	}

	for i, arg := range args.Entities {

		// TODO(fwereade): the auth is basically nonsense, and basically only
		// works by coincidence. Read carefully.

		// We "know" that arg.Tag is either the calling unit or its service
		// (because getCanModify is authUnitOrService, and we'll fail out if
		// it isn't); and, in practice, it's always going to be the calling
		// unit (because, /sigh, we don't actually use service tags to refer
		// to services in this method).
		tag, err := names.ParseTag(arg.Tag)
		if err != nil {
			result.Results[i].Error = ServerError(err)
			continue
		}
		if !canModify(tag) {
			result.Results[i].Error = ServerError(ErrPerm)
			continue
		}
		unitTag, ok := tag.(names.UnitTag)
		if !ok {
			// No matter what the canModify says, if this entity is not
			// a unit, we say "NO".
			result.Results[i].Error = ServerError(ErrPerm)
			continue
		}
		unitId := unitTag.Id()

		// Now we have the unit, we can get the service that should have been
		// specified in the first place...
		serviceId, err := names.UnitService(unitId)
		if err != nil {
			result.Results[i].Error = ServerError(err)
			continue
		}
		service, err := s.st.Service(serviceId)
		if err != nil {
			result.Results[i].Error = ServerError(err)
			continue
		}

		// ...and set the status, conditional on the unit being (and remaining)
		// service leader.
		checker := s.st.LeadershipChecker()
		token := checker.LeadershipCheck(serviceId, unitId)

		// TODO(fwereade) pass token into SetStatus instead of checking here.
		if err := token.Check(nil); err != nil {
			// TODO(fwereade) this should probably be ErrPerm is certain cases,
			// but I don't think I implemented an exported ErrNotLeader. I
			// should have done, though.
			result.Results[i].Error = ServerError(err)
			continue
		}

		if err := service.SetStatus(state.Status(arg.Status), arg.Info, arg.Data); err != nil {
			result.Results[i].Error = ServerError(err)
		}

	}
	return result, nil
}