func (e *exporter) newMachine(exParent description.Machine, machine *Machine, instances map[string]instanceData, portsData []portsDoc, blockDevices map[string][]BlockDeviceInfo) (description.Machine, error) { args := description.MachineArgs{ Id: machine.MachineTag(), Nonce: machine.doc.Nonce, PasswordHash: machine.doc.PasswordHash, Placement: machine.doc.Placement, Series: machine.doc.Series, ContainerType: machine.doc.ContainerType, } if supported, ok := machine.SupportedContainers(); ok { containers := make([]string, len(supported)) for i, containerType := range supported { containers[i] = string(containerType) } args.SupportedContainers = &containers } for _, job := range machine.Jobs() { args.Jobs = append(args.Jobs, job.MigrationValue()) } // A null value means that we don't yet know which containers // are supported. An empty slice means 'no containers are supported'. var exMachine description.Machine if exParent == nil { exMachine = e.model.AddMachine(args) } else { exMachine = exParent.AddContainer(args) } exMachine.SetAddresses( e.newAddressArgsSlice(machine.doc.MachineAddresses), e.newAddressArgsSlice(machine.doc.Addresses)) exMachine.SetPreferredAddresses( e.newAddressArgs(machine.doc.PreferredPublicAddress), e.newAddressArgs(machine.doc.PreferredPrivateAddress)) // We fully expect the machine to have tools set, and that there is // some instance data. instData, found := instances[machine.doc.Id] if !found { return nil, errors.NotValidf("missing instance data for machine %s", machine.Id()) } exMachine.SetInstance(e.newCloudInstanceArgs(instData)) // We don't rely on devices being there. If they aren't, we get an empty slice, // which is fine to iterate over with range. for _, device := range blockDevices[machine.doc.Id] { exMachine.AddBlockDevice(description.BlockDeviceArgs{ Name: device.DeviceName, Links: device.DeviceLinks, Label: device.Label, UUID: device.UUID, HardwareID: device.HardwareId, BusAddress: device.BusAddress, Size: device.Size, FilesystemType: device.FilesystemType, InUse: device.InUse, MountPoint: device.MountPoint, }) } // Find the current machine status. globalKey := machine.globalKey() statusArgs, err := e.statusArgs(globalKey) if err != nil { return nil, errors.Annotatef(err, "status for machine %s", machine.Id()) } exMachine.SetStatus(statusArgs) exMachine.SetStatusHistory(e.statusHistoryArgs(globalKey)) tools, err := machine.AgentTools() if err != nil { // This means the tools aren't set, but they should be. return nil, errors.Trace(err) } exMachine.SetTools(description.AgentToolsArgs{ Version: tools.Version, URL: tools.URL, SHA256: tools.SHA256, Size: tools.Size, }) for _, args := range e.openedPortsArgsForMachine(machine.Id(), portsData) { exMachine.AddOpenedPorts(args) } exMachine.SetAnnotations(e.getAnnotations(globalKey)) constraintsArgs, err := e.constraintsArgs(globalKey) if err != nil { return nil, errors.Trace(err) } exMachine.SetConstraints(constraintsArgs) return exMachine, nil }