func (api *MachinerAPI) getOneMachineProviderNetworkConfig(m *state.Machine) ([]params.NetworkConfig, error) { instId, err := m.InstanceId() if err != nil { return nil, errors.Trace(err) } netEnviron, err := networkingcommon.NetworkingEnvironFromModelConfig( stateenvirons.EnvironConfigGetter{api.st}, ) if errors.IsNotSupported(err) { logger.Infof("not updating provider network config: %v", err) return nil, nil } else if err != nil { return nil, errors.Annotate(err, "cannot get provider network config") } interfaceInfos, err := netEnviron.NetworkInterfaces(instId) if err != nil { return nil, errors.Annotatef(err, "cannot get network interfaces of %q", instId) } if len(interfaceInfos) == 0 { logger.Infof("not updating provider network config: no interfaces returned") return nil, nil } providerConfig := networkingcommon.NetworkConfigFromInterfaceInfo(interfaceInfos) logger.Tracef("provider network config instance %q: %+v", instId, providerConfig) return providerConfig, nil }
func (p *ProvisionerAPI) prepareOrGetContainerInterfaceInfo(args params.Entities, maintain bool) (params.MachineNetworkConfigResults, error) { result := params.MachineNetworkConfigResults{ Results: make([]params.MachineNetworkConfigResult, len(args.Entities)), } netEnviron, hostMachine, canAccess, err := p.prepareContainerAccessEnvironment() if err != nil { return result, errors.Trace(err) } instId, err := hostMachine.InstanceId() if errors.IsNotProvisioned(err) { err = errors.NotProvisionedf("cannot prepare container network config: host machine %q", hostMachine) return result, err } else if err != nil { return result, errors.Trace(err) } for i, entity := range args.Entities { machineTag, err := names.ParseMachineTag(entity.Tag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } // The auth function (canAccess) checks that the machine is a // top level machine (we filter those out next) or that the // machine has the host as a parent. container, err := p.getMachine(canAccess, machineTag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } else if !container.IsContainer() { err = errors.Errorf("cannot prepare network config for %q: not a container", machineTag) result.Results[i].Error = common.ServerError(err) continue } else if ciid, cerr := container.InstanceId(); maintain == true && cerr == nil { // Since we want to configure and create NICs on the // container before it starts, it must also be not // provisioned yet. err = errors.Errorf("container %q already provisioned as %q", container, ciid) result.Results[i].Error = common.ServerError(err) continue } else if cerr != nil && !errors.IsNotProvisioned(cerr) { // Any other error needs to be reported. result.Results[i].Error = common.ServerError(cerr) continue } if err := hostMachine.SetContainerLinkLayerDevices(container); err != nil { result.Results[i].Error = common.ServerError(err) continue } containerDevices, err := container.AllLinkLayerDevices() if err != nil { result.Results[i].Error = common.ServerError(err) continue } preparedInfo := make([]network.InterfaceInfo, len(containerDevices)) preparedOK := true for j, device := range containerDevices { parentDevice, err := device.ParentDevice() if err != nil || parentDevice == nil { err = errors.Errorf( "cannot get parent %q of container device %q: %v", device.ParentName(), device.Name(), err, ) result.Results[i].Error = common.ServerError(err) preparedOK = false break } parentAddrs, err := parentDevice.Addresses() if err != nil { result.Results[i].Error = common.ServerError(err) preparedOK = false break } info := network.InterfaceInfo{ InterfaceName: device.Name(), MACAddress: device.MACAddress(), ConfigType: network.ConfigManual, InterfaceType: network.InterfaceType(device.Type()), NoAutoStart: !device.IsAutoStart(), Disabled: !device.IsUp(), MTU: int(device.MTU()), ParentInterfaceName: parentDevice.Name(), } if len(parentAddrs) > 0 { logger.Infof("host machine device %q has addresses %v", parentDevice.Name(), parentAddrs) firstAddress := parentAddrs[0] parentDeviceSubnet, err := firstAddress.Subnet() if err != nil { err = errors.Annotatef(err, "cannot get subnet %q used by address %q of host machine device %q", firstAddress.SubnetCIDR(), firstAddress.Value(), parentDevice.Name(), ) result.Results[i].Error = common.ServerError(err) preparedOK = false break } info.ConfigType = network.ConfigStatic info.CIDR = parentDeviceSubnet.CIDR() info.ProviderSubnetId = parentDeviceSubnet.ProviderId() info.VLANTag = parentDeviceSubnet.VLANTag() } else { logger.Infof("host machine device %q has no addresses %v", parentDevice.Name(), parentAddrs) } logger.Tracef("prepared info for container interface %q: %+v", info.InterfaceName, info) preparedOK = true preparedInfo[j] = info } if !preparedOK { // Error result is already set. continue } allocatedInfo, err := netEnviron.AllocateContainerAddresses(instId, machineTag, preparedInfo) if err != nil { result.Results[i].Error = common.ServerError(err) continue } logger.Debugf("got allocated info from provider: %+v", allocatedInfo) allocatedConfig := networkingcommon.NetworkConfigFromInterfaceInfo(allocatedInfo) logger.Tracef("allocated network config: %+v", allocatedConfig) result.Results[i].Config = allocatedConfig } return result, nil }
func (task *provisionerTask) startMachine( machine *apiprovisioner.Machine, provisioningInfo *params.ProvisioningInfo, startInstanceParams environs.StartInstanceParams, ) error { var result *environs.StartInstanceResult for attemptsLeft := task.retryStartInstanceStrategy.retryCount; attemptsLeft >= 0; attemptsLeft-- { attemptResult, err := task.broker.StartInstance(startInstanceParams) if err == nil { result = attemptResult break } else if attemptsLeft <= 0 { // 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) } logger.Warningf("%v", errors.Annotate(err, "starting instance")) retryMsg := fmt.Sprintf("will retry to start instance in %v", task.retryStartInstanceStrategy.retryDelay) if err2 := machine.SetStatus(status.Pending, retryMsg, nil); err2 != nil { logger.Errorf("%v", err2) } logger.Infof(retryMsg) select { case <-task.catacomb.Dying(): return task.catacomb.ErrDying() case <-time.After(task.retryStartInstanceStrategy.retryDelay): } } networkConfig := networkingcommon.NetworkConfigFromInterfaceInfo(result.NetworkInfo) volumes := volumesToAPIserver(result.Volumes) volumeNameToAttachmentInfo := volumeAttachmentsToAPIserver(result.VolumeAttachments) if err := machine.SetInstanceInfo( result.Instance.Id(), startInstanceParams.InstanceConfig.MachineNonce, result.Hardware, networkConfig, volumes, volumeNameToAttachmentInfo, ); err != nil { // We need to stop the instance right away here, set error status and go on. if err2 := task.setErrorStatus("cannot register instance for machine %v: %v", machine, err); err2 != nil { logger.Errorf("%v", errors.Annotate(err2, "cannot set machine's status")) } if err2 := task.broker.StopInstances(result.Instance.Id()); err2 != nil { logger.Errorf("%v", errors.Annotate(err2, "after failing to set instance info")) } return errors.Annotate(err, "cannot set instance info") } logger.Infof( "started machine %s as instance %s with hardware %q, network config %+v, volumes %v, volume attachments %v, subnets to zones %v", machine, result.Instance.Id(), result.Hardware, networkConfig, volumes, volumeNameToAttachmentInfo, startInstanceParams.SubnetsToZones, ) return nil }
func (task *provisionerTask) startMachine( machine *apiprovisioner.Machine, provisioningInfo *params.ProvisioningInfo, startInstanceParams environs.StartInstanceParams, ) error { result, err := task.broker.StartInstance(startInstanceParams) if err != nil { if !instance.IsRetryableCreationError(errors.Cause(err)) { // 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) } logger.Infof("retryable error received on start instance: %v", err) for count := task.retryStartInstanceStrategy.retryCount; count > 0; count-- { if task.retryStartInstanceStrategy.retryDelay > 0 { select { case <-task.catacomb.Dying(): return task.catacomb.ErrDying() case <-time.After(task.retryStartInstanceStrategy.retryDelay): } } result, err = task.broker.StartInstance(startInstanceParams) if err == nil { break } // If this was the last attempt and an error was received, set the error // status on the machine. if count == 1 { return task.setErrorStatus("cannot start instance for machine %q: %v", machine, err) } } } inst := result.Instance hardware := result.Hardware nonce := startInstanceParams.InstanceConfig.MachineNonce networkConfig := networkingcommon.NetworkConfigFromInterfaceInfo(result.NetworkInfo) volumes := volumesToApiserver(result.Volumes) volumeAttachments := volumeAttachmentsToApiserver(result.VolumeAttachments) err = machine.SetInstanceInfo(inst.Id(), nonce, hardware, networkConfig, volumes, volumeAttachments) if err == nil { logger.Infof( "started machine %s as instance %s with hardware %q, network config %+v, volumes %v, volume attachments %v, subnets to zones %v", machine, inst.Id(), hardware, networkConfig, volumes, volumeAttachments, startInstanceParams.SubnetsToZones, ) 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. return errors.Annotatef(err, "cannot stop instance %q for machine %v", inst.Id(), machine) } return nil }