func (i *importer) machinePortsOps(m description.Machine) []txn.Op { var result []txn.Op machineId := m.Id() for _, ports := range m.NetworkPorts() { networkName := ports.NetworkName() doc := &portsDoc{ MachineID: machineId, NetworkName: networkName, } for _, opened := range ports.OpenPorts() { doc.Ports = append(doc.Ports, PortRange{ UnitName: opened.UnitName(), FromPort: opened.FromPort(), ToPort: opened.ToPort(), Protocol: opened.Protocol(), }) } result = append(result, txn.Op{ C: openedPortsC, Id: portsGlobalKey(machineId, networkName), Assert: txn.DocMissing, Insert: doc, }) } return result }
func (i *importer) makeMachineDoc(m description.Machine) (*machineDoc, error) { id := m.Id() supported, supportedSet := m.SupportedContainers() supportedContainers := make([]instance.ContainerType, len(supported)) for j, c := range supported { supportedContainers[j] = instance.ContainerType(c) } jobs, err := i.makeMachineJobs(m.Jobs()) if err != nil { return nil, errors.Trace(err) } return &machineDoc{ DocID: i.st.docID(id), Id: id, ModelUUID: i.st.ModelUUID(), Nonce: m.Nonce(), Series: m.Series(), ContainerType: m.ContainerType(), Principals: nil, // TODO Life: Alive, Tools: i.makeTools(m.Tools()), Jobs: jobs, NoVote: true, // State servers can't be migrated yet. HasVote: false, // State servers can't be migrated yet. PasswordHash: m.PasswordHash(), Clean: true, // check this later Addresses: i.makeAddresses(m.ProviderAddresses()), MachineAddresses: i.makeAddresses(m.MachineAddresses()), PreferredPrivateAddress: i.makeAddress(m.PreferredPrivateAddress()), PreferredPublicAddress: i.makeAddress(m.PreferredPublicAddress()), SupportedContainersKnown: supportedSet, SupportedContainers: supportedContainers, Placement: m.Placement(), }, nil }
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 }