// 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(inst.Id()); 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) } } }
// assertPorts retrieves the open ports of the instance and compares them // to the expected. func (s *FirewallerSuite) assertPorts(c *gc.C, inst instance.Instance, machineId string, expected []instance.Port) { s.BackingState.StartSync() start := time.Now() for { got, err := inst.Ports(machineId) if err != nil { c.Fatal(err) return } instance.SortPorts(got) instance.SortPorts(expected) if reflect.DeepEqual(got, expected) { c.Succeed() return } if time.Since(start) > coretesting.LongWait { c.Fatalf("timed out: expected %q; got %q", expected, got) return } time.Sleep(coretesting.ShortWait) } }
// 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 (s *lxcBrokerSuite) lxcRemovedContainerDir(inst instance.Instance) string { return filepath.Join(s.RemovedDir, string(inst.Id())) }