Beispiel #1
0
// UntarFiles will extract the contents of tarFile using
// outputFolder as root
func UntarFiles(tarFile io.Reader, outputFolder string) error {
	tr := tar.NewReader(tarFile)
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			// end of tar archive
			return nil
		}
		if err != nil {
			return fmt.Errorf("failed while reading tar header: %v", err)
		}
		fullPath := filepath.Join(outputFolder, hdr.Name)
		switch hdr.Typeflag {
		case tar.TypeDir:
			if err = os.MkdirAll(fullPath, os.FileMode(hdr.Mode)); err != nil {
				return fmt.Errorf("cannot extract directory %q: %v", fullPath, err)
			}
		case tar.TypeSymlink:
			if err = symlink.New(hdr.Linkname, fullPath); err != nil {
				return fmt.Errorf("cannot extract symlink %q to %q: %v", hdr.Linkname, fullPath, err)
			}
			continue
		case tar.TypeReg, tar.TypeRegA:
			if err = createAndFill(fullPath, hdr.Mode, tr); err != nil {
				return fmt.Errorf("cannot extract file %q: %v", fullPath, err)
			}
		}
	}
	return nil
}
Beispiel #2
0
func (s *prereqsSuite) SetUpTest(c *gc.C) {
	s.BaseSuite.SetUpTest(c)
	s.tmpdir = c.MkDir()
	s.testMongodPath = filepath.Join(s.tmpdir, "mongod")

	s.PatchEnvironment("PATH", s.tmpdir)

	s.PatchValue(&mongo.JujuMongodPath, "/somewhere/that/wont/exist")

	os.Setenv("JUJUTEST_LSB_RELEASE_ID", "Ubuntu")
	err := ioutil.WriteFile(filepath.Join(s.tmpdir, "lsb_release"), []byte(lsbrelease), 0777)
	c.Assert(err, jc.ErrorIsNil)

	// symlink $temp/dpkg-query to /bin/true, to
	// simulate package installation query responses.
	pm, err := testing.GetPackageManager()
	c.Assert(err, jc.ErrorIsNil)

	err = symlink.New("/bin/true", filepath.Join(s.tmpdir, pm.PackageQuery))
	c.Assert(err, jc.ErrorIsNil)
	s.PatchValue(&isPackageInstalled, func(pack string) bool {
		pacman, err := manager.NewPackageManager(series.HostSeries())
		c.Assert(err, jc.ErrorIsNil)
		return pacman.IsInstalled(pack)
	})
}
Beispiel #3
0
func (*SymlinkSuite) TestReplace(c *gc.C) {
	target, err := symlink.GetLongPathAsString(c.MkDir())
	c.Assert(err, gc.IsNil)
	target_second, err := symlink.GetLongPathAsString(c.MkDir())
	c.Assert(err, gc.IsNil)
	link := filepath.Join(target, "link")

	_, err = os.Stat(target)
	c.Assert(err, gc.IsNil)
	_, err = os.Stat(target_second)
	c.Assert(err, gc.IsNil)

	err = symlink.New(target, link)
	c.Assert(err, gc.IsNil)

	link_target, err := symlink.Read(link)
	c.Assert(err, gc.IsNil)
	c.Assert(link_target, gc.Equals, filepath.FromSlash(target))

	err = symlink.Replace(link, target_second)
	c.Assert(err, gc.IsNil)

	link_target, err = symlink.Read(link)
	c.Assert(err, gc.IsNil)
	c.Assert(link_target, gc.Equals, filepath.FromSlash(target_second))
}
Beispiel #4
0
func (s *MachineSuite) TestMachineAgentSymlinkJujuRunExists(c *gc.C) {
	if runtime.GOOS == "windows" {
		// Cannot make symlink to nonexistent file on windows or
		// create a file point a symlink to it then remove it
		c.Skip("Cannot test this on windows")
	}

	stm, _, _ := s.primeAgent(c, state.JobManageModel)
	a := s.newAgent(c, stm)
	defer a.Stop()

	// Pre-create the symlinks, but pointing to the incorrect location.
	links := []string{jujuRun, jujuDumpLogs}
	a.rootDir = c.MkDir()
	for _, link := range links {
		fullLink := utils.EnsureBaseDir(a.rootDir, link)
		c.Assert(os.MkdirAll(filepath.Dir(fullLink), os.FileMode(0755)), jc.ErrorIsNil)
		c.Assert(symlink.New("/nowhere/special", fullLink), jc.ErrorIsNil, gc.Commentf(link))
	}

	// Start the agent and wait for it be running.
	_, done := s.waitForOpenState(c, a)

	// juju-run symlink should have been recreated.
	for _, link := range links {
		fullLink := utils.EnsureBaseDir(a.rootDir, link)
		linkTarget, err := symlink.Read(fullLink)
		c.Assert(err, jc.ErrorIsNil)
		c.Assert(linkTarget, gc.Not(gc.Equals), "/nowhere/special", gc.Commentf(link))
	}

	s.waitStopped(c, state.JobManageModel, a, done)
}
Beispiel #5
0
func (s *ToolsSuite) SetUpTest(c *gc.C) {
	s.dataDir = c.MkDir()
	s.toolsDir = tools.SharedToolsDir(s.dataDir, version.Current)
	err := os.MkdirAll(s.toolsDir, 0755)
	c.Assert(err, gc.IsNil)
	err = symlink.New(s.toolsDir, tools.ToolsDir(s.dataDir, "unit-u-123"))
	c.Assert(err, gc.IsNil)
}
Beispiel #6
0
func (a *MachineAgent) createJujuRun(dataDir string) error {
	// TODO do not remove the symlink if it already points
	// to the right place.
	if err := os.Remove(jujuRun); err != nil && !os.IsNotExist(err) {
		return err
	}
	jujud := filepath.Join(dataDir, "tools", a.Tag().String(), jujunames.Jujud)
	return symlink.New(jujud, jujuRun)
}
Beispiel #7
0
func (s *prereqsSuite) TestJujuLocalPrereq(c *gc.C) {
	err := os.Remove(filepath.Join(s.tmpdir, "dpkg-query"))
	c.Assert(err, gc.IsNil)
	err = symlink.New("/bin/false", filepath.Join(s.tmpdir, "dpkg-query"))
	c.Assert(err, gc.IsNil)

	err = VerifyPrerequisites(instance.LXC)
	c.Assert(err, gc.ErrorMatches, "(.|\n)*juju-local must be installed to enable the local provider(.|\n)*")
	c.Assert(err, gc.ErrorMatches, "(.|\n)*apt-get install juju-local(.|\n)*")
}
Beispiel #8
0
func (s *ToolsSuite) SetUpTest(c *gc.C) {
	s.dataDir = c.MkDir()
	s.toolsDir = tools.SharedToolsDir(s.dataDir, version.Binary{
		Number: version.Current,
		Arch:   arch.HostArch(),
		Series: series.HostSeries(),
	})
	err := os.MkdirAll(s.toolsDir, 0755)
	c.Assert(err, jc.ErrorIsNil)
	err = symlink.New(s.toolsDir, tools.ToolsDir(s.dataDir, "unit-u-123"))
	c.Assert(err, jc.ErrorIsNil)
}
Beispiel #9
0
func (s *prereqsSuite) TestJujuLocalPrereq(c *gc.C) {

	pm, err := testing.GetPackageManager()
	c.Assert(err, jc.ErrorIsNil)

	err = os.Remove(filepath.Join(s.tmpdir, pm.PackageQuery))
	c.Assert(err, jc.ErrorIsNil)
	err = symlink.New("/bin/false", filepath.Join(s.tmpdir, pm.PackageQuery))
	c.Assert(err, jc.ErrorIsNil)

	err = VerifyPrerequisites(instance.LXC)
	c.Assert(err, gc.ErrorMatches, "(.|\n)*juju-local must be installed to enable the local provider(.|\n)*")
	c.Assert(err, gc.ErrorMatches, "(.|\n)*apt-get install juju-local(.|\n)*")
}
Beispiel #10
0
func (s *MachineSuite) TestMachineAgentSymlinkJujuRunExists(c *gc.C) {
	err := symlink.New("/nowhere/special", jujuRun)
	c.Assert(err, gc.IsNil)
	_, err = os.Stat(jujuRun)
	c.Assert(err, jc.Satisfies, os.IsNotExist)
	s.assertJobWithAPI(c, state.JobManageEnviron, func(conf agent.Config, st *api.State) {
		// juju-run should have been recreated
		_, err := os.Stat(jujuRun)
		c.Assert(err, gc.IsNil)
		link, err := symlink.Read(jujuRun)
		c.Assert(err, gc.IsNil)
		c.Assert(link, gc.Not(gc.Equals), "/nowhere/special")
	})
}
Beispiel #11
0
func (*SymlinkSuite) TestCreateSymLink(c *gc.C) {
	target, err := symlink.GetLongPathAsString(c.MkDir())
	c.Assert(err, gc.IsNil)

	link := filepath.Join(target, "link")

	_, err = os.Stat(target)
	c.Assert(err, gc.IsNil)

	err = symlink.New(target, link)
	c.Assert(err, gc.IsNil)

	link, err = symlink.Read(link)
	c.Assert(err, gc.IsNil)
	c.Assert(link, gc.Equals, filepath.FromSlash(target))
}
Beispiel #12
0
// EnsureJujucSymlinks creates a symbolic link to jujuc within dir for each
// hook command. If the commands already exist, this operation does nothing.
func EnsureJujucSymlinks(dir string) (err error) {
	for _, name := range jujuc.CommandNames() {
		// The link operation fails when the target already exists,
		// so this is a no-op when the command names already
		// exist.
		err := symlink.New("./jujud", filepath.Join(dir, name))
		if err == nil {
			continue
		}
		// TODO(rog) drop LinkError check when fix is released (see http://codereview.appspot.com/6442080/)
		if e, ok := err.(*os.LinkError); !ok || !os.IsExist(e.Err) {
			return fmt.Errorf("cannot initialize hook commands in %q: %v", dir, err)
		}
	}
	return nil
}
Beispiel #13
0
func (s *BaseRepoSuite) SetUpTest(c *gc.C) {
	// Set up a local repository.
	s.RepoPath = os.Getenv("JUJU_REPOSITORY")
	repoPath := c.MkDir()
	os.Setenv("JUJU_REPOSITORY", repoPath)
	s.SeriesPath = filepath.Join(repoPath, config.LatestLtsSeries())
	c.Assert(os.Mkdir(s.SeriesPath, 0777), jc.ErrorIsNil)
	// Create a symlink "quantal" -> "precise", because most charms
	// and machines are written with hard-coded "quantal" series,
	// hence they interact badly with a local repository that assumes
	// only "precise" charms are available.
	err := symlink.New(s.SeriesPath, filepath.Join(repoPath, "quantal"))
	c.Assert(err, jc.ErrorIsNil)
	s.BundlesPath = filepath.Join(repoPath, "bundle")
	c.Assert(os.Mkdir(s.BundlesPath, 0777), jc.ErrorIsNil)
}
Beispiel #14
0
func (*SymlinkSuite) TestIsSymlinkFolder(c *gc.C) {
	target, err := symlink.GetLongPathAsString(c.MkDir())
	c.Assert(err, gc.IsNil)

	link := filepath.Join(target, "link")

	_, err = os.Stat(target)
	c.Assert(err, gc.IsNil)

	err = symlink.New(target, link)
	c.Assert(err, gc.IsNil)

	isSymlink, err := symlink.IsSymlink(link)
	c.Assert(err, gc.IsNil)
	c.Assert(isSymlink, jc.IsTrue)
}
Beispiel #15
0
// ChangeAgentTools atomically replaces the agent-specific symlink
// under dataDir so it points to the previously unpacked
// version vers. It returns the new tools read.
func ChangeAgentTools(dataDir string, agentName string, vers version.Binary) (*coretools.Tools, error) {
	tools, err := ReadTools(dataDir, vers)
	if err != nil {
		return nil, err
	}
	tmpName := ToolsDir(dataDir, "tmplink-"+agentName)
	err = symlink.New(tools.Version.String(), tmpName)
	if err != nil {
		return nil, fmt.Errorf("cannot create tools symlink: %v", err)
	}
	err = os.Rename(tmpName, ToolsDir(dataDir, agentName))
	if err != nil {
		return nil, fmt.Errorf("cannot update tools symlink: %v", err)
	}
	return tools, nil
}
Beispiel #16
0
func (s *GitDeployerSuite) TestUpgrade(c *gc.C) {
	// Install.
	info1 := s.bundles.AddCustomBundle(c, corecharm.MustParseURL("cs:s/c-1"), func(path string) {
		err := ioutil.WriteFile(filepath.Join(path, "some-file"), []byte("hello"), 0644)
		c.Assert(err, jc.ErrorIsNil)
		err = symlink.New("./some-file", filepath.Join(path, "a-symlink"))
		c.Assert(err, jc.ErrorIsNil)
	})
	err := s.deployer.Stage(info1, nil)
	c.Assert(err, jc.ErrorIsNil)
	err = s.deployer.Deploy()
	c.Assert(err, jc.ErrorIsNil)

	// Upgrade.
	info2 := s.bundles.AddCustomBundle(c, corecharm.MustParseURL("cs:s/c-2"), func(path string) {
		err := ioutil.WriteFile(filepath.Join(path, "some-file"), []byte("goodbye"), 0644)
		c.Assert(err, jc.ErrorIsNil)
		err = ioutil.WriteFile(filepath.Join(path, "a-symlink"), []byte("not any more!"), 0644)
		c.Assert(err, jc.ErrorIsNil)
	})
	err = s.deployer.Stage(info2, nil)
	c.Assert(err, jc.ErrorIsNil)
	checkCleanup(c, s.deployer)
	err = s.deployer.Deploy()
	c.Assert(err, jc.ErrorIsNil)
	checkCleanup(c, s.deployer)

	// Check content.
	data, err := ioutil.ReadFile(filepath.Join(s.targetPath, "some-file"))
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(string(data), gc.Equals, "goodbye")
	data, err = ioutil.ReadFile(filepath.Join(s.targetPath, "a-symlink"))
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(string(data), gc.Equals, "not any more!")

	target := charm.NewGitDir(s.targetPath)
	url, err := target.ReadCharmURL()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(url, gc.DeepEquals, corecharm.MustParseURL("cs:s/c-2"))
	lines, err := target.Log()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(lines, gc.HasLen, 5)
	c.Assert(lines[0], gc.Matches, `[0-9a-f]{7} Upgraded charm to "cs:s/c-2".`)
}
Beispiel #17
0
func (s *prereqsSuite) SetUpTest(c *gc.C) {
	s.BaseSuite.SetUpTest(c)
	s.tmpdir = c.MkDir()
	s.testMongodPath = filepath.Join(s.tmpdir, "mongod")

	s.PatchEnvironment("PATH", s.tmpdir)

	s.PatchValue(&mongo.JujuMongodPath, "/somewhere/that/wont/exist")

	os.Setenv("JUJUTEST_LSB_RELEASE_ID", "Ubuntu")
	err := ioutil.WriteFile(filepath.Join(s.tmpdir, "lsb_release"), []byte(lsbrelease), 0777)
	c.Assert(err, gc.IsNil)

	// symlink $temp/dpkg-query to /bin/true, to
	// simulate package installation query responses.
	err = symlink.New("/bin/true", filepath.Join(s.tmpdir, "dpkg-query"))
	c.Assert(err, gc.IsNil)
	s.PatchValue(&isPackageInstalled, apt.IsPackageInstalled)
}
Beispiel #18
0
func autostartContainer(name string) error {
	// Now symlink the config file into the restart directory, if it exists.
	// This is for backwards compatiblity. From Trusty onwards, the auto start
	// option should be set in the LXC config file, this is done in the networkConfigTemplate
	// function below.
	if useRestartDir() {
		if err := symlink.New(
			containerConfigFilename(name),
			restartSymlink(name),
		); err != nil {
			return err
		}
		logger.Tracef("auto-restart link created")
	} else {
		logger.Tracef("Setting auto start to true in lxc config.")
		return appendToContainerConfig(name, "lxc.start.auto = 1\n")
	}
	return nil
}
Beispiel #19
0
func (*SymlinkSuite) TestIsSymlinkFile(c *gc.C) {
	dir, err := symlink.GetLongPathAsString(c.MkDir())
	c.Assert(err, gc.IsNil)

	target := filepath.Join(dir, "file")
	err = ioutil.WriteFile(target, []byte("TOP SECRET"), 0644)
	c.Assert(err, gc.IsNil)

	link := filepath.Join(dir, "link")

	_, err = os.Stat(target)
	c.Assert(err, gc.IsNil)

	err = symlink.New(target, link)
	c.Assert(err, gc.IsNil)

	isSymlink, err := symlink.IsSymlink(link)
	c.Assert(err, gc.IsNil)
	c.Assert(isSymlink, jc.IsTrue)
}
Beispiel #20
0
func (s *RepoSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)
	// Change the environ's config to ensure we're using the one in state,
	// not the one in the local environments.yaml
	updateAttrs := map[string]interface{}{"default-series": config.LatestLtsSeries()}
	err := s.State.UpdateEnvironConfig(updateAttrs, nil, nil)
	c.Assert(err, jc.ErrorIsNil)
	s.RepoPath = os.Getenv("JUJU_REPOSITORY")
	repoPath := c.MkDir()
	os.Setenv("JUJU_REPOSITORY", repoPath)
	s.SeriesPath = filepath.Join(repoPath, config.LatestLtsSeries())
	err = os.Mkdir(s.SeriesPath, 0777)
	c.Assert(err, jc.ErrorIsNil)
	// Create a symlink "quantal" -> "precise", because most charms
	// and machines are written with hard-coded "quantal" series,
	// hence they interact badly with a local repository that assumes
	// only "precise" charms are available.
	err = symlink.New(s.SeriesPath, filepath.Join(repoPath, "quantal"))
	c.Assert(err, jc.ErrorIsNil)
}
Beispiel #21
0
func (s *UpstartSuite) TestInstallAlreadyRunning(c *gc.C) {
	pathTo := func(name string) string {
		return filepath.Join(s.testPath, name)
	}
	s.MakeTool(c, "status-stopped", `echo "some-service stop/waiting"`)
	s.MakeTool(c, "status-started", `echo "some-service start/running, process 123"`)
	s.MakeTool(c, "stop", fmt.Sprintf(
		"rm %s; ln -s %s %s",
		pathTo("status"), pathTo("status-stopped"), pathTo("status"),
	))
	s.MakeTool(c, "start", fmt.Sprintf(
		"rm %s; ln -s %s %s",
		pathTo("status"), pathTo("status-started"), pathTo("status"),
	))
	err := symlink.New(pathTo("status-started"), pathTo("status"))
	c.Assert(err, gc.IsNil)

	conf := s.dummyConf(c)
	err = conf.Install()
	c.Assert(err, gc.IsNil)
	c.Assert(&conf.Service, jc.Satisfies, (*upstart.Service).Running)
}
Beispiel #22
0
func (*SymlinkSuite) TestReadData(c *gc.C) {
	dir := c.MkDir()
	sub := filepath.Join(dir, "sub")

	err := os.Mkdir(sub, 0700)
	c.Assert(err, gc.IsNil)

	oldname := filepath.Join(sub, "foo")
	data := []byte("data")

	err = ioutil.WriteFile(oldname, data, 0644)
	c.Assert(err, gc.IsNil)

	newname := filepath.Join(dir, "bar")
	err = symlink.New(oldname, newname)
	c.Assert(err, gc.IsNil)

	b, err := ioutil.ReadFile(newname)
	c.Assert(err, gc.IsNil)

	c.Assert(string(b), gc.Equals, string(data))
}
Beispiel #23
0
func (a *MachineAgent) createSymlink(target, link string) error {
	fullLink := utils.EnsureBaseDir(a.rootDir, link)

	currentTarget, err := symlink.Read(fullLink)
	if err != nil && !os.IsNotExist(err) {
		return err
	} else if err == nil {
		// Link already in place - check it.
		if currentTarget == target {
			// Link already points to the right place - nothing to do.
			return nil
		}
		// Link points to the wrong place - delete it.
		if err := os.Remove(fullLink); err != nil {
			return err
		}
	}

	if err := os.MkdirAll(filepath.Dir(fullLink), os.FileMode(0755)); err != nil {
		return err
	}
	return symlink.New(target, fullLink)
}
Beispiel #24
0
// EnsureSymlinks creates a symbolic link to jujuc within dir for each
// hook command. If the commands already exist, this operation does nothing.
// If dir is a symbolic link, it will be dereferenced first.
func EnsureSymlinks(dir string) (err error) {
	logger.Infof("ensure jujuc symlinks in %s", dir)
	defer func() {
		if err != nil {
			err = errors.Annotatef(err, "cannot initialize hook commands in %q", dir)
		}
	}()
	isSymlink, err := symlink.IsSymlink(dir)
	if err != nil {
		return err
	}
	if isSymlink {
		link, err := symlink.Read(dir)
		if err != nil {
			return err
		}
		if !filepath.IsAbs(link) {
			logger.Infof("%s is relative", link)
			link = filepath.Join(filepath.Dir(dir), link)
		}
		dir = link
		logger.Infof("was a symlink, now looking at %s", dir)
	}

	jujudPath := filepath.Join(dir, names.Jujud)
	logger.Debugf("jujud path %s", jujudPath)
	for _, name := range CommandNames() {
		// The link operation fails when the target already exists,
		// so this is a no-op when the command names already
		// exist.
		err := symlink.New(jujudPath, filepath.Join(dir, name))
		if err != nil && !os.IsExist(err) {
			return err
		}
	}
	return nil
}
Beispiel #25
0
func (s *UpstartSuite) TestInstallAlreadyRunning(c *gc.C) {
	pathTo := func(name string) string {
		return filepath.Join(s.testPath, name)
	}
	s.MakeTool(c, "status-stopped", `echo "some-application stop/waiting"`)
	s.MakeTool(c, "status-started", `echo "some-application start/running, process 123"`)
	s.MakeTool(c, "stop", fmt.Sprintf(
		"rm %s; ln -s %s %s",
		pathTo("status"), pathTo("status-stopped"), pathTo("status"),
	))
	s.MakeTool(c, "start", fmt.Sprintf(
		"rm %s; ln -s %s %s",
		pathTo("status"), pathTo("status-started"), pathTo("status"),
	))
	err := symlink.New(pathTo("status-started"), pathTo("status"))
	c.Assert(err, jc.ErrorIsNil)

	svc := upstart.NewService("some-application", s.dummyConf(c))
	err = svc.Install()
	c.Assert(err, jc.ErrorIsNil)
	installed, err := svc.Running()
	c.Assert(err, jc.ErrorIsNil)
	c.Check(installed, jc.IsTrue)
}
Beispiel #26
0
func (d *gitDeployer) Stage(info BundleInfo, abort <-chan struct{}) error {
	// Make sure we've got an actual bundle available.
	bundle, err := d.bundles.Read(info, abort)
	if err != nil {
		return err
	}

	// Read present state of current.
	if err := os.MkdirAll(d.dataPath, 0755); err != nil {
		return err
	}
	defer collectGitOrphans(d.dataPath)
	srcExists, err := d.current.Exists()
	if err != nil {
		return err
	}
	url := info.URL()
	if srcExists {
		prevURL, err := d.current.ReadCharmURL()
		if err != nil {
			return err
		}
		if *url == *prevURL {
			return nil
		}
	}

	// Prepare a fresh repository for the update, using current's history
	// if it exists.
	updatePath, err := d.newDir(gitUpdatePrefix)
	if err != nil {
		return err
	}
	var repo *GitDir
	if srcExists {
		repo, err = d.current.Clone(updatePath)
	} else {
		repo = NewGitDir(updatePath)
		err = repo.Init()
	}
	if err != nil {
		return err
	}

	// Write the desired new state and commit.
	if err = bundle.ExpandTo(updatePath); err != nil {
		return err
	}
	if err = repo.WriteCharmURL(url); err != nil {
		return err
	}
	if err = repo.Snapshotf("Imported charm %q.", url); err != nil {
		return err
	}

	// Atomically rename fresh repository to current.
	tmplink := filepath.Join(updatePath, "tmplink")
	if err = symlink.New(updatePath, tmplink); err != nil {
		return err
	}
	return os.Rename(tmplink, d.current.Path())
}
Beispiel #27
0
// finishBootstrap converts the machine config to cloud-config,
// converts that to a script, and then executes it locally.
func (env *localEnviron) finishBootstrap(ctx environs.BootstrapContext, icfg *instancecfg.InstanceConfig) error {
	icfg.InstanceId = bootstrapInstanceId
	icfg.DataDir = env.config.rootDir()
	icfg.LogDir = fmt.Sprintf("/var/log/juju-%s", env.config.namespace())
	icfg.CloudInitOutputLog = filepath.Join(icfg.DataDir, "cloud-init-output.log")

	// No JobManageNetworking added in order not to change the network
	// configuration of the user's machine.
	icfg.Jobs = []multiwatcher.MachineJob{multiwatcher.JobManageEnviron}

	icfg.MachineAgentServiceName = env.machineAgentServiceName()
	icfg.AgentEnvironment = map[string]string{
		agent.Namespace: env.config.namespace(),
		agent.LxcBridge: env.config.networkBridge(),

		// The local provider only supports a single state server,
		// so we make the oplog size to a small value. This makes
		// the preallocation faster with no disadvantage.
		agent.MongoOplogSize: "1", // 1MB
	}

	if err := instancecfg.FinishInstanceConfig(icfg, env.Config()); err != nil {
		return errors.Trace(err)
	}

	// Since Juju's state machine is currently the host machine
	// for local providers, don't stomp on it.
	cfgAttrs := env.config.AllAttrs()
	if val, ok := cfgAttrs["enable-os-refresh-update"].(bool); !ok {
		logger.Infof("local provider; disabling refreshing OS updates.")
		icfg.EnableOSRefreshUpdate = false
	} else {
		icfg.EnableOSRefreshUpdate = val
	}
	if val, ok := cfgAttrs["enable-os-upgrade"].(bool); !ok {
		logger.Infof("local provider; disabling OS upgrades.")
		icfg.EnableOSUpgrade = false
	} else {
		icfg.EnableOSUpgrade = val
	}

	// don't write proxy or mirror settings for local machine
	icfg.AptProxySettings = proxy.Settings{}
	icfg.ProxySettings = proxy.Settings{}
	icfg.AptMirror = ""

	cloudcfg, err := cloudinit.New(icfg.Series)
	if err != nil {
		return errors.Trace(err)
	}
	cloudcfg.SetSystemUpdate(icfg.EnableOSRefreshUpdate)
	cloudcfg.SetSystemUpgrade(icfg.EnableOSUpgrade)

	localLogDir := filepath.Join(icfg.DataDir, "log")
	if err := os.RemoveAll(localLogDir); err != nil {
		return errors.Trace(err)
	}
	if err := symlink.New(icfg.LogDir, localLogDir); err != nil {
		return errors.Trace(err)
	}
	if err := os.Remove(icfg.CloudInitOutputLog); err != nil && !os.IsNotExist(err) {
		return errors.Trace(err)
	}
	cloudcfg.AddScripts(
		fmt.Sprintf("rm -fr %s", icfg.LogDir),
	)
	udata, err := cloudconfig.NewUserdataConfig(icfg, cloudcfg)
	if err != nil {
		return errors.Trace(err)
	}
	if err := udata.ConfigureJuju(); err != nil {
		return errors.Trace(err)
	}
	return executeCloudConfig(ctx, icfg, cloudcfg)
}
Beispiel #28
0
func migrateLocalProviderAgentConfig(context Context) error {
	st := context.State()
	if st == nil {
		logger.Debugf("no state connection, no migration required")
		// We're running on a different node than the state server.
		return nil
	}
	envConfig, err := st.EnvironConfig()
	if err != nil {
		return fmt.Errorf("failed to read current config: %v", err)
	}
	if !isLocalEnviron(envConfig) {
		logger.Debugf("not a local environment, no migration required")
		return nil
	}
	attrs := envConfig.AllAttrs()
	rootDir, _ := attrs["root-dir"].(string)
	sharedStorageDir := filepath.Join(rootDir, "shared-storage")
	// In case these two are empty we need to set them and update the
	// environment config.
	namespace, _ := attrs["namespace"].(string)
	container, _ := attrs["container"].(string)

	if namespace == "" {
		username := os.Getenv("USER")
		if username == "root" {
			// sudo was probably called, get the original user.
			username = os.Getenv("SUDO_USER")
		}
		if username == "" {
			return fmt.Errorf("cannot get current user from the environment: %v", os.Environ())
		}
		namespace = username + "-" + envConfig.Name()
	}
	if container == "" {
		container = "lxc"
	}

	dataDir := rootDir
	localLogDir := filepath.Join(rootDir, "log")
	metricSpoolDir := filepath.Join(rootDir, "metricspool")
	uniterStateDir := filepath.Join(rootDir, "uniter", "state")
	// rsyslogd is restricted to write to /var/log
	logDir := fmt.Sprintf("%s/juju-%s", rootLogDir, namespace)
	jobs := []multiwatcher.MachineJob{multiwatcher.JobManageEnviron}
	values := map[string]string{
		agent.Namespace: namespace,
		// ContainerType is empty on the bootstrap node.
		agent.ContainerType:    "",
		agent.AgentServiceName: "juju-agent-" + namespace,
	}
	deprecatedValues := []string{
		"SHARED_STORAGE_ADDR",
		"SHARED_STORAGE_DIR",
	}

	// Remove shared-storage dir if there.
	if err := os.RemoveAll(sharedStorageDir); err != nil {
		return fmt.Errorf("cannot remove deprecated %q: %v", sharedStorageDir, err)
	}

	// We need to create the dirs if they don't exist.
	if err := os.MkdirAll(dataDir, 0755); err != nil {
		return fmt.Errorf("cannot create dataDir %q: %v", dataDir, err)
	}
	// We always recreate the logDir to make sure it's empty.
	if err := os.RemoveAll(logDir); err != nil {
		return fmt.Errorf("cannot remove logDir %q: %v", logDir, err)
	}
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return fmt.Errorf("cannot create logDir %q: %v", logDir, err)
	}
	if err := os.MkdirAll(metricSpoolDir, 0755); err != nil {
		return fmt.Errorf("cannot create metricSpoolDir %q: %v", metricSpoolDir, err)
	}
	if err := os.MkdirAll(uniterStateDir, 0755); err != nil {
		return fmt.Errorf("cannot create uniterStateDir %q: %v", uniterStateDir, err)
	}
	// Reconfigure rsyslog as needed:
	// 1. logDir must be owned by syslog:adm
	// 2. Remove old rsyslog spool config
	// 3. Relink logs to the new logDir
	if err := chownPath(logDir, "syslog"); err != nil {
		return err
	}
	spoolConfig := fmt.Sprintf("%s/machine-0-%s", rootSpoolDir, namespace)
	if err := os.RemoveAll(spoolConfig); err != nil {
		return fmt.Errorf("cannot remove %q: %v", spoolConfig, err)
	}
	allMachinesLog := filepath.Join(logDir, "all-machines.log")
	if err := symlink.New(allMachinesLog, localLogDir+"/"); err != nil && !os.IsExist(err) {
		return fmt.Errorf("cannot symlink %q to %q: %v", allMachinesLog, localLogDir, err)
	}
	machine0Log := filepath.Join(localLogDir, "machine-0.log")
	if err := symlink.New(machine0Log, logDir+"/"); err != nil && !os.IsExist(err) {
		return fmt.Errorf("cannot symlink %q to %q: %v", machine0Log, logDir, err)
	}

	newCfg := map[string]interface{}{
		"namespace": namespace,
		"container": container,
	}
	if err := st.UpdateEnvironConfig(newCfg, nil, nil); err != nil {
		return fmt.Errorf("cannot update environment config: %v", err)
	}

	return context.AgentConfig().Migrate(agent.MigrateParams{
		Paths: agent.Paths{
			DataDir:         dataDir,
			LogDir:          logDir,
			MetricsSpoolDir: metricSpoolDir,
		},
		Jobs:         jobs,
		Values:       values,
		DeleteValues: deprecatedValues,
	})
}
Beispiel #29
0
func (s *ToolsSuite) TestEnsureSymlinksSymlinkedDir(c *gc.C) {
	toolsDirSymlink := filepath.Join(c.MkDir(), "unit-ubuntu-0")
	err := symlink.New(s.toolsDir, toolsDirSymlink)
	c.Assert(err, jc.ErrorIsNil)
	s.testEnsureSymlinks(c, toolsDirSymlink)
}