Beispiel #1
0
func (s *imageURLSuite) TestImageURL(c *gc.C) {
	imageURLGetter := container.NewImageURLGetter("host:port", "12345", []byte("cert"))
	imageURL, err := imageURLGetter.ImageURL(instance.LXC, "trusty", "amd64")
	c.Assert(err, gc.IsNil)
	c.Assert(imageURL, gc.Equals, "https://host:port/environment/12345/images/lxc/trusty/amd64/trusty-released-amd64-root.tar.gz")
	c.Assert(imageURLGetter.CACert(), gc.DeepEquals, []byte("cert"))
}
Beispiel #2
0
func (s *imageURLSuite) assertImageURLForStream(c *gc.C, stream string) {
	imageURLGetter := container.NewImageURLGetter(
		container.ImageURLGetterConfig{
			ServerRoot:        "host:port",
			ModelUUID:         "12345",
			CACert:            []byte("cert"),
			CloudimgBaseUrl:   "",
			Stream:            stream,
			ImageDownloadFunc: container.ImageDownloadURL,
		})
	imageURL, err := imageURLGetter.ImageURL(instance.LXC, "trusty", "amd64")
	c.Assert(err, gc.IsNil)
	c.Assert(imageURL, gc.Equals, fmt.Sprintf("https://host:port/model/12345/images/lxc/trusty/amd64/trusty-%s-amd64-root.tar.gz", stream))
	c.Assert(imageURLGetter.CACert(), gc.DeepEquals, []byte("cert"))
}
Beispiel #3
0
func (s *imageURLSuite) TestImageURLOtherBase(c *gc.C) {
	var calledBaseURL string
	baseURL := "other://cloud-images"
	mockFunc := func(kind instance.ContainerType, series, arch, cloudimgBaseUrl string) (string, error) {
		calledBaseURL = cloudimgBaseUrl
		return "omg://wat/trusty-released-amd64-root.tar.gz", nil
	}
	imageURLGetter := container.NewImageURLGetter(
		container.ImageURLGetterConfig{
			"host:port", "12345", []byte("cert"), baseURL, mockFunc,
		})
	imageURL, err := imageURLGetter.ImageURL(instance.LXC, "trusty", "amd64")
	c.Assert(err, gc.IsNil)
	c.Assert(imageURL, gc.Equals, "https://host:port/model/12345/images/lxc/trusty/amd64/trusty-released-amd64-root.tar.gz")
	c.Assert(imageURLGetter.CACert(), gc.DeepEquals, []byte("cert"))
	c.Assert(calledBaseURL, gc.Equals, baseURL)
}
Beispiel #4
0
// SetConfig is specified in the Environ interface.
func (env *localEnviron) SetConfig(cfg *config.Config) error {
	ecfg, err := providerInstance.newConfig(cfg)
	if err != nil {
		logger.Errorf("failed to create new environ config: %v", err)
		return errors.Trace(err)
	}
	env.localMutex.Lock()
	defer env.localMutex.Unlock()
	env.config = ecfg
	env.name = ecfg.Name()
	containerType := ecfg.container()
	managerConfig := container.ManagerConfig{
		container.ConfigName:   env.config.namespace(),
		container.ConfigLogDir: env.config.logDir(),
	}
	var imageURLGetter container.ImageURLGetter
	if containerType == instance.LXC {
		if useLxcClone, ok := cfg.LXCUseClone(); ok {
			managerConfig["use-clone"] = fmt.Sprint(useLxcClone)
		}
		if useLxcCloneAufs, ok := cfg.LXCUseCloneAUFS(); ok {
			managerConfig["use-aufs"] = fmt.Sprint(useLxcCloneAufs)
		}
		// For lxc containers, we cache image tarballs in the environment storage, so here
		// we construct a URL getter.
		if uuid, ok := ecfg.UUID(); ok {
			var caCert []byte = nil
			if cert, ok := cfg.CACert(); ok {
				caCert = []byte(cert)
			}
			baseUrl := ecfg.CloudImageBaseURL()

			imageURLGetter = container.NewImageURLGetter(
				// Explicitly call the non-named constructor so if anyone
				// adds additional fields, this fails.
				container.ImageURLGetterConfig{
					ecfg.stateServerAddr(), uuid, caCert, baseUrl,
					container.ImageDownloadURL,
				})

		}
	}
	env.containerManager, err = factory.NewContainerManager(
		containerType, managerConfig, imageURLGetter)
	if err != nil {
		return errors.Trace(err)
	}

	// When the localEnviron value is created on the client
	// side, the bootstrap-ip attribute will not exist,
	// because it is only set *within* the running
	// environment, not in the configuration created by
	// Prepare.
	if addr := ecfg.bootstrapIPAddress(); addr != "" {
		env.bridgeAddress = addr
		return nil
	}
	// If we get to here, it is because we haven't yet bootstrapped an
	// environment, and saved the config in it, or we are running a command
	// from the command line, so it is ok to work on the assumption that we
	// have direct access to the directories.
	if err := env.config.createDirs(); err != nil {
		return errors.Trace(err)
	}
	// Record the network bridge address and create a filestorage.
	if err := env.resolveBridgeAddress(cfg); err != nil {
		return errors.Trace(err)
	}
	return nil
}
Beispiel #5
0
// updateSupportedContainers records in state that a machine can run the specified containers.
// It starts a watcher and when a container of a given type is first added to the machine,
// the watcher is killed, the machine is set up to be able to start containers of the given type,
// and a suitable provisioner is started.
func (a *MachineAgent) updateSupportedContainers(
	runner worker.Runner,
	st api.Connection,
	containers []instance.ContainerType,
	agentConfig agent.Config,
) error {
	pr := st.Provisioner()
	tag := agentConfig.Tag().(names.MachineTag)
	machine, err := pr.Machine(tag)
	if errors.IsNotFound(err) || err == nil && machine.Life() == params.Dead {
		return worker.ErrTerminateAgent
	}
	if err != nil {
		return errors.Annotatef(err, "cannot load machine %s from state", tag)
	}
	if len(containers) == 0 {
		if err := machine.SupportsNoContainers(); err != nil {
			return errors.Annotatef(err, "clearing supported containers for %s", tag)
		}
		return nil
	}
	if err := machine.SetSupportedContainers(containers...); err != nil {
		return errors.Annotatef(err, "setting supported containers for %s", tag)
	}
	initLock, err := cmdutil.HookExecutionLock(agentConfig.DataDir())
	if err != nil {
		return err
	}
	// Start the watcher to fire when a container is first requested on the machine.
	modelUUID, err := st.ModelTag()
	if err != nil {
		return err
	}
	watcherName := fmt.Sprintf("%s-container-watcher", machine.Id())
	// There may not be a CA certificate private key available, and without
	// it we can't ensure that other Juju nodes can connect securely, so only
	// use an image URL getter if there's a private key.
	var imageURLGetter container.ImageURLGetter
	if agentConfig.Value(agent.AllowsSecureConnection) == "true" {
		cfg, err := pr.ModelConfig()
		if err != nil {
			return errors.Annotate(err, "unable to get environ config")
		}
		imageURLGetter = container.NewImageURLGetter(
			// Explicitly call the non-named constructor so if anyone
			// adds additional fields, this fails.
			container.ImageURLGetterConfig{
				ServerRoot:        st.Addr(),
				ModelUUID:         modelUUID.Id(),
				CACert:            []byte(agentConfig.CACert()),
				CloudimgBaseUrl:   cfg.CloudImageBaseURL(),
				Stream:            cfg.ImageStream(),
				ImageDownloadFunc: container.ImageDownloadURL,
			})
	}
	params := provisioner.ContainerSetupParams{
		Runner:              runner,
		WorkerName:          watcherName,
		SupportedContainers: containers,
		ImageURLGetter:      imageURLGetter,
		Machine:             machine,
		Provisioner:         pr,
		Config:              agentConfig,
		InitLock:            initLock,
	}
	handler := provisioner.NewContainerSetupHandler(params)
	a.startWorkerAfterUpgrade(runner, watcherName, func() (worker.Worker, error) {
		w, err := watcher.NewStringsWorker(watcher.StringsConfig{
			Handler: handler,
		})
		if err != nil {
			return nil, errors.Annotatef(err, "cannot start %s worker", watcherName)
		}
		return w, nil
	})
	return nil
}