func (s *serviceStatusGetterSuite) TestGetUnitStatusIsLeader(c *gc.C) { // If the unit isn't the leader, it can't get it. unit := s.Factory.MakeUnit(c, &factory.UnitParams{Status: &state.StatusInfo{ Status: state.StatusMaintenance, }}) service, err := unit.Service() c.Assert(err, jc.ErrorIsNil) s.State.LeadershipClaimer().ClaimLeadership( service.Name(), unit.Name(), time.Minute) result, err := s.getter.Status(params.Entities{[]params.Entity{{ unit.Tag().String(), }}}) c.Assert(err, jc.ErrorIsNil) c.Assert(result.Results, gc.HasLen, 1) r := result.Results[0] c.Assert(r.Error, gc.IsNil) c.Assert(r.Service.Error, gc.IsNil) c.Assert(r.Service.Status, gc.Equals, params.Status(state.StatusMaintenance)) units := r.Units c.Assert(units, gc.HasLen, 1) status, ok := units[unit.Name()] c.Assert(ok, jc.IsTrue) c.Assert(status.Error, gc.IsNil) c.Assert(status.Status, gc.Equals, params.Status(state.StatusMaintenance)) }
func serviceStatus(s *ServiceStatusGetter, args params.Entities, getService serviceGetter, isLeaderCheck isLeaderFunc) (params.ServiceStatusResults, error) { results := params.ServiceStatusResults{ Results: make([]params.ServiceStatusResult, len(args.Entities)), } canAccess, err := s.getcanAccess() if err != nil { return params.ServiceStatusResults{}, err } for i, serviceUnit := range args.Entities { leader, err := isLeaderCheck(s.st, serviceUnit.Tag) if err != nil { results.Results[i].Error = ServerError(err) continue } if !leader { results.Results[i].Error = ServerError(ErrIsNotLeader) continue } var service StatusService service, err = getService(s.st, serviceUnit.Tag) if err != nil { results.Results[i].Error = ServerError(err) continue } if !canAccess(service.Tag()) { results.Results[i].Error = ServerError(ErrPerm) continue } serviceStatus, unitStatuses, err := service.ServiceAndUnitsStatus() if err != nil { results.Results[i].Service.Error = ServerError(err) results.Results[i].Error = ServerError(err) continue } results.Results[i].Service.Status = params.Status(serviceStatus.Status) results.Results[i].Service.Info = serviceStatus.Message results.Results[i].Service.Data = serviceStatus.Data results.Results[i].Service.Since = serviceStatus.Since results.Results[i].Units = make(map[string]params.StatusResult, len(unitStatuses)) for uTag, r := range unitStatuses { ur := params.StatusResult{ Status: params.Status(r.Status), Info: r.Message, Data: r.Data, Since: r.Since, } results.Results[i].Units[uTag] = ur } } return results, nil }
// 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 }
func storageDetailsFromLegacy(legacy params.LegacyStorageDetails) params.StorageDetails { nowUTC := time.Now().UTC() details := params.StorageDetails{ legacy.StorageTag, legacy.OwnerTag, legacy.Kind, params.EntityStatus{ Status: params.Status(legacy.Status), Since: &nowUTC, }, legacy.Persistent, nil, } if legacy.UnitTag != "" { details.Attachments = map[string]params.StorageAttachmentDetails{ legacy.UnitTag: params.StorageAttachmentDetails{ legacy.StorageTag, legacy.UnitTag, "", // machine is unknown in legacy legacy.Location, }, } } return details }
// makeStatusForEntity creates status information for machines, units. func makeStatusForEntity(agent *api.AgentStatus, getter state.StatusGetter) { statusInfo, err := getter.Status() agent.Err = err agent.Status = params.Status(statusInfo.Status) agent.Info = statusInfo.Message agent.Data = filterStatusData(statusInfo.Data) agent.Since = statusInfo.Since }
// populateStatusFromGetter creates status information for machines, units. func populateStatusFromGetter(agent *params.AgentStatus, getter state.StatusGetter) { statusInfo, err := getter.Status() agent.Err = err agent.Status = params.Status(statusInfo.Status) agent.Info = statusInfo.Message agent.Data = filterStatusData(statusInfo.Data) agent.Since = statusInfo.Since }
// EntityStatusFromState converts a state.StatusInfo into a params.EntityStatus. func EntityStatusFromState(status state.StatusInfo) params.EntityStatus { return params.EntityStatus{ params.Status(status.Status), status.Message, status.Data, status.Since, } }
// SetUnitStatus will set the given status for this unit. func (ctx *HookContext) SetUnitStatus(status jujuc.StatusInfo) error { ctx.hasRunStatusSet = true logger.Debugf("[WORKLOAD-STATUS] %s: %s", status.Status, status.Info) return ctx.unit.SetUnitStatus( params.Status(status.Status), status.Info, status.Data, ) }
func (context *statusContext) processService(service *state.Service) (status params.ServiceStatus) { serviceCharmURL, _ := service.CharmURL() status.Charm = serviceCharmURL.String() status.Exposed = service.IsExposed() status.Life = processLife(service) latestCharm, ok := context.latestCharms[*serviceCharmURL.WithRevision(-1)] if ok && latestCharm != serviceCharmURL.String() { status.CanUpgradeTo = latestCharm } var err error status.Relations, status.SubordinateTo, err = context.processServiceRelations(service) if err != nil { status.Err = err return } networks, err := service.Networks() if err != nil { status.Err = err return } var cons constraints.Value if service.IsPrincipal() { // Only principals can have constraints. cons, err = service.Constraints() if err != nil { status.Err = err return } } // TODO(dimitern): Drop support for this in a follow-up. if len(networks) > 0 || cons.HaveNetworks() { // Only the explicitly requested networks (using "juju deploy // <svc> --networks=...") will be enabled, and altough when // specified, networks constraints will be used for instance // selection, they won't be actually enabled. status.Networks = params.NetworksSpecification{ Enabled: networks, Disabled: append(cons.IncludeNetworks(), cons.ExcludeNetworks()...), } } if service.IsPrincipal() { status.Units = context.processUnits(context.units[service.Name()], serviceCharmURL.String()) serviceStatus, err := service.Status() if err != nil { status.Err = err return } status.Status.Status = params.Status(serviceStatus.Status) status.Status.Info = serviceStatus.Message status.Status.Data = serviceStatus.Data status.Status.Since = serviceStatus.Since status.MeterStatuses = context.processUnitMeterStatuses(context.units[service.Name()]) } return status }
func (s *statusGetterSuite) TestGetMachineStatus(c *gc.C) { machine := s.Factory.MakeMachine(c, nil) result, err := s.getter.Status(params.Entities{[]params.Entity{{ machine.Tag().String(), }}}) c.Assert(err, jc.ErrorIsNil) c.Assert(result.Results, gc.HasLen, 1) status := result.Results[0] c.Assert(status.Error, gc.IsNil) c.Assert(status.Status, gc.Equals, params.Status(state.StatusPending)) }
func checkStatusInfo(c *gc.C, obtained []params.AgentStatus, expected []state.StatusInfo) { c.Assert(len(obtained), gc.Equals, len(expected)) lastTimestamp := int64(0) for i, obtainedInfo := range obtained { thisTimeStamp := obtainedInfo.Since.Unix() c.Assert(thisTimeStamp >= lastTimestamp, jc.IsTrue) lastTimestamp = thisTimeStamp obtainedInfo.Since = nil c.Assert(obtainedInfo.Status, gc.Equals, params.Status(expected[i].Status)) c.Assert(obtainedInfo.Info, gc.Equals, expected[i].Message) } }
func (s *statusGetterSuite) TestGetServiceStatus(c *gc.C) { service := s.Factory.MakeService(c, &factory.ServiceParams{Status: &state.StatusInfo{ Status: state.StatusMaintenance, }}) result, err := s.getter.Status(params.Entities{[]params.Entity{{ service.Tag().String(), }}}) c.Assert(err, jc.ErrorIsNil) c.Assert(result.Results, gc.HasLen, 1) status := result.Results[0] c.Assert(status.Error, gc.IsNil) c.Assert(status.Status, gc.Equals, params.Status(state.StatusMaintenance)) }
func agentStatusFromStatusInfo(s []state.StatusInfo, kind params.HistoryKind) []params.AgentStatus { result := []params.AgentStatus{} for _, v := range s { result = append(result, params.AgentStatus{ Status: params.Status(v.Status), Info: v.Message, Data: v.Data, Since: v.Since, Kind: kind, }) } return result }
func (s *statusGetterSuite) TestGetUnitStatus(c *gc.C) { // The status has to be a valid workload status, because get status // on the unit returns the workload status not the agent status as it // does on a machine. unit := s.Factory.MakeUnit(c, &factory.UnitParams{Status: &state.StatusInfo{ Status: state.StatusMaintenance, }}) result, err := s.getter.Status(params.Entities{[]params.Entity{{ unit.Tag().String(), }}}) c.Assert(err, jc.ErrorIsNil) c.Assert(result.Results, gc.HasLen, 1) status := result.Results[0] c.Assert(status.Error, gc.IsNil) c.Assert(status.Status, gc.Equals, params.Status(state.StatusMaintenance)) }
func (s *statusGetterSuite) TestBulk(c *gc.C) { s.badTag = names.NewMachineTag("42") machine := s.Factory.MakeMachine(c, nil) result, err := s.getter.Status(params.Entities{[]params.Entity{{ s.badTag.String(), }, { machine.Tag().String(), }, { "bad-tag", }}}) c.Assert(err, jc.ErrorIsNil) c.Assert(result.Results, gc.HasLen, 3) c.Assert(result.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized) c.Assert(result.Results[1].Error, gc.IsNil) c.Assert(result.Results[1].Status, gc.Equals, params.Status(state.StatusPending)) c.Assert(result.Results[2].Error, gc.ErrorMatches, `"bad-tag" is not a valid tag`) }
func (s *StatusGetter) getEntityStatus(tag names.Tag) params.StatusResult { var result params.StatusResult entity, err := s.st.FindEntity(tag) if err != nil { result.Error = ServerError(err) return result } switch getter := entity.(type) { case state.StatusGetter: statusInfo, err := getter.Status() result.Status = params.Status(statusInfo.Status) result.Info = statusInfo.Message result.Data = statusInfo.Data result.Since = statusInfo.Since result.Error = ServerError(err) default: result.Error = ServerError(NotSupportedError(tag, fmt.Sprintf("getting status, %T", getter))) } return result }
// MachinesWithTransientErrors returns status data for machines with provisioning // errors which are transient. func (p *ProvisionerAPI) MachinesWithTransientErrors() (params.StatusResults, error) { var results params.StatusResults canAccessFunc, err := p.getAuthFunc() if err != nil { return results, err } // TODO (wallyworld) - add state.State API for more efficient machines query machines, err := p.st.AllMachines() if err != nil { return results, err } for _, machine := range machines { if !canAccessFunc(machine.Tag()) { continue } if _, provisionedErr := machine.InstanceId(); provisionedErr == nil { // Machine may have been provisioned but machiner hasn't set the // status to Started yet. continue } var result params.StatusResult statusInfo, err := machine.Status() if err != nil { continue } result.Status = params.Status(statusInfo.Status) result.Info = statusInfo.Message result.Data = statusInfo.Data if result.Status != params.StatusError { continue } // Transient errors are marked as such in the status data. if transient, ok := result.Data["transient"].(bool); !ok || !transient { continue } result.Id = machine.Id() result.Life = params.Life(machine.Life().String()) results.Results = append(results.Results, result) } return results, nil }
// SetServiceStatus will set the given status to the service to which this // unit's belong, only if this unit is the leader. func (ctx *HookContext) SetServiceStatus(status jujuc.StatusInfo) error { logger.Debugf("[SERVICE-STATUS] %s: %s", status.Status, status.Info) isLeader, err := ctx.IsLeader() if err != nil { return errors.Annotatef(err, "cannot determine leadership") } if !isLeader { return ErrIsNotLeader } service, err := ctx.unit.Service() if err != nil { return errors.Trace(err) } return service.SetStatus( ctx.unit.Name(), params.Status(status.Status), status.Info, status.Data, ) }
func (s *UnitSuite) TestGetSetStatusWhileAlive(c *gc.C) { err := s.unit.SetStatus(params.StatusError, "", nil) c.Assert(err, gc.ErrorMatches, `cannot set status "error" without info`) err = s.unit.SetStatus(params.StatusPending, "", nil) c.Assert(err, gc.ErrorMatches, `cannot set status "pending"`) err = s.unit.SetStatus(params.StatusDown, "", nil) c.Assert(err, gc.ErrorMatches, `cannot set status "down"`) err = s.unit.SetStatus(params.Status("vliegkat"), "orville", nil) c.Assert(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`) status, info, data, err := s.unit.Status() c.Assert(err, gc.IsNil) c.Assert(status, gc.Equals, params.StatusPending) c.Assert(info, gc.Equals, "") c.Assert(data, gc.HasLen, 0) err = s.unit.SetStatus(params.StatusStarted, "", nil) c.Assert(err, gc.IsNil) status, info, data, err = s.unit.Status() c.Assert(err, gc.IsNil) c.Assert(status, gc.Equals, params.StatusStarted) c.Assert(info, gc.Equals, "") c.Assert(data, gc.HasLen, 0) err = s.unit.SetStatus(params.StatusError, "test-hook failed", params.StatusData{ "foo": "bar", }) c.Assert(err, gc.IsNil) status, info, data, err = s.unit.Status() c.Assert(err, gc.IsNil) c.Assert(status, gc.Equals, params.StatusError) c.Assert(info, gc.Equals, "test-hook failed") c.Assert(data, gc.DeepEquals, params.StatusData{ "foo": "bar", }) }
func (f *summaryFormatter) printStateToCount(m map[params.Status]int) { for _, status := range common.SortStringsNaturally(stringKeysFromMap(m)) { numInStatus := m[params.Status(status)] f.delimitValuesWithTabs(status+":", fmt.Sprintf(" %d ", numInStatus)) } }
// Status returns the status of the Service for each given Unit tag. func (s *ServiceStatusGetter) Status(args params.Entities) (params.ServiceStatusResults, error) { result := params.ServiceStatusResults{ Results: make([]params.ServiceStatusResult, len(args.Entities)), } canAccess, err := s.getCanAccess() if err != nil { return params.ServiceStatusResults{}, err } for i, arg := range args.Entities { // TODO(fwereade): the auth is basically nonsense, and basically only // works by coincidence (and is happening at the wrong layer anyway). // Read carefully. // We "know" that arg.Tag is either the calling unit or its service // (because getCanAccess 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 !canAccess(tag) { result.Results[i].Error = ServerError(ErrPerm) continue } unitTag, ok := tag.(names.UnitTag) if !ok { // No matter what the canAccess 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 } // ...so we can check the unit's service leadership... checker := s.st.LeadershipChecker() token := checker.LeadershipCheck(serviceId, unitId) 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 } // ...and collect the results. serviceStatus, unitStatuses, err := service.ServiceAndUnitsStatus() if err != nil { result.Results[i].Service.Error = ServerError(err) result.Results[i].Error = ServerError(err) continue } result.Results[i].Service.Status = params.Status(serviceStatus.Status) result.Results[i].Service.Info = serviceStatus.Message result.Results[i].Service.Data = serviceStatus.Data result.Results[i].Service.Since = serviceStatus.Since result.Results[i].Units = make(map[string]params.StatusResult, len(unitStatuses)) for uTag, r := range unitStatuses { ur := params.StatusResult{ Status: params.Status(r.Status), Info: r.Message, Data: r.Data, Since: r.Since, } result.Results[i].Units[uTag] = ur } } return result, nil }