func (s *HardwareSuite) TestParseHardware(c *gc.C) { for i, t := range parseHardwareTests { c.Logf("test %d: %s", i, t.summary) hwc, err := instance.ParseHardware(t.args...) if t.err == "" { c.Assert(err, gc.IsNil) } else { c.Assert(err, gc.ErrorMatches, t.err) continue } cons1, err := instance.ParseHardware(hwc.String()) c.Assert(err, gc.IsNil) c.Assert(cons1, gc.DeepEquals, hwc) } }
// FormatMachineTabular returns a tabular summary of machine func FormatMachineTabular(value interface{}) ([]byte, error) { fs, valueConverted := value.(formattedMachineStatus) if !valueConverted { return nil, errors.Errorf("expected value of type %T, got %T", fs, value) } var out bytes.Buffer // To format things into columns. tw := tabwriter.NewWriter(&out, 0, 1, 1, ' ', 0) p := func(values ...interface{}) { for _, v := range values { fmt.Fprintf(tw, "%s\t", v) } fmt.Fprintln(tw) } p("\n[Machines]") p("ID\tSTATE\tDNS\tINS-ID\tSERIES\tAZ") for _, name := range common.SortStringsNaturally(stringKeysFromMap(fs.Machines)) { m := fs.Machines[name] // We want to display availability zone so extract from hardware info". hw, err := instance.ParseHardware(m.Hardware) if err != nil { logger.Warningf("invalid hardware info %s for machine %v", m.Hardware, m) } az := "" if hw.AvailabilityZone != nil { az = *hw.AvailabilityZone } p(m.Id, m.AgentState, m.DNSName, m.InstanceId, m.Series, az) } tw.Flush() return out.Bytes(), nil }
func (manager *containerManager) CreateContainer( machineConfig *cloudinit.MachineConfig, series string, network *container.NetworkConfig, ) (instance.Instance, *instance.HardwareCharacteristics, error) { name := names.NewMachineTag(machineConfig.MachineId).String() if manager.name != "" { name = fmt.Sprintf("%s-%s", manager.name, name) } // Note here that the kvmObjectFacotry only returns a valid container // object, and doesn't actually construct the underlying kvm container on // disk. kvmContainer := KvmObjectFactory.New(name) // Create the cloud-init. directory, err := container.NewDirectory(name) if err != nil { return nil, nil, fmt.Errorf("failed to create container directory: %v", err) } logger.Tracef("write cloud-init") userDataFilename, err := container.WriteUserData(machineConfig, directory) if err != nil { return nil, nil, errors.LoggedErrorf(logger, "failed to write user data: %v", err) } // Create the container. startParams = ParseConstraintsToStartParams(machineConfig.Constraints) startParams.Arch = version.Current.Arch startParams.Series = series startParams.Network = network startParams.UserDataFile = userDataFilename // If the Simplestream requested is anything but released, update // our StartParams to request it. if machineConfig.ImageStream != imagemetadata.ReleasedStream { startParams.ImageDownloadUrl = imagemetadata.UbuntuCloudImagesURL + "/" + machineConfig.ImageStream } var hardware instance.HardwareCharacteristics hardware, err = instance.ParseHardware( fmt.Sprintf("arch=%s mem=%vM root-disk=%vG cpu-cores=%v", startParams.Arch, startParams.Memory, startParams.RootDisk, startParams.CpuCores)) if err != nil { logger.Warningf("failed to parse hardware: %v", err) } logger.Tracef("create the container, constraints: %v", machineConfig.Constraints) if err := kvmContainer.Start(startParams); err != nil { return nil, nil, errors.LoggedErrorf(logger, "kvm container creation failed: %v", err) } logger.Tracef("kvm container created") return &kvmInstance{kvmContainer, name}, &hardware, nil }
func (ts *parseHardwareTestSpec) check(c *gc.C) { hwc, err := instance.ParseHardware(ts.args...) // Check the spec'ed error condition first. if ts.err != "" { c.Check(err, gc.ErrorMatches, ts.err) // We expected an error so we don't worry about checking hwc. return } else if !c.Check(err, jc.ErrorIsNil) { // We got an unexpected error so we don't worry about checking hwc. return } // The error condition matched so we check hwc. cons1, err := instance.ParseHardware(hwc.String()) if !c.Check(err, jc.ErrorIsNil) { // Parsing didn't work so we don't worry about checking hwc. return } // Compare the round-tripped HWC. c.Check(cons1, gc.DeepEquals, hwc) }
func printMachine(w output.Wrapper, m machineStatus) { // We want to display availability zone so extract from hardware info". hw, err := instance.ParseHardware(m.Hardware) if err != nil { logger.Warningf("invalid hardware info %s for machine %v", m.Hardware, m) } az := "" if hw.AvailabilityZone != nil { az = *hw.AvailabilityZone } w.Print(m.Id) w.PrintStatus(m.JujuStatus.Current) w.Println(m.DNSName, m.InstanceId, m.Series, az) for _, name := range utils.SortStringsNaturally(stringKeysFromMap(m.Containers)) { printMachine(w, m.Containers[name]) } }
// getHardwareCharacteristics compiles hardware-related details about // the given instance and relative to the provided spec and returns it. func (env *environ) getHardwareCharacteristics(args environs.StartInstanceParams, inst *environInstance) *instance.HardwareCharacteristics { raw := inst.raw.Hardware archStr := raw.Architecture if archStr == "unknown" || !arch.IsSupportedArch(archStr) { // TODO(ericsnow) This special-case should be improved. archStr = arch.HostArch() } hwc, err := instance.ParseHardware( "arch="+archStr, fmt.Sprintf("cpu-cores=%d", raw.NumCores), fmt.Sprintf("mem=%dM", raw.MemoryMB), //"root-disk=", //"tags=", ) if err != nil { logger.Errorf("unexpected problem parsing hardware info: %v", err) // Keep moving... } return &hwc }
// FormatTabular returns a tabular summary of machines, services, and // units. Any subordinate items are indented by two spaces beneath // their superior. func FormatTabular(value interface{}) ([]byte, error) { fs, valueConverted := value.(formattedStatus) if !valueConverted { return nil, errors.Errorf("expected value of type %T, got %T", fs, value) } var out bytes.Buffer // To format things into columns. tw := tabwriter.NewWriter(&out, 0, 1, 1, ' ', 0) p := func(values ...interface{}) { for _, v := range values { fmt.Fprintf(tw, "%s\t", v) } fmt.Fprintln(tw) } if envStatus := fs.ModelStatus; envStatus != nil { p("[Model]") if envStatus.AvailableVersion != "" { p("UPGRADE-AVAILABLE") p(envStatus.AvailableVersion) } p() tw.Flush() } units := make(map[string]unitStatus) relations := newRelationFormatter() p("[Services]") p("NAME\tSTATUS\tEXPOSED\tCHARM") for _, svcName := range common.SortStringsNaturally(stringKeysFromMap(fs.Services)) { svc := fs.Services[svcName] for un, u := range svc.Units { units[un] = u } subs := set.NewStrings(svc.SubordinateTo...) p(svcName, svc.StatusInfo.Current, fmt.Sprintf("%t", svc.Exposed), svc.Charm) for relType, relatedUnits := range svc.Relations { for _, related := range relatedUnits { relations.add(related, svcName, relType, subs.Contains(related)) } } } if relations.len() > 0 { p() p("[Relations]") p("SERVICE1\tSERVICE2\tRELATION\tTYPE") for _, k := range relations.sorted() { r := relations.get(k) if r != nil { p(r.service1, r.service2, r.relation, r.relationType()) } } } tw.Flush() pUnit := func(name string, u unitStatus, level int) { message := u.WorkloadStatusInfo.Message agentDoing := agentDoing(u.AgentStatusInfo) if agentDoing != "" { message = fmt.Sprintf("(%s) %s", agentDoing, message) } p( indent("", level*2, name), u.WorkloadStatusInfo.Current, u.AgentStatusInfo.Current, u.AgentStatusInfo.Version, u.Machine, strings.Join(u.OpenedPorts, ","), u.PublicAddress, message, ) } header := []string{"ID", "WORKLOAD-STATE", "AGENT-STATE", "VERSION", "MACHINE", "PORTS", "PUBLIC-ADDRESS", "MESSAGE"} p("\n[Units]") p(strings.Join(header, "\t")) for _, name := range common.SortStringsNaturally(stringKeysFromMap(units)) { u := units[name] pUnit(name, u, 0) const indentationLevel = 1 recurseUnits(u, indentationLevel, pUnit) } tw.Flush() p("\n[Machines]") p("ID\tSTATE\tDNS\tINS-ID\tSERIES\tAZ") for _, name := range common.SortStringsNaturally(stringKeysFromMap(fs.Machines)) { m := fs.Machines[name] // We want to display availability zone so extract from hardware info". hw, err := instance.ParseHardware(m.Hardware) if err != nil { logger.Warningf("invalid hardware info %s for machine %v", m.Hardware, m) } az := "" if hw.AvailabilityZone != nil { az = *hw.AvailabilityZone } p(m.Id, m.AgentState, m.DNSName, m.InstanceId, m.Series, az) } tw.Flush() return out.Bytes(), nil }
func (manager *containerManager) CreateContainer( instanceConfig *instancecfg.InstanceConfig, cons constraints.Value, series string, networkConfig *container.NetworkConfig, storageConfig *container.StorageConfig, callback container.StatusCallback, ) (_ instance.Instance, _ *instance.HardwareCharacteristics, err error) { name, err := manager.namespace.Hostname(instanceConfig.MachineId) if err != nil { return nil, nil, errors.Trace(err) } defer func() { if err != nil { callback(status.ProvisioningError, fmt.Sprintf("Creating container: %v", err), nil) } }() // Set the MachineContainerHostname to match the name returned by virsh list instanceConfig.MachineContainerHostname = name // Note here that the kvmObjectFactory only returns a valid container // object, and doesn't actually construct the underlying kvm container on // disk. kvmContainer := KvmObjectFactory.New(name) // Create the cloud-init. directory, err := container.NewDirectory(name) if err != nil { return nil, nil, errors.Annotate(err, "failed to create container directory") } logger.Tracef("write cloud-init") userDataFilename, err := containerinit.WriteUserData(instanceConfig, networkConfig, directory) if err != nil { logger.Infof("machine config api %#v", *instanceConfig.APIInfo) err = errors.Annotate(err, "failed to write user data") logger.Infof(err.Error()) return nil, nil, err } // Create the container. startParams = ParseConstraintsToStartParams(cons) startParams.Arch = arch.HostArch() startParams.Series = series startParams.Network = networkConfig startParams.UserDataFile = userDataFilename // If the Simplestream requested is anything but released, update // our StartParams to request it. if instanceConfig.ImageStream != imagemetadata.ReleasedStream { startParams.ImageDownloadUrl = imagemetadata.UbuntuCloudImagesURL + "/" + instanceConfig.ImageStream } var hardware instance.HardwareCharacteristics hardware, err = instance.ParseHardware( fmt.Sprintf("arch=%s mem=%vM root-disk=%vG cores=%v", startParams.Arch, startParams.Memory, startParams.RootDisk, startParams.CpuCores)) if err != nil { return nil, nil, errors.Annotate(err, "failed to parse hardware") } callback(status.Allocating, "Creating container; it might take some time", nil) logger.Tracef("create the container, constraints: %v", cons) if err := kvmContainer.Start(startParams); err != nil { err = errors.Annotate(err, "kvm container creation failed") logger.Infof(err.Error()) return nil, nil, err } logger.Tracef("kvm container created") return &kvmInstance{kvmContainer, name}, &hardware, nil }