Пример #1
0
// upstartService returns an upstart.Service corresponding to the specified
// unit.
func (ctx *SimpleContext) upstartService(unitName string) *upstart.Service {
	tag := names.UnitTag(unitName)
	svcName := "jujud-" + tag
	svc := upstart.NewService(svcName)
	svc.InitDir = ctx.initDir
	return svc
}
Пример #2
0
// NewDeployerAPI creates a new client-side DeployerAPI facade.
func NewDeployerAPI(
	st *state.State,
	resources *common.Resources,
	authorizer common.Authorizer,
) (*DeployerAPI, error) {
	if !authorizer.AuthMachineAgent() {
		return nil, common.ErrPerm
	}
	getAuthFunc := func() (common.AuthFunc, error) {
		// Get all units of the machine and cache them.
		thisMachineTag := authorizer.GetAuthTag()
		units, err := getAllUnits(st, thisMachineTag)
		if err != nil {
			return nil, err
		}
		// Then we just check if the unit is already known.
		return func(tag string) bool {
			for _, unit := range units {
				if names.UnitTag(unit) == tag {
					return true
				}
			}
			return false
		}, nil
	}
	return &DeployerAPI{
		Remover:         common.NewRemover(st, getAuthFunc),
		PasswordChanger: common.NewPasswordChanger(st, getAuthFunc),
		LifeGetter:      common.NewLifeGetter(st, getAuthFunc),
		st:              st,
		resources:       resources,
		authorizer:      authorizer,
	}, nil
}
Пример #3
0
// changed ensures that the named unit is deployed, recalled, or removed, as
// indicated by its state.
func (d *Deployer) changed(unitName string) error {
	unitTag := names.UnitTag(unitName)
	// Determine unit life state, and whether we're responsible for it.
	logger.Infof("checking unit %q", unitName)
	var life params.Life
	unit, err := d.st.Unit(unitTag)
	if isNotFoundOrUnauthorized(err) {
		life = params.Dead
	} else if err != nil {
		return err
	} else {
		life = unit.Life()
	}
	// Deployed units must be removed if they're Dead, or if the deployer
	// is no longer responsible for them.
	if d.deployed.Contains(unitName) {
		if life == params.Dead {
			if err := d.recall(unitName); err != nil {
				return err
			}
		}
	}
	// The only units that should be deployed are those that (1) we are responsible
	// for and (2) are Alive -- if we're responsible for a Dying unit that is not
	// yet deployed, we should remove it immediately rather than undergo the hassle
	// of deploying a unit agent purely so it can set itself to Dead.
	if !d.deployed.Contains(unitName) {
		if life == params.Alive {
			return d.deploy(unit)
		} else if unit != nil {
			return d.remove(unit)
		}
	}
	return nil
}
Пример #4
0
func (ctx *SimpleContext) RecallUnit(unitName string) error {
	svc := ctx.findUpstartJob(unitName)
	if svc == nil || !svc.Installed() {
		return fmt.Errorf("unit %q is not deployed", unitName)
	}
	if err := svc.Remove(); err != nil {
		return err
	}
	tag := names.UnitTag(unitName)
	agentDir := tools.Dir(ctx.dataDir, tag)
	if err := os.RemoveAll(agentDir); err != nil {
		return err
	}
	if err := os.Remove(ctx.syslogConfigPath); err != nil && !os.IsNotExist(err) {
		logger.Warningf("installer: cannot remove %q: %v", ctx.syslogConfigPath, err)
	}
	// Defer this so a failure here does not impede the cleanup (as in tests).
	defer func() {
		if err := syslog.Restart(); err != nil {
			logger.Warningf("installer: cannot restart syslog daemon: %v", err)
		}
	}()
	toolsDir := tools.ToolsDir(ctx.dataDir, tag)
	return os.Remove(toolsDir)
}
Пример #5
0
func (fix *SimpleToolsFixture) checkUnitInstalled(c *C, name, password string) {
	tag := names.UnitTag(name)
	uconfPath, _, toolsDir, syslogConfPath := fix.paths(tag)
	uconfData, err := ioutil.ReadFile(uconfPath)
	c.Assert(err, IsNil)
	uconf := string(uconfData)
	var execLine string
	for _, line := range strings.Split(uconf, "\n") {
		if strings.HasPrefix(line, "exec ") {
			execLine = line
			break
		}
	}
	if execLine == "" {
		c.Fatalf("no command found in %s:\n%s", uconfPath, uconf)
	}
	logPath := filepath.Join(fix.logDir, tag+".log")
	jujudPath := filepath.Join(toolsDir, "jujud")
	for _, pat := range []string{
		"^exec " + jujudPath + " unit ",
		" --unit-name " + name + " ",
		" >> " + logPath + " 2>&1$",
	} {
		match, err := regexp.MatchString(pat, execLine)
		c.Assert(err, IsNil)
		if !match {
			c.Fatalf("failed to match:\n%s\nin:\n%s", pat, execLine)
		}
	}

	conf, err := agent.ReadConf(fix.dataDir, tag)
	c.Assert(err, IsNil)
	c.Assert(conf, DeepEquals, &agent.Conf{
		DataDir:     fix.dataDir,
		OldPassword: password,
		StateInfo: &state.Info{
			Addrs:  []string{"s1:123", "s2:123"},
			CACert: []byte("test-cert"),
			Tag:    tag,
		},
		APIInfo: &api.Info{
			Addrs:  []string{"a1:123", "a2:123"},
			CACert: []byte("test-cert"),
			Tag:    tag,
		},
	})

	jujudData, err := ioutil.ReadFile(jujudPath)
	c.Assert(err, IsNil)
	c.Assert(string(jujudData), Equals, fakeJujud)

	syslogConfData, err := ioutil.ReadFile(syslogConfPath)
	c.Assert(err, IsNil)
	parts := strings.SplitN(name, "/", 2)
	unitTag := fmt.Sprintf("unit-%s-%s", parts[0], parts[1])
	expectedSyslogConfReplaced := fmt.Sprintf(expectedSyslogConf, unitTag, unitTag, unitTag, unitTag)
	c.Assert(string(syslogConfData), Equals, expectedSyslogConfReplaced)

}
Пример #6
0
// DeployerTag returns the tag of the agent responsible for deploying
// the unit. If no such entity can be determined, false is returned.
func (u *Unit) DeployerTag() (string, bool) {
	if u.doc.Principal != "" {
		return names.UnitTag(u.doc.Principal), true
	} else if u.doc.MachineId != "" {
		return names.MachineTag(u.doc.MachineId), true
	}
	return "", false
}
Пример #7
0
func (s *unitSuite) TestInvalidUnitTagFormats(c *gc.C) {
	for i, test := range unitNameTests {
		if !test.valid {
			c.Logf("test %d: %q", i, test.pattern)
			expect := fmt.Sprintf("%q is not a valid unit name", test.pattern)
			testUnitTag := func() { names.UnitTag(test.pattern) }
			c.Assert(testUnitTag, gc.PanicMatches, expect)
		}
	}
}
Пример #8
0
func (fix *SimpleToolsFixture) checkUnitRemoved(c *C, name string) {
	tag := names.UnitTag(name)
	confPath, agentDir, toolsDir, syslogConfPath := fix.paths(tag)
	for _, path := range []string{confPath, agentDir, toolsDir, syslogConfPath} {
		_, err := ioutil.ReadFile(path)
		if err == nil {
			c.Log("Warning: %q not removed as expected", path)
		} else {
			c.Assert(err, checkers.Satisfies, os.IsNotExist)
		}
	}
}
Пример #9
0
func (a *UnitAgent) Tag() string {
	return names.UnitTag(a.UnitName)
}
Пример #10
0
func (ctx *SimpleContext) DeployUnit(unitName, initialPassword string) (err error) {
	// Check sanity.
	svc := ctx.upstartService(unitName)
	if svc.Installed() {
		return fmt.Errorf("unit %q is already deployed", unitName)
	}

	// Link the current tools for use by the new agent.
	tag := names.UnitTag(unitName)
	_, err = tools.ChangeAgentTools(ctx.dataDir, tag, version.Current)
	toolsDir := tools.ToolsDir(ctx.dataDir, tag)
	defer removeOnErr(&err, toolsDir)

	// Retrieve the state addresses.
	stateAddrs, err := ctx.addresser.StateAddresses()
	if err != nil {
		return err
	}
	apiAddrs, err := ctx.addresser.APIAddresses()
	if err != nil {
		return err
	}

	stateInfo := state.Info{
		Addrs:  stateAddrs,
		Tag:    tag,
		CACert: ctx.caCert,
	}
	logger.Debugf("state addresses: %q", stateAddrs)
	apiInfo := api.Info{
		Addrs:  apiAddrs,
		Tag:    tag,
		CACert: ctx.caCert,
	}
	logger.Debugf("API addresses: %q", apiAddrs)
	// Prepare the agent's configuration data.
	conf := &agent.Conf{
		DataDir:     ctx.dataDir,
		OldPassword: initialPassword,
		StateInfo:   &stateInfo,
		APIInfo:     &apiInfo,
	}
	if err := conf.Write(); err != nil {
		return err
	}
	defer removeOnErr(&err, conf.Dir())

	// Install an upstart job that runs the unit agent.
	logPath := path.Join(ctx.logDir, tag+".log")
	syslogConfigRenderer := syslog.NewForwardConfig(tag, stateAddrs)
	syslogConfigRenderer.ConfigDir = ctx.syslogConfigDir
	syslogConfigRenderer.ConfigFileName = fmt.Sprintf("26-juju-%s.conf", tag)
	if err := syslogConfigRenderer.Write(); err != nil {
		return err
	}
	ctx.syslogConfigPath = syslogConfigRenderer.ConfigFilePath()
	if err := syslog.Restart(); err != nil {
		logger.Warningf("installer: cannot restart syslog daemon: %v", err)
	}
	defer removeOnErr(&err, ctx.syslogConfigPath)

	cmd := strings.Join([]string{
		path.Join(toolsDir, "jujud"), "unit",
		"--data-dir", conf.DataDir,
		"--unit-name", unitName,
		"--debug", // TODO: propagate debug state sensibly
	}, " ")
	uconf := &upstart.Conf{
		Service: *svc,
		Desc:    "juju unit agent for " + unitName,
		Cmd:     cmd,
		Out:     logPath,
		// Propagate the provider type enviroment variable.
		Env: map[string]string{
			osenv.JujuProviderType: os.Getenv(osenv.JujuProviderType),
		},
	}
	return uconf.Install()
}
Пример #11
0
func (s *unitSuite) TestUnitTag(c *gc.C) {
	c.Assert(names.UnitTag("wordpress/2"), gc.Equals, "unit-wordpress-2")
}
Пример #12
0
func (c *HooksContext) ClientFileLock() string {
	basename := fmt.Sprintf("juju-%s-debug-hooks", names.UnitTag(c.Unit))
	return filepath.Join(c.FlockDir, basename)
}
Пример #13
0
// Tag returns a name identifying the unit that is safe to use
// as a file name.  The returned name will be different from other
// Tag values returned by any other entities from the same state.
func (u *Unit) Tag() string {
	return names.UnitTag(u.Name())
}