// handleBootstrapError cleans up after a failed bootstrap. func handleBootstrapError(err error, ctx environs.BootstrapContext, inst instance.Instance, env environs.Environ) { if err == nil { return } logger.Errorf("bootstrap failed: %v", err) ch := make(chan os.Signal, 1) ctx.InterruptNotify(ch) defer ctx.StopInterruptNotify(ch) defer close(ch) go func() { for _ = range ch { fmt.Fprintln(ctx.GetStderr(), "Cleaning up failed bootstrap") } }() if inst != nil { fmt.Fprintln(ctx.GetStderr(), "Stopping instance...") if stoperr := env.StopInstances([]instance.Instance{inst}); stoperr != nil { logger.Errorf("cannot stop failed bootstrap instance %q: %v", inst.Id(), stoperr) } else { // set to nil so we know we can safely delete the state file inst = nil } } // We only delete the bootstrap state file if either we didn't // start an instance, or we managed to cleanly stop it. if inst == nil { if rmerr := bootstrap.DeleteStateFile(env.Storage()); rmerr != nil { logger.Errorf("cannot delete bootstrap state file: %v", rmerr) } } }
// WaitDNSName is an implementation that the providers can use. It builds on // the provider's implementation of Instance.DNSName. func WaitDNSName(inst instance.Instance) (string, error) { for a := LongAttempt.Start(); a.Next(); { name, err := inst.DNSName() if err == nil || err != instance.ErrNoDNSName { return name, err } } return "", fmt.Errorf("timed out trying to get DNS address for %v", inst.Id()) }
func (manager *containerManager) DestroyContainer(instance instance.Instance) error { name := string(instance.Id()) kvmContainer := KvmObjectFactory.New(name) if err := kvmContainer.Stop(); err != nil { logger.Errorf("failed to stop kvm container: %v", err) return err } return container.RemoveDirectory(name) }
// assertInstanceId asserts that the machine has an instance id // that matches that of the given instance. If the instance is nil, // It asserts that the instance id is unset. func assertInstanceId(c *gc.C, m *state.Machine, inst instance.Instance) { var wantId, gotId instance.Id var err error if inst != nil { wantId = inst.Id() } for a := waitAgent.Start(); a.Next(); { err := m.Refresh() c.Assert(err, gc.IsNil) gotId, err = m.InstanceId() if err != nil { c.Assert(err, jc.Satisfies, state.IsNotProvisionedError) if inst == nil { return } continue } break } c.Assert(err, gc.IsNil) c.Assert(gotId, gc.Equals, wantId) }
// Bootstrap is a common implementation of the Bootstrap method defined on // environs.Environ; we strongly recommend that this implementation be used // when writing a new provider. func Bootstrap(ctx environs.BootstrapContext, env environs.Environ, args environs.BootstrapParams) (err error) { // TODO make safe in the case of racing Bootstraps // If two Bootstraps are called concurrently, there's // no way to make sure that only one succeeds. var inst instance.Instance defer func() { handleBootstrapError(err, ctx, inst, env) }() // First thing, ensure we have tools otherwise there's no point. selectedTools, err := EnsureBootstrapTools(ctx, env, config.PreferredSeries(env.Config()), args.Constraints.Arch) if err != nil { return err } // Get the bootstrap SSH client. Do this early, so we know // not to bother with any of the below if we can't finish the job. client := ssh.DefaultClient if client == nil { // This should never happen: if we don't have OpenSSH, then // go.crypto/ssh should be used with an auto-generated key. return fmt.Errorf("no SSH client available") } privateKey, err := GenerateSystemSSHKey(env) if err != nil { return err } machineConfig := environs.NewBootstrapMachineConfig(privateKey) fmt.Fprintln(ctx.GetStderr(), "Launching instance") inst, hw, _, err := env.StartInstance(environs.StartInstanceParams{ Constraints: args.Constraints, Tools: selectedTools, MachineConfig: machineConfig, Placement: args.Placement, }) if err != nil { return fmt.Errorf("cannot start bootstrap instance: %v", err) } fmt.Fprintf(ctx.GetStderr(), " - %s\n", inst.Id()) machineConfig.InstanceId = inst.Id() machineConfig.HardwareCharacteristics = hw err = bootstrap.SaveState( env.Storage(), &bootstrap.BootstrapState{ StateInstances: []instance.Id{inst.Id()}, }) if err != nil { return fmt.Errorf("cannot save state: %v", err) } return FinishBootstrap(ctx, client, inst, machineConfig) }
func (manager *containerManager) DestroyContainer(instance instance.Instance) error { start := time.Now() name := string(instance.Id()) lxcContainer := LxcObjectFactory.New(name) if useRestartDir() { // Remove the autostart link. if err := os.Remove(restartSymlink(name)); err != nil { logger.Errorf("failed to remove restart symlink: %v", err) return err } } if err := lxcContainer.Destroy(); err != nil { logger.Errorf("failed to destroy lxc container: %v", err) return err } err := container.RemoveDirectory(name) logger.Tracef("container %q stopped: %v", name, time.Now().Sub(start)) return err }
func (s *lxcBrokerSuite) lxcRemovedContainerDir(inst instance.Instance) string { return filepath.Join(s.RemovedDir, string(inst.Id())) }
func (s *kvmBrokerSuite) kvmContainerDir(inst instance.Instance) string { return filepath.Join(s.ContainerDir, string(inst.Id())) }