func (s *provisionerSuite) TestProvisioningScript(c *gc.C) { const series = "precise" const arch = "amd64" defer fakeSSH{ Series: series, Arch: arch, InitUbuntuUser: true, }.install(c).Restore() machineId, err := manual.ProvisionMachine(s.getArgs(c)) c.Assert(err, gc.IsNil) mcfg, err := client.MachineConfig(s.State, machineId, agent.BootstrapNonce, "/var/lib/juju") c.Assert(err, gc.IsNil) script, err := manual.ProvisioningScript(mcfg) c.Assert(err, gc.IsNil) cloudcfg := coreCloudinit.New() err = cloudinit.ConfigureJuju(mcfg, cloudcfg) c.Assert(err, gc.IsNil) cloudcfg.SetAptUpgrade(false) sshinitScript, err := sshinit.ConfigureScript(cloudcfg) c.Assert(err, gc.IsNil) removeLogFile := "rm -f '/var/log/cloud-init-output.log'\n" expectedScript := removeLogFile + shell.DumpFileOnErrorScript("/var/log/cloud-init-output.log") + sshinitScript c.Assert(script, gc.Equals, expectedScript) }
func (s *provisionerSuite) TestFinishInstancConfig(c *gc.C) { var series = series.LatestLts() const arch = "amd64" defer fakeSSH{ Series: series, Arch: arch, InitUbuntuUser: true, }.install(c).Restore() machineId, err := manual.ProvisionMachine(s.getArgs(c)) c.Assert(err, jc.ErrorIsNil) // Now check what we would've configured it with. icfg, err := client.InstanceConfig(s.State, machineId, agent.BootstrapNonce, "/var/lib/juju") c.Assert(err, jc.ErrorIsNil) c.Check(icfg, gc.NotNil) c.Check(icfg.APIInfo, gc.NotNil) apiInfo := s.APIInfo(c) c.Check(icfg.APIInfo.Addrs, gc.DeepEquals, apiInfo.Addrs) }
func (s *provisionerSuite) TestProvisioningScript(c *gc.C) { var series = series.LatestLts() const arch = "amd64" defer fakeSSH{ Series: series, Arch: arch, InitUbuntuUser: true, }.install(c).Restore() machineId, err := manual.ProvisionMachine(s.getArgs(c)) c.Assert(err, jc.ErrorIsNil) err = s.State.UpdateModelConfig( map[string]interface{}{ "enable-os-upgrade": false, }, nil, nil) c.Assert(err, jc.ErrorIsNil) icfg, err := client.InstanceConfig(s.State, machineId, agent.BootstrapNonce, "/var/lib/juju") c.Assert(err, jc.ErrorIsNil) script, err := manual.ProvisioningScript(icfg) c.Assert(err, jc.ErrorIsNil) cloudcfg, err := cloudinit.New(series) c.Assert(err, jc.ErrorIsNil) udata, err := cloudconfig.NewUserdataConfig(icfg, cloudcfg) c.Assert(err, jc.ErrorIsNil) err = udata.ConfigureJuju() c.Assert(err, jc.ErrorIsNil) cloudcfg.SetSystemUpgrade(false) provisioningScript, err := cloudcfg.RenderScript() c.Assert(err, jc.ErrorIsNil) removeLogFile := "rm -f '/var/log/cloud-init-output.log'\n" expectedScript := removeLogFile + shell.DumpFileOnErrorScript("/var/log/cloud-init-output.log") + provisioningScript c.Assert(script, gc.Equals, expectedScript) }
func (s *provisionerSuite) TestFinishMachineConfig(c *gc.C) { const series = "precise" const arch = "amd64" defer fakeSSH{ Series: series, Arch: arch, InitUbuntuUser: true, }.install(c).Restore() machineId, err := manual.ProvisionMachine(s.getArgs(c)) c.Assert(err, gc.IsNil) // Now check what we would've configured it with. mcfg, err := client.MachineConfig(s.State, machineId, agent.BootstrapNonce, "/var/lib/juju") c.Assert(err, gc.IsNil) c.Check(mcfg, gc.NotNil) c.Check(mcfg.APIInfo, gc.NotNil) c.Check(mcfg.MongoInfo, gc.NotNil) stateInfo := s.MongoInfo(c) apiInfo := s.APIInfo(c) c.Check(mcfg.APIInfo.Addrs, gc.DeepEquals, apiInfo.Addrs) c.Check(mcfg.MongoInfo.Addrs, gc.DeepEquals, stateInfo.Addrs) }
func (s *provisionerSuite) TestProvisioningScript(c *gc.C) { const series = coretesting.FakeDefaultSeries const arch = "amd64" defer fakeSSH{ Series: series, Arch: arch, InitUbuntuUser: true, }.install(c).Restore() machineId, err := manual.ProvisionMachine(s.getArgs(c)) c.Assert(err, gc.IsNil) err = s.State.UpdateEnvironConfig( map[string]interface{}{ "enable-os-upgrade": false, }, nil, nil) c.Assert(err, gc.IsNil) mcfg, err := client.MachineConfig(s.State, machineId, agent.BootstrapNonce, "/var/lib/juju") c.Assert(err, gc.IsNil) script, err := manual.ProvisioningScript(mcfg) c.Assert(err, gc.IsNil) cloudcfg := coreCloudinit.New() udata, err := cloudinit.NewUserdataConfig(mcfg, cloudcfg) c.Assert(err, gc.IsNil) err = udata.ConfigureJuju() c.Assert(err, gc.IsNil) cloudcfg.SetAptUpgrade(false) sshinitScript, err := sshinit.ConfigureScript(cloudcfg) c.Assert(err, gc.IsNil) removeLogFile := "rm -f '/var/log/cloud-init-output.log'\n" expectedScript := removeLogFile + shell.DumpFileOnErrorScript("/var/log/cloud-init-output.log") + sshinitScript c.Assert(script, gc.Equals, expectedScript) }
func (s *provisionerSuite) TestProvisionMachine(c *gc.C) { var series = series.LatestLts() const arch = "amd64" args := s.getArgs(c) hostname := args.Host args.Host = "ubuntu@" + args.Host defaultToolsURL := envtools.DefaultBaseURL envtools.DefaultBaseURL = "" defer fakeSSH{ Series: series, Arch: arch, InitUbuntuUser: true, SkipProvisionAgent: true, }.install(c).Restore() // Attempt to provision a machine with no tools available, expect it to fail. machineId, err := manual.ProvisionMachine(args) c.Assert(err, jc.Satisfies, params.IsCodeNotFound) c.Assert(machineId, gc.Equals, "") cfg := s.Environ.Config() number, ok := cfg.AgentVersion() c.Assert(ok, jc.IsTrue) binVersion := version.Binary{ Number: number, Series: series, Arch: arch, } envtesting.AssertUploadFakeToolsVersions(c, s.DefaultToolsStorage, "released", "released", binVersion) envtools.DefaultBaseURL = defaultToolsURL for i, errorCode := range []int{255, 0} { c.Logf("test %d: code %d", i, errorCode) defer fakeSSH{ Series: series, Arch: arch, InitUbuntuUser: true, ProvisionAgentExitCode: errorCode, }.install(c).Restore() machineId, err = manual.ProvisionMachine(args) if errorCode != 0 { c.Assert(err, gc.ErrorMatches, fmt.Sprintf("subprocess encountered error code %d", errorCode)) c.Assert(machineId, gc.Equals, "") } else { c.Assert(err, jc.ErrorIsNil) c.Assert(machineId, gc.Not(gc.Equals), "") // machine ID will be incremented. Even though we failed and the // machine is removed, the ID is not reused. c.Assert(machineId, gc.Equals, fmt.Sprint(i+1)) m, err := s.State.Machine(machineId) c.Assert(err, jc.ErrorIsNil) instanceId, err := m.InstanceId() c.Assert(err, jc.ErrorIsNil) c.Assert(instanceId, gc.Equals, instance.Id("manual:"+hostname)) } } // Attempting to provision a machine twice should fail. We effect // this by checking for existing juju upstart configurations. defer fakeSSH{ Provisioned: true, InitUbuntuUser: true, SkipDetection: true, SkipProvisionAgent: true, }.install(c).Restore() _, err = manual.ProvisionMachine(args) c.Assert(err, gc.Equals, manual.ErrProvisioned) defer fakeSSH{ Provisioned: true, CheckProvisionedExitCode: 255, InitUbuntuUser: true, SkipDetection: true, SkipProvisionAgent: true, }.install(c).Restore() _, err = manual.ProvisionMachine(args) c.Assert(err, gc.ErrorMatches, "error checking if provisioned: subprocess encountered error code 255") }
func (c *AddMachineCommand) Run(ctx *cmd.Context) error { if c.Placement != nil && c.Placement.Scope == "ssh" { args := manual.ProvisionMachineArgs{ Host: c.Placement.Directive, EnvName: c.EnvName, Stdin: ctx.Stdin, Stdout: ctx.Stdout, Stderr: ctx.Stderr, } _, err := manual.ProvisionMachine(args) return err } client, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer client.Close() if c.Placement != nil && c.Placement.Scope == instance.MachineScope { // It does not make sense to add-machine <id>. return fmt.Errorf("machine-id cannot be specified when adding machines") } machineParams := params.AddMachineParams{ Placement: c.Placement, Series: c.Series, Constraints: c.Constraints, Jobs: []params.MachineJob{params.JobHostUnits}, } results, err := client.AddMachines([]params.AddMachineParams{machineParams}) if params.IsCodeNotImplemented(err) { if c.Placement != nil { containerType, parseErr := instance.ParseContainerType(c.Placement.Scope) if parseErr != nil { // The user specified a non-container placement directive: // return original API not implemented error. return err } machineParams.ContainerType = containerType machineParams.ParentId = c.Placement.Directive machineParams.Placement = nil } logger.Infof( "AddMachinesWithPlacement not supported by the API server, " + "falling back to 1.18 compatibility mode", ) results, err = client.AddMachines1dot18([]params.AddMachineParams{machineParams}) } if err != nil { return err } // Currently, only one machine is added, but in future there may be several added in one call. machineInfo := results[0] if machineInfo.Error != nil { return machineInfo.Error } machineId := machineInfo.Machine if names.IsContainerMachine(machineId) { ctx.Infof("created container %v", machineId) } else { ctx.Infof("created machine %v", machineId) } return nil }
func (c *AddMachineCommand) Run(ctx *cmd.Context) error { if c.Placement != nil && c.Placement.Scope == "ssh" { args := manual.ProvisionMachineArgs{ Host: c.Placement.Directive, EnvName: c.EnvName, Stdin: ctx.Stdin, Stdout: ctx.Stdout, Stderr: ctx.Stderr, } _, err := manual.ProvisionMachine(args) return err } client, err := getAddMachineAPI(c.EnvName) if err != nil { return err } defer client.Close() if c.Placement != nil && c.Placement.Scope == instance.MachineScope { // It does not make sense to add-machine <id>. return fmt.Errorf("machine-id cannot be specified when adding machines") } machineParams := params.AddMachineParams{ Placement: c.Placement, Series: c.Series, Constraints: c.Constraints, Jobs: []params.MachineJob{params.JobHostUnits}, } machines := make([]params.AddMachineParams, c.NumMachines) for i := 0; i < c.NumMachines; i++ { machines[i] = machineParams } results, err := client.AddMachines(machines) if params.IsCodeNotImplemented(err) { if c.Placement != nil { containerType, parseErr := instance.ParseContainerType(c.Placement.Scope) if parseErr != nil { // The user specified a non-container placement directive: // return original API not implemented error. return err } machineParams.ContainerType = containerType machineParams.ParentId = c.Placement.Directive machineParams.Placement = nil } logger.Infof( "AddMachinesWithPlacement not supported by the API server, " + "falling back to 1.18 compatibility mode", ) results, err = client.AddMachines1dot18([]params.AddMachineParams{machineParams}) } if err != nil { return err } errs := []error{} for _, machineInfo := range results { if machineInfo.Error != nil { errs = append(errs, machineInfo.Error) continue } machineId := machineInfo.Machine if names.IsContainerMachine(machineId) { ctx.Infof("created container %v", machineId) } else { ctx.Infof("created machine %v", machineId) } } if len(errs) == 1 { fmt.Fprintf(ctx.Stderr, "failed to create 1 machine\n") return errs[0] } if len(errs) > 1 { fmt.Fprintf(ctx.Stderr, "failed to create %d machines\n", len(errs)) returnErr := []string{} for _, e := range errs { returnErr = append(returnErr, fmt.Sprintf("%s", e)) } return errors.New(strings.Join(returnErr, ", ")) } return nil }