Пример #1
0
// Bootstrap is specified in the Environ interface.
// TODO(bug 1199847): This work can be shared between providers.
func (env *maasEnviron) Bootstrap(cons constraints.Value) error {

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

	inst, err := env.startBootstrapNode(cons)
	if err != nil {
		return err
	}
	// TODO(wallyworld) add hardware characteristics to BootstrapState
	err = environs.SaveState(
		env.Storage(),
		&environs.BootstrapState{StateInstances: []instance.Id{inst.Id()}})
	if err != nil {
		err2 := env.releaseInstance(inst)
		if err2 != nil {
			// Failure upon failure.  Log it, but return the
			// original error.
			logger.Errorf("cannot release failed bootstrap instance: %v", err2)
		}
		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 make sure that only one succeeds.
	return nil
}
Пример #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
}
Пример #3
0
// Bootstrap is specified in the Environ interface.
func (env *localEnviron) Bootstrap(cons constraints.Value) error {
	logger.Infof("bootstrapping environment %q", env.name)
	if !env.config.runningAsRoot {
		return fmt.Errorf("bootstrapping a local environment must be done as root")
	}
	if err := env.config.createDirs(); err != nil {
		logger.Errorf("failed to create necessary directories: %v", err)
		return err
	}

	if err := env.ensureCertOwner(); err != nil {
		logger.Errorf("failed to reassign ownership of the certs to the user: %v", err)
		return err
	}
	// TODO(thumper): check that the constraints don't include "container=lxc" for now.

	var noRetry = utils.AttemptStrategy{}
	if err := environs.VerifyBootstrapInit(env, noRetry); err != nil {
		return err
	}

	cert, key, err := env.setupLocalMongoService()
	if err != nil {
		return err
	}

	// Before we write the agent config file, we need to make sure the
	// instance is saved in the StateInfo.
	bootstrapId := instance.Id(boostrapInstanceId)
	if err := environs.SaveState(env.Storage(), &environs.BootstrapState{StateInstances: []instance.Id{bootstrapId}}); err != nil {
		logger.Errorf("failed to save state instances: %v", err)
		return err
	}

	// Need to write out the agent file for machine-0 before initializing
	// state, as as part of that process, it will reset the password in the
	// agent file.
	if err := env.writeBootstrapAgentConfFile(cert, key); err != nil {
		return err
	}

	// Have to initialize the state configuration with localhost so we get
	// "special" permissions.
	stateConnection, err := env.initialStateConfiguration(boostrapInstanceId, cons)
	if err != nil {
		return err
	}
	defer stateConnection.Close()

	return env.setupLocalMachineAgent(cons)
}
Пример #4
0
// Bootstrap is specified in the Environ interface.
// TODO(bug 1199847): This work can be shared between providers.
func (env *azureEnviron) Bootstrap(cons constraints.Value) (err error) {
	if err := environs.VerifyBootstrapInit(env, shortAttempt); err != nil {
		return err
	}

	// TODO(bug 1199847). The creation of the affinity group and the
	// virtual network is specific to the Azure provider.
	err = env.createAffinityGroup()
	if err != nil {
		return err
	}
	// If we fail after this point, clean up the affinity group.
	defer func() {
		if err != nil {
			env.deleteAffinityGroup()
		}
	}()
	err = env.createVirtualNetwork()
	if err != nil {
		return err
	}
	// If we fail after this point, clean up the virtual network.
	defer func() {
		if err != nil {
			env.deleteVirtualNetwork()
		}
	}()

	inst, err := env.startBootstrapInstance(cons)
	if err != nil {
		return err
	}
	// TODO(wallyworld) - save hardware characteristics
	err = environs.SaveState(
		env.Storage(),
		&environs.BootstrapState{StateInstances: []instance.Id{inst.Id()}})
	if err != nil {
		err2 := env.StopInstances([]instance.Instance{inst})
		if err2 != nil {
			// Failure upon failure.  Log it, but return the
			// original error.
			logger.Errorf("cannot release failed bootstrap instance: %v", err2)
		}
		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 make sure that only one succeeds.
	return nil
}
Пример #5
0
func (suite *StateSuite) TestLoadStateIntegratesWithSaveState(c *C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()
	arch := "amd64"
	state := environs.BootstrapState{
		StateInstances:  []instance.Id{instance.Id("an-instance-id")},
		Characteristics: []instance.HardwareCharacteristics{{Arch: &arch}}}
	err := environs.SaveState(storage, &state)
	c.Assert(err, IsNil)
	storedState, err := environs.LoadState(storage)
	c.Assert(err, IsNil)

	c.Check(*storedState, DeepEquals, state)
}
Пример #6
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
}
Пример #7
0
func (suite *StateSuite) TestSaveStateWritesStateFile(c *C) {
	storage, cleanup := makeDummyStorage(c)
	defer cleanup()
	arch := "amd64"
	state := environs.BootstrapState{
		StateInstances:  []instance.Id{instance.Id("an-instance-id")},
		Characteristics: []instance.HardwareCharacteristics{{Arch: &arch}}}
	marshaledState, err := goyaml.Marshal(state)
	c.Assert(err, IsNil)

	err = environs.SaveState(storage, &state)
	c.Assert(err, IsNil)

	loadedState, err := storage.Get(environs.StateFile)
	c.Assert(err, IsNil)
	content, err := ioutil.ReadAll(loadedState)
	c.Assert(err, IsNil)
	c.Check(content, DeepEquals, marshaledState)
}
Пример #8
0
func (suite *EnvironSuite) TestStateInfo(c *C) {
	env := suite.makeEnviron()
	hostname := "test"
	input := `{"system_id": "system_id", "hostname": "` + hostname + `"}`
	node := suite.testMAASObject.TestServer.NewNode(input)
	testInstance := &maasInstance{&node, suite.environ}
	err := environs.SaveState(
		env.Storage(),
		&environs.BootstrapState{StateInstances: []instance.Id{testInstance.Id()}})
	c.Assert(err, IsNil)

	stateInfo, apiInfo, err := env.StateInfo()
	c.Assert(err, IsNil)

	config := env.Config()
	statePortSuffix := fmt.Sprintf(":%d", config.StatePort())
	apiPortSuffix := fmt.Sprintf(":%d", config.APIPort())
	c.Assert(stateInfo.Addrs, DeepEquals, []string{hostname + statePortSuffix})
	c.Assert(apiInfo.Addrs, DeepEquals, []string{hostname + apiPortSuffix})
}
Пример #9
0
func (*EnvironSuite) TestStateInfo(c *C) {
	instanceID := "my-instance"
	patchWithServiceListResponse(c, []gwacl.HostedServiceDescriptor{{
		ServiceName: instanceID,
	}})
	env := makeEnviron(c)
	cleanup := setDummyStorage(c, env)
	defer cleanup()
	err := environs.SaveState(
		env.Storage(),
		&environs.BootstrapState{StateInstances: []instance.Id{instance.Id(instanceID)}})
	c.Assert(err, IsNil)

	stateInfo, apiInfo, err := env.StateInfo()
	c.Assert(err, IsNil)

	config := env.Config()
	dnsName := "my-instance." + AZURE_DOMAIN_NAME
	stateServerAddr := fmt.Sprintf("%s:%d", dnsName, config.StatePort())
	apiServerAddr := fmt.Sprintf("%s:%d", dnsName, config.APIPort())
	c.Check(stateInfo.Addrs, DeepEquals, []string{stateServerAddr})
	c.Check(apiInfo.Addrs, DeepEquals, []string{apiServerAddr})
}