// 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) }