Beispiel #1
0
// startBootstrapInstance starts the bootstrap instance for this environment.
func (env *azureEnviron) startBootstrapInstance(cons constraints.Value) (instance.Instance, error) {
	// The bootstrap instance gets machine id "0".  This is not related to
	// instance ids or anything in Azure.  Juju assigns the machine ID.
	const machineID = "0"

	// Create an empty bootstrap state file so we can get its URL.
	// It will be updated with the instance id and hardware characteristics
	// after the bootstrap instance is started.
	stateFileURL, err := environs.CreateStateFile(env.Storage())
	if err != nil {
		return nil, err
	}
	machineConfig := environs.NewBootstrapMachineConfig(machineID, stateFileURL)

	logger.Debugf("bootstrapping environment %q", env.Name())
	possibleTools, err := environs.FindBootstrapTools(env, cons)
	if err != nil {
		return nil, err
	}
	inst, err := env.internalStartInstance(cons, possibleTools, machineConfig)
	if err != nil {
		return nil, fmt.Errorf("cannot start bootstrap instance: %v", err)
	}
	return inst, nil
}
Beispiel #2
0
// TODO(bug 1199847): This work can be shared between providers.
func (e *environ) Bootstrap(cons constraints.Value) error {
	// The bootstrap instance gets machine id "0".  This is not related
	// to instance ids.  Juju assigns the machine ID.
	const machineID = "0"
	log.Infof("environs/openstack: bootstrapping environment %q", e.name)

	if err := environs.VerifyBootstrapInit(e, shortAttempt); err != nil {
		return err
	}

	possibleTools, err := environs.FindBootstrapTools(e, cons)
	if err != nil {
		return err
	}
	err = environs.CheckToolsSeries(possibleTools, e.Config().DefaultSeries())
	if err != nil {
		return err
	}
	// The client's authentication may have been reset by FindBootstrapTools() if the agent-version
	// attribute was updated so we need to re-authenticate. This will be a no-op if already authenticated.
	// An authenticated client is needed for the URL() call below.
	err = e.client.Authenticate()
	if err != nil {
		return err
	}
	stateFileURL, err := environs.CreateStateFile(e.Storage())
	if err != nil {
		return err
	}

	machineConfig := environs.NewBootstrapMachineConfig(machineID, stateFileURL)

	// TODO(wallyworld) - save bootstrap machine metadata
	inst, characteristics, err := e.internalStartInstance(cons, possibleTools, machineConfig)
	if err != nil {
		return fmt.Errorf("cannot start bootstrap instance: %v", err)
	}
	err = environs.SaveState(e.Storage(), &environs.BootstrapState{
		StateInstances:  []instance.Id{inst.Id()},
		Characteristics: []instance.HardwareCharacteristics{*characteristics},
	})
	if err != nil {
		// ignore error on StopInstance because the previous error is
		// more important.
		e.StopInstances([]instance.Instance{inst})
		return fmt.Errorf("cannot save state: %v", err)
	}
	// TODO make safe in the case of racing Bootstraps
	// If two Bootstraps are called concurrently, there's
	// no way to use Swift to make sure that only one succeeds.
	// Perhaps consider using SimpleDB for state storage
	// which would enable that possibility.

	return nil
}
Beispiel #3
0
// TODO(bug 1199847): Much of this work can be shared between providers.
func (e *environ) Bootstrap(cons constraints.Value) error {
	// The bootstrap instance gets machine id "0".  This is not related to
	// instance ids.  Juju assigns the machine ID.
	const machineID = "0"
	log.Infof("environs/ec2: bootstrapping environment %q", e.name)
	// If the state file exists, it might actually have just been
	// removed by Destroy, and eventual consistency has not caught
	// up yet, so we retry to verify if that is happening.
	if err := environs.VerifyBootstrapInit(e, shortAttempt); err != nil {
		return err
	}

	possibleTools, err := environs.FindBootstrapTools(e, cons)
	if err != nil {
		return err
	}
	err = environs.CheckToolsSeries(possibleTools, e.Config().DefaultSeries())
	if err != nil {
		return err
	}
	stateFileURL, err := environs.CreateStateFile(e.Storage())
	if err != nil {
		return err
	}

	machineConfig := environs.NewBootstrapMachineConfig(machineID, stateFileURL)

	// TODO(wallyworld) - save bootstrap machine metadata
	inst, characteristics, err := e.internalStartInstance(cons, possibleTools, machineConfig)
	if err != nil {
		return fmt.Errorf("cannot start bootstrap instance: %v", err)
	}
	err = environs.SaveState(e.Storage(), &environs.BootstrapState{
		StateInstances:  []instance.Id{inst.Id()},
		Characteristics: []instance.HardwareCharacteristics{*characteristics},
	})
	if err != nil {
		// ignore error on StopInstance because the previous error is
		// more important.
		e.StopInstances([]instance.Instance{inst})
		return fmt.Errorf("cannot save state: %v", err)
	}
	// TODO make safe in the case of racing Bootstraps
	// If two Bootstraps are called concurrently, there's
	// no way to use S3 to make sure that only one succeeds.
	// Perhaps consider using SimpleDB for state storage
	// which would enable that possibility.
	return nil
}
Beispiel #4
0
func (*StateSuite) TestCreateStateFileWritesEmptyStateFile(c *C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()

	url, err := environs.CreateStateFile(storage)
	c.Assert(err, IsNil)

	reader, err := storage.Get(environs.StateFile)
	c.Assert(err, IsNil)
	data, err := ioutil.ReadAll(reader)
	c.Assert(err, IsNil)
	c.Check(string(data), Equals, "")
	c.Assert(url, NotNil)
	expectedURL, err := storage.URL(environs.StateFile)
	c.Assert(err, IsNil)
	c.Check(url, Equals, expectedURL)
}