Esempio n. 1
0
// startBootstrapNode starts the juju bootstrap node for this environment.
func (env *maasEnviron) startBootstrapNode(cons constraints.Value) (instance.Instance, error) {
	// The bootstrap instance gets machine id "0".  This is not related to
	// instance ids or MAAS system ids.  Juju assigns the machine ID.
	const machineID = "0"

	// Create an empty bootstrap state file so we can get its URL.
	// If will be updated with the instance id and hardware characteristics
	// after the bootstrap instance is started.
	reader := strings.NewReader("")
	err := env.Storage().Put(environs.StateFile, reader, int64(0))
	if err != nil {
		return nil, fmt.Errorf("cannot create bootstrap state file: %v", err)
	}
	stateFileURL, err := env.Storage().URL(environs.StateFile)
	if err != nil {
		return nil, fmt.Errorf("cannot create bootstrap state file: %v", err)
	}

	logger.Debugf("bootstrapping environment %q", env.Name())
	possibleTools, err := environs.FindBootstrapTools(env, cons)
	if err != nil {
		return nil, err
	}
	err = environs.CheckToolsSeries(possibleTools, env.Config().DefaultSeries())
	if err != nil {
		return nil, err
	}

	machineConfig := environs.NewBootstrapMachineConfig(machineID, stateFileURL)
	inst, err := env.internalStartInstance(cons, possibleTools, machineConfig)
	if err != nil {
		return nil, fmt.Errorf("cannot start bootstrap instance: %v", err)
	}
	return inst, nil
}
Esempio n. 2
0
func (s *ToolsSuite) TestCheckToolsSeriesAcceptsOneSetOfTools(c *C) {
	names := []string{"precise", "raring"}
	for _, series := range names {
		list := fakeToolsList(series)
		err := environs.CheckToolsSeries(list, series)
		c.Check(err, IsNil)
	}
}
Esempio n. 3
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
}
Esempio n. 4
0
// TODO(bug 1199847): This work can be shared between providers.
func (e *environ) StartInstance(machineId, machineNonce string, series string, cons constraints.Value,
	stateInfo *state.Info, apiInfo *api.Info) (instance.Instance, *instance.HardwareCharacteristics, error) {
	possibleTools, err := environs.FindInstanceTools(e, series, cons)
	if err != nil {
		return nil, nil, err
	}
	err = environs.CheckToolsSeries(possibleTools, series)
	if err != nil {
		return nil, nil, err
	}

	machineConfig := environs.NewMachineConfig(machineId, machineNonce, stateInfo, apiInfo)
	return e.internalStartInstance(cons, possibleTools, machineConfig)
}
Esempio n. 5
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 := e.Storage().URL(environs.StateFile)
	if err != nil {
		return fmt.Errorf("cannot create bootstrap state file: %v", 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
}
Esempio n. 6
0
// StartInstance is specified in the Environ interface.
// TODO(bug 1199847): This work can be shared between providers.
func (env *azureEnviron) StartInstance(machineID, machineNonce string, series string, cons constraints.Value,
	stateInfo *state.Info, apiInfo *api.Info) (instance.Instance, *instance.HardwareCharacteristics, error) {
	possibleTools, err := environs.FindInstanceTools(env, series, cons)
	if err != nil {
		return nil, nil, err
	}
	err = environs.CheckToolsSeries(possibleTools, series)
	if err != nil {
		return nil, nil, err
	}
	machineConfig := environs.NewMachineConfig(machineID, machineNonce, stateInfo, apiInfo)
	// TODO(bug 1193998) - return instance hardware characteristics as well.
	inst, err := env.internalStartInstance(cons, possibleTools, machineConfig)
	return inst, nil, err
}
Esempio n. 7
0
func (e *environ) StartInstance(machineId, machineNonce string, series string, cons constraints.Value,
	info *state.Info, apiInfo *api.Info) (instance.Instance, *instance.HardwareCharacteristics, error) {
	defer delay()
	log.Infof("environs/dummy: dummy startinstance, machine %s", machineId)
	if err := e.checkBroken("StartInstance"); err != nil {
		return nil, nil, err
	}
	possibleTools, err := environs.FindInstanceTools(e, series, cons)
	if err != nil {
		return nil, nil, err
	}
	err = environs.CheckToolsSeries(possibleTools, series)
	if err != nil {
		return nil, nil, err
	}
	log.Infof("environs/dummy: would pick tools from %s", possibleTools)
	e.state.mu.Lock()
	defer e.state.mu.Unlock()
	if machineNonce == "" {
		return nil, nil, fmt.Errorf("cannot start instance: missing machine nonce")
	}
	if _, ok := e.Config().CACert(); !ok {
		return nil, nil, fmt.Errorf("no CA certificate in environment configuration")
	}
	if info.Tag != names.MachineTag(machineId) {
		return nil, nil, fmt.Errorf("entity tag must match started machine")
	}
	if apiInfo.Tag != names.MachineTag(machineId) {
		return nil, nil, fmt.Errorf("entity tag must match started machine")
	}
	i := &dummyInstance{
		state:     e.state,
		id:        instance.Id(fmt.Sprintf("%s-%d", e.state.name, e.state.maxId)),
		ports:     make(map[instance.Port]bool),
		machineId: machineId,
		series:    series,
	}
	var hc *instance.HardwareCharacteristics
	// To match current system capability, only provide hardware characteristics for
	// environ machines, not containers.
	if state.ParentId(machineId) == "" {
		// We will just assume the instance hardware characteristics exactly matches
		// the supplied constraints (if specified).
		hc = &instance.HardwareCharacteristics{
			Arch:     cons.Arch,
			Mem:      cons.Mem,
			CpuCores: cons.CpuCores,
			CpuPower: cons.CpuPower,
		}
		// Fill in some expected instance hardware characteristics if constraints not specified.
		if hc.Arch == nil {
			arch := "amd64"
			hc.Arch = &arch
		}
		if hc.Mem == nil {
			mem := uint64(1024)
			hc.Mem = &mem
		}
		if hc.CpuCores == nil {
			cores := uint64(1)
			hc.CpuCores = &cores
		}
	}
	e.state.insts[i.id] = i
	e.state.maxId++
	e.state.ops <- OpStartInstance{
		Env:          e.state.name,
		MachineId:    machineId,
		MachineNonce: machineNonce,
		Constraints:  cons,
		Instance:     i,
		Info:         info,
		APIInfo:      apiInfo,
		Secret:       e.ecfg().secret(),
	}
	return i, hc, nil
}
Esempio n. 8
0
func (s *ToolsSuite) TestCheckToolsSeriesRejectsToolsForMixedSeries(c *C) {
	list := fakeToolsList("precise", "raring")
	err := environs.CheckToolsSeries(list, "precise")
	c.Assert(err, NotNil)
	c.Check(err, ErrorMatches, "expected single series, got .*")
}
Esempio n. 9
0
func (s *ToolsSuite) TestCheckToolsSeriesRejectsToolsForOtherSeries(c *C) {
	list := fakeToolsList("hoary")
	err := environs.CheckToolsSeries(list, "warty")
	c.Assert(err, NotNil)
	c.Check(err, ErrorMatches, "tools mismatch: expected series warty, got hoary")
}
Esempio n. 10
0
func (s *ToolsSuite) TestCheckToolsSeriesAcceptsMultipleForSameSeries(c *C) {
	series := "quantal"
	list := fakeToolsList(series, series, series)
	err := environs.CheckToolsSeries(list, series)
	c.Check(err, IsNil)
}
Esempio n. 11
0
func (s *ToolsSuite) TestCheckToolsSeriesRequiresTools(c *C) {
	err := environs.CheckToolsSeries(fakeToolsList(), "precise")
	c.Assert(err, NotNil)
	c.Check(err, ErrorMatches, "expected single series, got \\[\\]")
}