Exemplo n.º 1
0
func (e *environ) StartInstance(machineId string, info *state.Info, tools *state.Tools) (environs.Instance, error) {
	defer delay()
	log.Printf("environs/dummy: dummy startinstance, machine %s", machineId)
	if err := e.checkBroken("StartInstance"); err != nil {
		return nil, err
	}
	e.state.mu.Lock()
	defer e.state.mu.Unlock()
	if _, ok := e.Config().CACert(); !ok {
		return nil, fmt.Errorf("no CA certificate in environment configuration")
	}
	if info.EntityName != state.MachineEntityName(machineId) {
		return nil, fmt.Errorf("entity name must match started machine")
	}
	if tools != nil && (strings.HasPrefix(tools.Series, "unknown") || strings.HasPrefix(tools.Arch, "unknown")) {
		return nil, fmt.Errorf("cannot find image for %s-%s", tools.Series, tools.Arch)
	}
	i := &instance{
		state:     e.state,
		id:        state.InstanceId(fmt.Sprintf("%s-%d", e.state.name, e.state.maxId)),
		ports:     make(map[state.Port]bool),
		machineId: machineId,
	}
	e.state.insts[i.id] = i
	e.state.maxId++
	e.state.ops <- OpStartInstance{
		Env:       e.state.name,
		MachineId: machineId,
		Instance:  i,
		Info:      info,
		Secret:    e.ecfg().secret(),
	}
	return i, nil
}
Exemplo n.º 2
0
// InvalidStateInfo holds information about no state - it will always
// give an error when connected to.  The machine id gives the machine id
// of the machine to be started
func InvalidStateInfo(machineId string) *state.Info {
	return &state.Info{
		Addrs:      []string{"0.1.2.3:1234"},
		EntityName: state.MachineEntityName(machineId),
		Password:   "******",
		CACert:     []byte(testing.CACert),
	}
}
Exemplo n.º 3
0
// Run runs a machine agent.
func (a *MachineAgent) Run(_ *cmd.Context) error {
	if err := a.Conf.read(state.MachineEntityName(a.MachineId)); err != nil {
		return err
	}
	defer log.Printf("cmd/jujud: machine agent exiting")
	defer a.tomb.Done()
	return RunLoop(a.Conf.Conf, a)
}
Exemplo n.º 4
0
// primeAgent adds a new Machine to run the given jobs, and sets up the
// machine agent's directory.  It returns the new machine and the
// agent's configuration.
func (s *MachineSuite) primeAgent(c *C, jobs ...state.MachineJob) (*state.Machine, *agent.Conf) {
	m, err := s.State.InjectMachine("ardbeg-0", jobs...)
	c.Assert(err, IsNil)
	err = m.SetMongoPassword("machine-password")
	c.Assert(err, IsNil)
	conf, _ := s.agentSuite.primeAgent(c, state.MachineEntityName(m.Id()), "machine-password")
	return m, conf
}
Exemplo n.º 5
0
func verifyConfig(cfg *MachineConfig) (err error) {
	defer trivial.ErrorContextf(&err, "invalid machine configuration")
	if !state.IsMachineId(cfg.MachineId) {
		return fmt.Errorf("invalid machine id")
	}
	if cfg.ProviderType == "" {
		return fmt.Errorf("missing provider type")
	}
	if cfg.DataDir == "" {
		return fmt.Errorf("missing var directory")
	}
	if cfg.Tools == nil {
		return fmt.Errorf("missing tools")
	}
	if cfg.Tools.URL == "" {
		return fmt.Errorf("missing tools URL")
	}
	if cfg.StateInfo == nil {
		return fmt.Errorf("missing state info")
	}
	if len(cfg.StateInfo.CACert) == 0 {
		return fmt.Errorf("missing CA certificate")
	}
	if cfg.StateServer {
		if cfg.InstanceIdAccessor == "" {
			return fmt.Errorf("missing instance id accessor")
		}
		if cfg.Config == nil {
			return fmt.Errorf("missing environment configuration")
		}
		if cfg.StateInfo.EntityName != "" {
			return fmt.Errorf("entity name must be blank when starting a state server")
		}
		if len(cfg.StateServerCert) == 0 {
			return fmt.Errorf("missing state server certificate")
		}
		if len(cfg.StateServerKey) == 0 {
			return fmt.Errorf("missing state server private key")
		}
	} else {
		if len(cfg.StateInfo.Addrs) == 0 {
			return fmt.Errorf("missing state hosts")
		}
		if cfg.StateInfo.EntityName != state.MachineEntityName(cfg.MachineId) {
			return fmt.Errorf("entity name must match started machine")
		}
	}
	for _, r := range cfg.StateInfo.Password {
		if r == '\'' || r == '\\' || r < 32 {
			return fmt.Errorf("password has disallowed characters")
		}
	}
	return nil
}
Exemplo n.º 6
0
// startInstance is the internal version of StartInstance, used by Bootstrap
// as well as via StartInstance itself.
func (e *environ) startInstance(scfg *startInstanceParams) (environs.Instance, error) {
	if scfg.tools == nil {
		var err error
		flags := environs.HighestVersion | environs.CompatVersion
		scfg.tools, err = environs.FindTools(e, version.Current, flags)
		if err != nil {
			return nil, err
		}
	}

	log.Printf("environs/openstack: starting machine %s in %q running tools version %q from %q",
		scfg.machineId, e.name, scfg.tools.Binary, scfg.tools.URL)
	// TODO(wallyworld) - implement spec lookup
	if strings.Contains(scfg.tools.Series, "unknown") || strings.Contains(scfg.tools.Series, "unknown") {
		return nil, fmt.Errorf("cannot find image for unknown series or architecture")
	}
	userData, err := e.userData(scfg)
	if err != nil {
		return nil, fmt.Errorf("cannot make user data: %v", err)
	}
	log.Debugf("environs/openstack: openstack user data: %q", userData)
	groups, err := e.setUpGroups(scfg.machineId)
	if err != nil {
		return nil, fmt.Errorf("cannot set up groups: %v", err)
	}
	var groupNames = make([]nova.SecurityGroupName, len(groups))
	for i, g := range groups {
		groupNames[i] = nova.SecurityGroupName{g.Name}
	}

	var server *nova.Entity
	for a := shortAttempt.Start(); a.Next(); {
		server, err = e.nova().RunServer(nova.RunServerOpts{
			Name: state.MachineEntityName(scfg.machineId),
			// TODO(wallyworld) - do not use hard coded image
			FlavorId:           defaultFlavorId,
			ImageId:            defaultImageId,
			UserData:           userData,
			SecurityGroupNames: groupNames,
		})
		if err == nil || !gooseerrors.IsNotFound(err) {
			break
		}
	}
	if err != nil {
		return nil, fmt.Errorf("cannot run instance: %v", err)
	}
	inst := &instance{e, server}
	log.Printf("environs/openstack: started instance %q", inst.Id())
	return inst, nil
}
Exemplo n.º 7
0
func (s *MachineSuite) TestMachineEntityName(c *C) {
	c.Assert(state.MachineEntityName("10"), Equals, "machine-10")
}
Exemplo n.º 8
0
func (a *MachineAgent) EntityName() string {
	return state.MachineEntityName(a.MachineId)
}
Exemplo n.º 9
0
func New(cfg *MachineConfig) (*cloudinit.Config, error) {
	if err := verifyConfig(cfg); err != nil {
		return nil, err
	}
	c := cloudinit.New()

	c.AddSSHAuthorizedKeys(cfg.AuthorizedKeys)
	c.AddPackage("git")

	addScripts(c,
		fmt.Sprintf("mkdir -p %s", cfg.DataDir),
		"mkdir -p /var/log/juju")

	// Make a directory for the tools to live in, then fetch the
	// tools and unarchive them into it.
	addScripts(c,
		"bin="+shquote(cfg.jujuTools()),
		"mkdir -p $bin",
		fmt.Sprintf("wget --no-verbose -O - %s | tar xz -C $bin", shquote(cfg.Tools.URL)),
		fmt.Sprintf("echo -n %s > $bin/downloaded-url.txt", shquote(cfg.Tools.URL)),
	)

	debugFlag := ""
	// TODO: disable debug mode by default when the system is stable.
	if true || log.Debug {
		debugFlag = " --debug"
	}

	if cfg.StateServer {
		certKey := string(cfg.StateServerCert) + string(cfg.StateServerKey)
		addFile(c, cfg.dataFile("server.pem"), certKey, 0600)
		// TODO The public bucket must come from the environment configuration.
		b := cfg.Tools.Binary
		url := fmt.Sprintf("http://juju-dist.s3.amazonaws.com/tools/mongo-2.2.0-%s-%s.tgz", b.Series, b.Arch)
		addScripts(c,
			"mkdir -p /opt",
			fmt.Sprintf("wget --no-verbose -O - %s | tar xz -C /opt", shquote(url)),
		)
		if err := addMongoToBoot(c, cfg); err != nil {
			return nil, err
		}
		// We temporarily give bootstrap-state a directory
		// of its own so that it can get the state info via the
		// same mechanism as other jujud commands.
		acfg, err := addAgentInfo(c, cfg, "bootstrap")
		if err != nil {
			return nil, err
		}
		addScripts(c,
			cfg.jujuTools()+"/jujud bootstrap-state"+
				" --data-dir "+shquote(cfg.DataDir)+
				" --instance-id "+cfg.InstanceIdAccessor+
				" --env-config "+shquote(base64yaml(cfg.Config))+
				debugFlag,
			"rm -rf "+shquote(acfg.Dir()),
		)
	}

	if _, err := addAgentToBoot(c, cfg, "machine",
		state.MachineEntityName(cfg.MachineId),
		fmt.Sprintf("--machine-id %s "+debugFlag, cfg.MachineId)); err != nil {
		return nil, err
	}

	// general options
	c.SetAptUpgrade(true)
	c.SetAptUpdate(true)
	c.SetOutput(cloudinit.OutAll, "| tee -a /var/log/cloud-init-output.log", "")
	return c, nil
}