// SetInstanceStatus updates the instance status for each given // entity. Only machine tags are accepted. func (a *InstancePollerAPI) SetInstanceStatus(args params.SetStatus) (params.ErrorResults, error) { result := params.ErrorResults{ Results: make([]params.ErrorResult, len(args.Entities)), } canAccess, err := a.accessMachine() if err != nil { return result, err } for i, arg := range args.Entities { machine, err := a.getOneMachine(arg.Tag, canAccess) if err == nil { now := a.clock.Now() s := status.StatusInfo{ Status: status.Status(arg.Status), Message: arg.Info, Data: arg.Data, Since: &now, } err = machine.SetInstanceStatus(s) if status.Status(arg.Status) == status.ProvisioningError { s.Status = status.Error if err == nil { err = machine.SetStatus(s) } } } result.Results[i].Error = common.ServerError(err) } return result, nil }
func (s *InstancePollerSuite) TestSetInstanceStatusFailure(c *gc.C) { s.st.SetErrors( errors.New("pow!"), // m1 := FindEntity("1") nil, // m2 := FindEntity("2") errors.New("FAIL"), // m2.SetInstanceStatus() errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved) ) s.st.SetMachineInfo(c, machineInfo{id: "1", instanceStatus: statusInfo("foo")}) s.st.SetMachineInfo(c, machineInfo{id: "2", instanceStatus: statusInfo("")}) result, err := s.api.SetInstanceStatus(params.SetStatus{ Entities: []params.EntityStatusArgs{ {Tag: "machine-1", Status: status.Status("new")}, {Tag: "machine-2", Status: status.Status("invalid")}, {Tag: "machine-3", Status: status.Status("")}, }}, ) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, s.machineErrorResults) s.st.CheckFindEntityCall(c, 0, "1") s.st.CheckFindEntityCall(c, 1, "2") s.st.CheckCall(c, 2, "SetInstanceStatus", status.Status("invalid")) s.st.CheckFindEntityCall(c, 3, "3") }
func (s *InstancePollerSuite) TestInstanceStatusSuccess(c *gc.C) { s.st.SetMachineInfo(c, machineInfo{id: "1", instanceStatus: statusInfo("foo")}) s.st.SetMachineInfo(c, machineInfo{id: "2", instanceStatus: statusInfo("")}) result, err := s.api.InstanceStatus(s.mixedEntities) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, params.StatusResults{ Results: []params.StatusResult{ {Status: status.Status("foo")}, {Status: status.Status("")}, {Error: apiservertesting.NotFoundError("machine 42")}, {Error: apiservertesting.ServerError(`"service-unknown" is not a valid machine tag`)}, {Error: apiservertesting.ServerError(`"invalid-tag" is not a valid tag`)}, {Error: apiservertesting.ServerError(`"unit-missing-1" is not a valid machine tag`)}, {Error: apiservertesting.ServerError(`"" is not a valid tag`)}, {Error: apiservertesting.ServerError(`"42" is not a valid tag`)}, }, }, ) s.st.CheckFindEntityCall(c, 0, "1") s.st.CheckCall(c, 1, "InstanceStatus") s.st.CheckFindEntityCall(c, 2, "2") s.st.CheckCall(c, 3, "InstanceStatus") s.st.CheckFindEntityCall(c, 4, "42") }
// SetInstanceStatus updates the instance status for each given // entity. Only machine tags are accepted. func (p *ProvisionerAPI) SetInstanceStatus(args params.SetStatus) (params.ErrorResults, error) { result := params.ErrorResults{ Results: make([]params.ErrorResult, len(args.Entities)), } canAccess, err := p.getAuthFunc() if err != nil { logger.Errorf("failed to get an authorisation function: %v", err) return result, errors.Trace(err) } for i, arg := range args.Entities { mTag, err := names.ParseMachineTag(arg.Tag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } machine, err := p.getMachine(canAccess, mTag) if err == nil { // TODO(perrito666) 2016-05-02 lp:1558657 now := time.Now() s := status.StatusInfo{ Status: status.Status(arg.Status), Message: arg.Info, Data: arg.Data, Since: &now, } err = machine.SetInstanceStatus(s) } result.Results[i].Error = common.ServerError(err) } return result, nil }
// SetStatus sets the status of each given entity. func (s *StatusSetter) 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 } // TODO(perrito666) 2016-05-02 lp:1558657 now := time.Now() for i, arg := range args.Entities { tag, err := names.ParseTag(arg.Tag) if err != nil { result.Results[i].Error = ServerError(err) continue } err = ErrPerm if canModify(tag) { err = s.setEntityStatus(tag, status.Status(arg.Status), arg.Info, arg.Data, &now) } result.Results[i].Error = ServerError(err) } return result, nil }
// makeStatusDoc assumes status is non-nil. func (i *importer) makeStatusDoc(statusVal description.Status) statusDoc { return statusDoc{ Status: status.Status(statusVal.Value()), StatusInfo: statusVal.Message(), StatusData: statusVal.Data(), Updated: statusVal.Updated().UnixNano(), } }
// SetUnitStatus will set the given status for this unit. func (ctx *HookContext) SetUnitStatus(unitStatus jujuc.StatusInfo) error { ctx.hasRunStatusSet = true logger.Tracef("[WORKLOAD-STATUS] %s: %s", unitStatus.Status, unitStatus.Info) return ctx.unit.SetUnitStatus( status.Status(unitStatus.Status), unitStatus.Info, unitStatus.Data, ) }
func (s *InstancePollerSuite) TestSetInstanceStatusSuccess(c *gc.C) { s.st.SetMachineInfo(c, machineInfo{id: "1", instanceStatus: statusInfo("foo")}) s.st.SetMachineInfo(c, machineInfo{id: "2", instanceStatus: statusInfo("")}) result, err := s.api.SetInstanceStatus(params.SetStatus{ Entities: []params.EntityStatusArgs{ {Tag: "machine-1", Status: ""}, {Tag: "machine-2", Status: "new status"}, {Tag: "machine-42", Status: ""}, {Tag: "application-unknown", Status: ""}, {Tag: "invalid-tag", Status: ""}, {Tag: "unit-missing-1", Status: ""}, {Tag: "", Status: ""}, {Tag: "42", Status: ""}, }}, ) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, s.mixedErrorResults) now := s.clock.Now() s.st.CheckFindEntityCall(c, 0, "1") s.st.CheckCall(c, 1, "SetInstanceStatus", status.StatusInfo{Status: status.Status(""), Since: &now}) s.st.CheckFindEntityCall(c, 2, "2") s.st.CheckCall(c, 3, "SetInstanceStatus", status.StatusInfo{Status: status.Status("new status"), Since: &now}) s.st.CheckFindEntityCall(c, 4, "42") // Ensure machines were updated. machine, err := s.st.Machine("1") c.Assert(err, jc.ErrorIsNil) // TODO (perrito666) there should not be an empty StatusInfo here, // this is certainly a smell. setStatus, err := machine.InstanceStatus() c.Assert(err, jc.ErrorIsNil) setStatus.Since = nil c.Assert(setStatus, gc.DeepEquals, status.StatusInfo{}) machine, err = s.st.Machine("2") c.Assert(err, jc.ErrorIsNil) setStatus, err = machine.InstanceStatus() c.Assert(err, jc.ErrorIsNil) setStatus.Since = nil c.Assert(setStatus, gc.DeepEquals, status.StatusInfo{Status: "new status"}) }
// pollInstanceInfo checks the current provider addresses and status // for the given machine's instance, and sets them on the machine if they've changed. func pollInstanceInfo(context machineContext, m machine) (instInfo instanceInfo, err error) { instInfo = instanceInfo{} instId, err := m.InstanceId() // We can't ask the machine for its addresses if it isn't provisioned yet. if params.IsCodeNotProvisioned(err) { return instanceInfo{}, err } if err != nil { return instanceInfo{}, errors.Annotate(err, "cannot get machine's instance id") } instInfo, err = context.instanceInfo(instId) if err != nil { // TODO (anastasiamac 2016-02-01) This does not look like it needs to be removed now. if params.IsCodeNotImplemented(err) { return instanceInfo{}, err } logger.Warningf("cannot get instance info for instance %q: %v", instId, err) return instInfo, nil } if instStat, err := m.InstanceStatus(); err != nil { // This should never occur since the machine is provisioned. // But just in case, we reset polled status so we try again next time. logger.Warningf("cannot get current instance status for machine %v: %v", m.Id(), err) instInfo.status = instance.InstanceStatus{status.Unknown, ""} } else { // TODO(perrito666) add status validation. currentInstStatus := instance.InstanceStatus{ Status: status.Status(instStat.Status), Message: instStat.Info, } if instInfo.status != currentInstStatus { logger.Infof("machine %q instance status changed from %q to %q", m.Id(), currentInstStatus, instInfo.status) if err = m.SetInstanceStatus(instInfo.status.Status, instInfo.status.Message, nil); err != nil { logger.Errorf("cannot set instance status on %q: %v", m, err) return instanceInfo{}, err } } } if m.Life() != params.Dead { providerAddresses, err := m.ProviderAddresses() if err != nil { return instanceInfo{}, err } if !addressesEqual(providerAddresses, instInfo.addresses) { logger.Infof("machine %q has new addresses: %v", m.Id(), instInfo.addresses) if err := m.SetProviderAddresses(instInfo.addresses...); err != nil { logger.Errorf("cannot set addresses on %q: %v", m, err) return instanceInfo{}, err } } } return instInfo, nil }
func (sf *statusFormatter) updateUnitStatusInfo(unit *params.UnitStatus, applicationName string) { // TODO(perrito66) add status validation. if status.Status(unit.WorkloadStatus.Status) == status.Error { if relation, ok := sf.relations[getRelationIdFromData(unit)]; ok { // Append the details of the other endpoint on to the status info string. if ep, ok := findOtherEndpoint(relation.Endpoints, applicationName); ok { unit.WorkloadStatus.Info = unit.WorkloadStatus.Info + " for " + ep.String() } } } }
func (s *ServiceStatusSuite) TestSetUnknownStatus(c *gc.C) { now := testing.ZeroTime() sInfo := status.StatusInfo{ Status: status.Status("vliegkat"), Message: "orville", Since: &now, } err := s.service.SetStatus(sInfo) c.Check(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`) s.checkInitialStatus(c) }
func (s *MachineStatusSuite) TestSetUnknownStatus(c *gc.C) { now := time.Now() sInfo := status.StatusInfo{ Status: status.Status("vliegkat"), Message: "orville", Since: &now, } err := s.machine.SetStatus(sInfo) c.Assert(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`) s.checkInitialStatus(c) }
func (sf *statusFormatter) getServiceStatusInfo(service params.ApplicationStatus) statusInfoContents { // TODO(perrito66) add status validation. info := statusInfoContents{ Err: service.Status.Err, Current: status.Status(service.Status.Status), Message: service.Status.Info, Version: service.Status.Version, } if service.Status.Since != nil { info.Since = common.FormatTime(service.Status.Since, sf.isoTime) } return info }
func checkStatusInfo(c *gc.C, obtained []params.DetailedStatus, expected []status.StatusInfo) { c.Assert(len(obtained), gc.Equals, len(expected)) lastTimestamp := int64(0) for i, obtainedInfo := range obtained { c.Logf("Checking status %q with info %q", obtainedInfo.Status, obtainedInfo.Info) thisTimeStamp := obtainedInfo.Since.Unix() c.Assert(thisTimeStamp >= lastTimestamp, jc.IsTrue) lastTimestamp = thisTimeStamp obtainedInfo.Since = nil c.Assert(obtainedInfo.Status, gc.Equals, status.Status(expected[i].Status)) c.Assert(obtainedInfo.Info, gc.Equals, expected[i].Message) } }
func (sf *statusFormatter) getAgentStatusInfo(unit params.UnitStatus) statusInfoContents { // TODO(perrito66) add status validation. info := statusInfoContents{ Err: unit.AgentStatus.Err, Current: status.Status(unit.AgentStatus.Status), Message: unit.AgentStatus.Info, Version: unit.AgentStatus.Version, } if unit.AgentStatus.Since != nil { info.Since = common.FormatTime(unit.AgentStatus.Since, sf.isoTime) } return info }
func (s *StatusModelSuite) TestUnitAgentStatusDocValidation(c *gc.C) { unit := s.Factory.MakeUnit(c, nil) for i, test := range []struct { status status.Status info string err string }{{ status: status.StatusPending, err: `cannot set invalid status "pending"`, }, { status: status.StatusDown, err: `cannot set invalid status "down"`, }, { status: status.StatusStarted, err: `cannot set invalid status "started"`, }, { status: status.StatusStopped, err: `cannot set invalid status "stopped"`, }, { status: status.StatusAllocating, err: `cannot set status "allocating"`, }, { status: status.StatusAllocating, info: "any message", err: `cannot set status "allocating"`, }, { status: status.StatusLost, err: `cannot set status "lost"`, }, { status: status.StatusLost, info: "any message", err: `cannot set status "lost"`, }, { status: status.StatusError, err: `cannot set status "error" without info`, }, { status: status.StatusError, info: "some error info", }, { status: status.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) } } }
func (s *InstancePollerSuite) TestSetInstanceStatusSuccess(c *gc.C) { s.st.SetMachineInfo(c, machineInfo{id: "1", instanceStatus: statusInfo("foo")}) s.st.SetMachineInfo(c, machineInfo{id: "2", instanceStatus: statusInfo("")}) result, err := s.api.SetInstanceStatus(params.SetStatus{ Entities: []params.EntityStatusArgs{ {Tag: "machine-1", Status: status.Status("")}, {Tag: "machine-2", Status: status.Status("new status")}, {Tag: "machine-42", Status: status.Status("")}, {Tag: "service-unknown", Status: status.Status("")}, {Tag: "invalid-tag", Status: status.Status("")}, {Tag: "unit-missing-1", Status: status.Status("")}, {Tag: "", Status: status.Status("")}, {Tag: "42", Status: status.Status("")}, }}, ) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, s.mixedErrorResults) s.st.CheckFindEntityCall(c, 0, "1") s.st.CheckCall(c, 1, "SetInstanceStatus", status.Status("")) s.st.CheckFindEntityCall(c, 2, "2") s.st.CheckCall(c, 3, "SetInstanceStatus", status.Status("new status")) s.st.CheckFindEntityCall(c, 4, "42") // Ensure machines were updated. machine, err := s.st.Machine("1") c.Assert(err, jc.ErrorIsNil) setStatus, err := machine.InstanceStatus() c.Assert(err, jc.ErrorIsNil) c.Assert(setStatus, gc.DeepEquals, status.StatusInfo{}) machine, err = s.st.Machine("2") c.Assert(err, jc.ErrorIsNil) setStatus, err = machine.InstanceStatus() c.Assert(err, jc.ErrorIsNil) c.Assert(setStatus, gc.DeepEquals, status.StatusInfo{Status: "new status"}) }
func (sf *statusFormatter) getStatusInfoContents(inst params.DetailedStatus) statusInfoContents { // TODO(perrito66) add status validation. info := statusInfoContents{ Err: inst.Err, Current: status.Status(inst.Status), Message: inst.Info, Version: inst.Version, Life: inst.Life, } if inst.Since != nil { info.Since = common.FormatTime(inst.Since, sf.isoTime) } return info }
func matchAgentStatus(patterns []string, agentStatus status.Status) (bool, bool, error) { oneValidStatus := false for _, p := range patterns { // If the pattern isn't a known status, ignore it. ps := status.Status(p) if !ps.KnownAgentStatus() { continue } oneValidStatus = true if agentStatus.Matches(ps) { return true, true, nil } } return false, oneValidStatus, nil }
// StatusHistory retrieves the last <size> results of // <kind:combined|agent|workload|machine|machineinstance|container|containerinstance> status // for <name> unit func (c *Client) StatusHistory(kind status.HistoryKind, tag names.Tag, filter status.StatusHistoryFilter) (status.History, error) { var results params.StatusHistoryResults args := params.StatusHistoryRequest{ Kind: string(kind), Filter: params.StatusHistoryFilter{ Size: filter.Size, Date: filter.Date, Delta: filter.Delta, }, Tag: tag.String(), } bulkArgs := params.StatusHistoryRequests{Requests: []params.StatusHistoryRequest{args}} err := c.facade.FacadeCall("StatusHistory", bulkArgs, &results) if err != nil { return status.History{}, errors.Trace(err) } if len(results.Results) != 1 { return status.History{}, errors.Errorf("expected 1 result got %d", len(results.Results)) } if results.Results[0].Error != nil { return status.History{}, errors.Annotatef(results.Results[0].Error, "while processing the request") } history := make(status.History, len(results.Results[0].History.Statuses)) if results.Results[0].History.Error != nil { return status.History{}, results.Results[0].History.Error } for i, h := range results.Results[0].History.Statuses { history[i] = status.DetailedStatus{ Status: status.Status(h.Status), Info: h.Info, Data: h.Data, Since: h.Since, Kind: status.HistoryKind(h.Kind), Version: h.Version, // TODO(perrito666) make sure these are still used. Life: h.Life, Err: h.Err, } // TODO(perrito666) https://launchpad.net/bugs/1577589 if !history[i].Kind.Valid() { logger.Errorf("history returned an unknown status kind %q", h.Kind) } } return history, nil }
func matchWorkloadStatus(patterns []string, workloadStatus status.Status, agentStatus status.Status) (bool, bool, error) { oneValidStatus := false for _, p := range patterns { // If the pattern isn't a known status, ignore it. ps := status.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 != status.Error && workloadStatus.WorkloadMatches(ps) { return true, true, nil } } return false, oneValidStatus, nil }
func (inst *dummyInstance) Status() instance.InstanceStatus { inst.mu.Lock() defer inst.mu.Unlock() // TODO(perrito666) add a provider status -> juju status mapping. jujuStatus := status.StatusPending if inst.status != "" { dummyStatus := status.Status(inst.status) if dummyStatus.KnownInstanceStatus() { jujuStatus = dummyStatus } } return instance.InstanceStatus{ Status: jujuStatus, Message: inst.status, } }
// InstanceStatus returns the status of the provider instance. func (m *Machine) InstanceStatus() (status.Status, string, error) { var results params.StatusResults args := params.Entities{Entities: []params.Entity{ {Tag: m.tag.String()}, }} err := m.st.facade.FacadeCall("InstanceStatus", args, &results) if err != nil { return "", "", err } if len(results.Results) != 1 { return "", "", fmt.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return "", "", result.Error } // TODO(perrito666) add status validation. return status.Status(result.Status), result.Info, nil }
func (i *importer) importStatusHistory(globalKey string, history []description.Status) error { docs := make([]interface{}, len(history)) for i, statusVal := range history { docs[i] = historicalStatusDoc{ GlobalKey: globalKey, Status: status.Status(statusVal.Value()), StatusInfo: statusVal.Message(), StatusData: statusVal.Data(), Updated: statusVal.Updated().UnixNano(), } } statusHistory, closer := i.st.getCollection(statusesHistoryC) defer closer() if err := statusHistory.Writeable().Insert(docs...); err != nil { return errors.Trace(err) } return nil }
// 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 = status.Status(statusInfo.Status) result.Info = statusInfo.Message result.Data = statusInfo.Data if result.Status != status.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 }
// SetApplicationStatus will set the given status to the service to which this // unit's belong, only if this unit is the leader. func (ctx *HookContext) SetApplicationStatus(serviceStatus jujuc.StatusInfo) error { logger.Tracef("[APPLICATION-STATUS] %s: %s", serviceStatus.Status, serviceStatus.Info) isLeader, err := ctx.IsLeader() if err != nil { return errors.Annotatef(err, "cannot determine leadership") } if !isLeader { return ErrIsNotLeader } service, err := ctx.unit.Application() if err != nil { return errors.Trace(err) } return service.SetStatus( ctx.unit.Name(), status.Status(serviceStatus.Status), serviceStatus.Info, serviceStatus.Data, ) }
func (s *MachineStatusSuite) TestSetUnknownStatus(c *gc.C) { err := s.machine.SetStatus(status.Status("vliegkat"), "orville", nil) c.Assert(err, gc.ErrorMatches, `cannot set invalid status "vliegkat"`) s.checkInitialStatus(c) }
// 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.UnitApplication(unitId) if err != nil { result.Results[i].Error = ServerError(err) continue } service, err := s.st.Application(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 } // TODO(perrito666) 2016-05-02 lp:1558657 now := time.Now() sInfo := status.StatusInfo{ Status: status.Status(arg.Status), Message: arg.Info, Data: arg.Data, Since: &now, } if err := service.SetStatus(sInfo); err != nil { result.Results[i].Error = ServerError(err) } } return result, nil }
func (f *summaryFormatter) printStateToCount(m map[status.Status]int) { for _, stateToCount := range common.SortStringsNaturally(stringKeysFromMap(m)) { numInStatus := m[status.Status(stateToCount)] f.delimitValuesWithTabs(stateToCount+":", fmt.Sprintf(" %d ", numInStatus)) } }
func (i *importer) machine(m description.Machine) error { // Import this machine, then import its containers. i.logger.Debugf("importing machine %s", m.Id()) // 1. construct a machineDoc mdoc, err := i.makeMachineDoc(m) if err != nil { return errors.Annotatef(err, "machine %s", m.Id()) } // 2. construct enough MachineTemplate to pass into 'insertNewMachineOps' // - adds constraints doc // - adds status doc // - adds requested network doc // - adds machine block devices doc // TODO: consider filesystems and volumes mStatus := m.Status() if mStatus == nil { return errors.NotValidf("missing status") } machineStatusDoc := statusDoc{ ModelUUID: i.st.ModelUUID(), Status: status.Status(mStatus.Value()), StatusInfo: mStatus.Message(), StatusData: mStatus.Data(), Updated: mStatus.Updated().UnixNano(), } // XXX(mjs) - this needs to be included in the serialized model // (a card exists for the work). Fake it for now. instanceStatusDoc := statusDoc{ ModelUUID: i.st.ModelUUID(), Status: status.StatusStarted, } cons := i.constraints(m.Constraints()) networks := []string{} prereqOps, machineOp := i.st.baseNewMachineOps(mdoc, machineStatusDoc, instanceStatusDoc, cons, networks) // 3. create op for adding in instance data if instance := m.Instance(); instance != nil { prereqOps = append(prereqOps, i.machineInstanceOp(mdoc, instance)) } if parentId := ParentId(mdoc.Id); parentId != "" { prereqOps = append(prereqOps, // Update containers record for host machine. i.st.addChildToContainerRefOp(parentId, mdoc.Id), ) } // insertNewContainerRefOp adds an empty doc into the containerRefsC // collection for the machine being added. prereqOps = append(prereqOps, i.st.insertNewContainerRefOp(mdoc.Id)) // 4. gather prereqs and machine op, run ops. ops := append(prereqOps, machineOp) // 5. add any ops that we may need to add the opened ports information. ops = append(ops, i.machinePortsOps(m)...) if err := i.st.runTransaction(ops); err != nil { return errors.Trace(err) } machine := newMachine(i.st, mdoc) if annotations := m.Annotations(); len(annotations) > 0 { if err := i.st.SetAnnotations(machine, annotations); err != nil { return errors.Trace(err) } } if err := i.importStatusHistory(machine.globalKey(), m.StatusHistory()); err != nil { return errors.Trace(err) } // Now that this machine exists in the database, process each of the // containers in this machine. for _, container := range m.Containers() { if err := i.machine(container); err != nil { return errors.Annotate(err, container.Id()) } } return nil }