func (task *provisionerTask) startMachine(machine *apiprovisioner.Machine) error { provisioningInfo, err := task.provisioningInfo(machine) if err != nil { return err } possibleTools, err := task.possibleTools(provisioningInfo.Series, provisioningInfo.Constraints) if err != nil { return task.setErrorStatus("cannot find tools for machine %q: %v", machine, err) } inst, metadata, networkInfo, err := task.broker.StartInstance(environs.StartInstanceParams{ Constraints: provisioningInfo.Constraints, Tools: possibleTools, MachineConfig: provisioningInfo.MachineConfig, Placement: provisioningInfo.Placement, DistributionGroup: machine.DistributionGroup, }) if err != nil { // Set the state to error, so the machine will be skipped next // time until the error is resolved, but don't return an // error; just keep going with the other machines. return task.setErrorStatus("cannot start instance for machine %q: %v", machine, err) } nonce := provisioningInfo.MachineConfig.MachineNonce networks, ifaces := task.prepareNetworkAndInterfaces(networkInfo) err = machine.SetInstanceInfo(inst.Id(), nonce, metadata, networks, ifaces) if err != nil && params.IsCodeNotImplemented(err) { return fmt.Errorf("cannot provision instance %v for machine %q with networks: not implemented", inst.Id(), machine) } else if err == nil { logger.Infof("started machine %s as instance %s with hardware %q, networks %v, interfaces %v", machine, inst.Id(), metadata, networks, ifaces) return nil } // We need to stop the instance right away here, set error status and go on. task.setErrorStatus("cannot register instance for machine %v: %v", machine, err) if err := task.broker.StopInstances(inst.Id()); err != nil { // We cannot even stop the instance, log the error and quit. logger.Errorf("cannot stop instance %q for machine %v: %v", inst.Id(), machine, err) return err } return nil }