func (s *configureSuite) getCloudConfig(c *gc.C, stateServer bool, vers version.Binary) cloudinit.CloudConfig { var icfg *instancecfg.InstanceConfig var err error if stateServer { icfg, err = instancecfg.NewBootstrapInstanceConfig(constraints.Value{}, vers.Series) c.Assert(err, jc.ErrorIsNil) icfg.InstanceId = "instance-id" icfg.Jobs = []multiwatcher.MachineJob{multiwatcher.JobManageEnviron, multiwatcher.JobHostUnits} } else { icfg, err = instancecfg.NewInstanceConfig("0", "ya", imagemetadata.ReleasedStream, vers.Series, true, nil, nil, nil) c.Assert(err, jc.ErrorIsNil) icfg.Jobs = []multiwatcher.MachineJob{multiwatcher.JobHostUnits} } icfg.Tools = &tools.Tools{ Version: vers, URL: "http://testing.invalid/tools.tar.gz", } environConfig := testConfig(c, stateServer, vers) err = instancecfg.FinishInstanceConfig(icfg, environConfig) c.Assert(err, jc.ErrorIsNil) cloudcfg, err := cloudinit.New(icfg.Series) c.Assert(err, jc.ErrorIsNil) udata, err := cloudconfig.NewUserdataConfig(icfg, cloudcfg) c.Assert(err, jc.ErrorIsNil) err = udata.Configure() c.Assert(err, jc.ErrorIsNil) return cloudcfg }
func (s *CloudInitSuite) TestWindowsUserdataEncoding(c *gc.C) { series := "win8" metricsSpoolDir := must(paths.MetricsSpoolDir("win8")) toolsList := tools.List{ &tools.Tools{ URL: "http://foo.com/tools/released/juju1.2.3-win8-amd64.tgz", Version: version.MustParseBinary("1.2.3-win8-amd64"), Size: 10, SHA256: "1234", }, } dataDir, err := paths.DataDir(series) c.Assert(err, jc.ErrorIsNil) logDir, err := paths.LogDir(series) c.Assert(err, jc.ErrorIsNil) cfg := instancecfg.InstanceConfig{ ControllerTag: testing.ControllerTag, MachineId: "10", AgentEnvironment: map[string]string{agent.ProviderType: "dummy"}, Series: series, Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, MachineNonce: "FAKE_NONCE", APIInfo: &api.Info{ Addrs: []string{"state-addr.testing.invalid:54321"}, Password: "******", CACert: "CA CERT\n" + testing.CACert, Tag: names.NewMachineTag("10"), ModelTag: testing.ModelTag, }, MachineAgentServiceName: "jujud-machine-10", DataDir: dataDir, LogDir: path.Join(logDir, "juju"), MetricsSpoolDir: metricsSpoolDir, CloudInitOutputLog: path.Join(logDir, "cloud-init-output.log"), } err = cfg.SetTools(toolsList) c.Assert(err, jc.ErrorIsNil) ci, err := cloudinit.New("win8") c.Assert(err, jc.ErrorIsNil) udata, err := cloudconfig.NewUserdataConfig(&cfg, ci) c.Assert(err, jc.ErrorIsNil) err = udata.Configure() c.Assert(err, jc.ErrorIsNil) data, err := ci.RenderYAML() c.Assert(err, jc.ErrorIsNil) cicompose, err := cloudinit.New("win8") c.Assert(err, jc.ErrorIsNil) base64Data := base64.StdEncoding.EncodeToString(utils.Gzip(data)) got := []byte(fmt.Sprintf(cloudconfig.UserDataScript, base64Data)) expected, err := providerinit.ComposeUserData(&cfg, cicompose, openstack.OpenstackRenderer{}) c.Assert(err, jc.ErrorIsNil) c.Assert(string(got), gc.Equals, string(expected)) }
func (*instancecfgSuite) TestAgentVersion(c *gc.C) { var icfg instancecfg.InstanceConfig list := coretools.List{ &coretools.Tools{Version: version.MustParseBinary("2.3.4-trusty-amd64")}, } err := icfg.SetTools(list) c.Assert(err, jc.ErrorIsNil) c.Assert(icfg.AgentVersion(), gc.Equals, list[0].Version) }
func (*instancecfgSuite) TestSetToolsDifferentVersions(c *gc.C) { var icfg instancecfg.InstanceConfig list := coretools.List{ &coretools.Tools{Version: version.MustParseBinary("2.3.4-trusty-amd64")}, &coretools.Tools{Version: version.MustParseBinary("2.3.5-trusty-amd64")}, } err := icfg.SetTools(list) c.Assert(err, gc.ErrorMatches, `tools info mismatch.*2\.3\.4.*2\.3\.5.*`) c.Assert(icfg.ToolsList(), gc.HasLen, 0) }
func (*instancecfgSuite) TestSetToolsSameVersions(c *gc.C) { var icfg instancecfg.InstanceConfig list := coretools.List{ &coretools.Tools{Version: version.MustParseBinary("2.3.4-trusty-amd64")}, &coretools.Tools{Version: version.MustParseBinary("2.3.4-trusty-amd64")}, } err := icfg.SetTools(list) c.Assert(err, jc.ErrorIsNil) c.Assert(icfg.ToolsList(), jc.DeepEquals, list) }
func assocProvInfoAndMachCfg( provInfo *params.ProvisioningInfo, instanceConfig *instancecfg.InstanceConfig, ) *provisioningInfo { instanceConfig.Tags = provInfo.Tags if len(provInfo.Jobs) > 0 { instanceConfig.Jobs = provInfo.Jobs } return &provisioningInfo{ Constraints: provInfo.Constraints, Series: provInfo.Series, Placement: provInfo.Placement, InstanceConfig: instanceConfig, SubnetsToZones: provInfo.SubnetsToZones, } }
func (s *configureSuite) getCloudConfig(c *gc.C, controller bool, vers version.Binary) cloudinit.CloudConfig { var icfg *instancecfg.InstanceConfig var err error modelConfig := testConfig(c, controller, vers) if controller { icfg, err = instancecfg.NewBootstrapInstanceConfig( coretesting.FakeControllerConfig(), constraints.Value{}, constraints.Value{}, vers.Series, "", ) c.Assert(err, jc.ErrorIsNil) icfg.APIInfo = &api.Info{ Password: "******", CACert: coretesting.CACert, ModelTag: coretesting.ModelTag, } icfg.Controller.MongoInfo = &mongo.MongoInfo{ Password: "******", Info: mongo.Info{CACert: coretesting.CACert}, } icfg.Bootstrap.ControllerModelConfig = modelConfig icfg.Bootstrap.BootstrapMachineInstanceId = "instance-id" icfg.Bootstrap.HostedModelConfig = map[string]interface{}{ "name": "hosted-model", } icfg.Bootstrap.StateServingInfo = params.StateServingInfo{ Cert: coretesting.ServerCert, PrivateKey: coretesting.ServerKey, CAPrivateKey: coretesting.CAKey, StatePort: 123, APIPort: 456, } icfg.Jobs = []multiwatcher.MachineJob{multiwatcher.JobManageModel, multiwatcher.JobHostUnits} icfg.Bootstrap.StateServingInfo = params.StateServingInfo{ Cert: coretesting.ServerCert, PrivateKey: coretesting.ServerKey, CAPrivateKey: coretesting.CAKey, StatePort: 123, APIPort: 456, } } else { icfg, err = instancecfg.NewInstanceConfig(coretesting.ControllerTag, "0", "ya", imagemetadata.ReleasedStream, vers.Series, nil) c.Assert(err, jc.ErrorIsNil) icfg.Jobs = []multiwatcher.MachineJob{multiwatcher.JobHostUnits} } err = icfg.SetTools(tools.List{ &tools.Tools{ Version: vers, URL: "http://testing.invalid/tools.tar.gz", }, }) err = instancecfg.FinishInstanceConfig(icfg, modelConfig) c.Assert(err, jc.ErrorIsNil) cloudcfg, err := cloudinit.New(icfg.Series) c.Assert(err, jc.ErrorIsNil) udata, err := cloudconfig.NewUserdataConfig(icfg, cloudcfg) c.Assert(err, jc.ErrorIsNil) err = udata.Configure() c.Assert(err, jc.ErrorIsNil) return cloudcfg }
func (*instancecfgSuite) TestAgentVersionZero(c *gc.C) { var icfg instancecfg.InstanceConfig c.Assert(icfg.AgentVersion(), gc.Equals, version.Binary{}) }
// 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) }
func (manager *containerManager) CreateContainer( instanceConfig *instancecfg.InstanceConfig, cons constraints.Value, series string, networkConfig *container.NetworkConfig, storageConfig *container.StorageConfig, callback container.StatusCallback, ) (_ instance.Instance, _ *instance.HardwareCharacteristics, err error) { name, err := manager.namespace.Hostname(instanceConfig.MachineId) if err != nil { return nil, nil, errors.Trace(err) } defer func() { if err != nil { callback(status.ProvisioningError, fmt.Sprintf("Creating container: %v", err), nil) } }() // Set the MachineContainerHostname to match the name returned by virsh list instanceConfig.MachineContainerHostname = name // Note here that the kvmObjectFactory only returns a valid container // object, and doesn't actually construct the underlying kvm container on // disk. kvmContainer := KvmObjectFactory.New(name) // Create the cloud-init. directory, err := container.NewDirectory(name) if err != nil { return nil, nil, errors.Annotate(err, "failed to create container directory") } logger.Tracef("write cloud-init") userDataFilename, err := containerinit.WriteUserData(instanceConfig, networkConfig, directory) if err != nil { logger.Infof("machine config api %#v", *instanceConfig.APIInfo) err = errors.Annotate(err, "failed to write user data") logger.Infof(err.Error()) return nil, nil, err } // Create the container. startParams = ParseConstraintsToStartParams(cons) startParams.Arch = arch.HostArch() startParams.Series = series startParams.Network = networkConfig startParams.UserDataFile = userDataFilename // If the Simplestream requested is anything but released, update // our StartParams to request it. if instanceConfig.ImageStream != imagemetadata.ReleasedStream { startParams.ImageDownloadUrl = imagemetadata.UbuntuCloudImagesURL + "/" + instanceConfig.ImageStream } var hardware instance.HardwareCharacteristics hardware, err = instance.ParseHardware( fmt.Sprintf("arch=%s mem=%vM root-disk=%vG cores=%v", startParams.Arch, startParams.Memory, startParams.RootDisk, startParams.CpuCores)) if err != nil { return nil, nil, errors.Annotate(err, "failed to parse hardware") } callback(status.Allocating, "Creating container; it might take some time", nil) logger.Tracef("create the container, constraints: %v", cons) if err := kvmContainer.Start(startParams); err != nil { err = errors.Annotate(err, "kvm container creation failed") logger.Infof(err.Error()) return nil, nil, err } logger.Tracef("kvm container created") return &kvmInstance{kvmContainer, name}, &hardware, nil }
func (manager *containerManager) CreateContainer( instanceConfig *instancecfg.InstanceConfig, series string, networkConfig *container.NetworkConfig, storageConfig *container.StorageConfig, ) (instance.Instance, *instance.HardwareCharacteristics, error) { name := names.NewMachineTag(instanceConfig.MachineId).String() if manager.name != "" { name = fmt.Sprintf("%s-%s", manager.name, name) } // Set the MachineContainerHostname to match the name returned by virsh list instanceConfig.MachineContainerHostname = name // Note here that the kvmObjectFacotry only returns a valid container // object, and doesn't actually construct the underlying kvm container on // disk. kvmContainer := KvmObjectFactory.New(name) // Create the cloud-init. directory, err := container.NewDirectory(name) if err != nil { return nil, nil, errors.Annotate(err, "failed to create container directory") } logger.Tracef("write cloud-init") userDataFilename, err := containerinit.WriteUserData(instanceConfig, networkConfig, directory) if err != nil { logger.Infof("machine config api %#v", *instanceConfig.APIInfo) err = errors.Annotate(err, "failed to write user data") logger.Infof(err.Error()) return nil, nil, err } // Create the container. startParams = ParseConstraintsToStartParams(instanceConfig.Constraints) startParams.Arch = version.Current.Arch startParams.Series = series startParams.Network = networkConfig startParams.UserDataFile = userDataFilename // If the Simplestream requested is anything but released, update // our StartParams to request it. if instanceConfig.ImageStream != imagemetadata.ReleasedStream { startParams.ImageDownloadUrl = imagemetadata.UbuntuCloudImagesURL + "/" + instanceConfig.ImageStream } var hardware instance.HardwareCharacteristics hardware, err = instance.ParseHardware( fmt.Sprintf("arch=%s mem=%vM root-disk=%vG cpu-cores=%v", startParams.Arch, startParams.Memory, startParams.RootDisk, startParams.CpuCores)) if err != nil { logger.Warningf("failed to parse hardware: %v", err) } logger.Tracef("create the container, constraints: %v", instanceConfig.Constraints) if err := kvmContainer.Start(startParams); err != nil { err = errors.Annotate(err, "kvm container creation failed") logger.Infof(err.Error()) return nil, nil, err } logger.Tracef("kvm container created") return &kvmInstance{kvmContainer, name}, &hardware, nil }
func finalizeInstanceBootstrapConfig( ctx environs.BootstrapContext, icfg *instancecfg.InstanceConfig, args BootstrapParams, cfg *config.Config, customImageMetadata []*imagemetadata.ImageMetadata, ) error { if icfg.APIInfo != nil || icfg.Controller.MongoInfo != nil { return errors.New("machine configuration already has api/state info") } controllerCfg := icfg.Controller.Config caCert, hasCACert := controllerCfg.CACert() if !hasCACert { return errors.New("controller configuration has no ca-cert") } icfg.APIInfo = &api.Info{ Password: args.AdminSecret, CACert: caCert, ModelTag: names.NewModelTag(cfg.UUID()), } icfg.Controller.MongoInfo = &mongo.MongoInfo{ Password: args.AdminSecret, Info: mongo.Info{CACert: caCert}, } // These really are directly relevant to running a controller. // Initially, generate a controller certificate with no host IP // addresses in the SAN field. Once the controller is up and the // NIC addresses become known, the certificate can be regenerated. cert, key, err := controller.GenerateControllerCertAndKey(caCert, args.CAPrivateKey, nil) if err != nil { return errors.Annotate(err, "cannot generate controller certificate") } icfg.Bootstrap.StateServingInfo = params.StateServingInfo{ StatePort: controllerCfg.StatePort(), APIPort: controllerCfg.APIPort(), Cert: string(cert), PrivateKey: string(key), CAPrivateKey: args.CAPrivateKey, } if _, ok := cfg.AgentVersion(); !ok { return errors.New("controller model configuration has no agent-version") } icfg.Bootstrap.ControllerModelConfig = cfg icfg.Bootstrap.CustomImageMetadata = customImageMetadata icfg.Bootstrap.ControllerCloudName = args.CloudName icfg.Bootstrap.ControllerCloud = args.Cloud icfg.Bootstrap.ControllerCloudRegion = args.CloudRegion icfg.Bootstrap.ControllerCloudCredential = args.CloudCredential icfg.Bootstrap.ControllerCloudCredentialName = args.CloudCredentialName icfg.Bootstrap.ControllerConfig = args.ControllerConfig icfg.Bootstrap.ControllerInheritedConfig = args.ControllerInheritedConfig icfg.Bootstrap.RegionInheritedConfig = args.Cloud.RegionConfig icfg.Bootstrap.HostedModelConfig = args.HostedModelConfig icfg.Bootstrap.Timeout = args.DialOpts.Timeout icfg.Bootstrap.GUI = guiArchive(args.GUIDataSourceBaseURL, func(msg string) { ctx.Infof(msg) }) return nil }