func (t *localServerSuite) testStartInstanceAvailZoneAllConstrained(c *gc.C, runInstancesError *amzec2.Error) { env := t.Prepare(c) err := bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{}) c.Assert(err, jc.ErrorIsNil) mock := mockAvailabilityZoneAllocations{ result: []common.AvailabilityZoneInstances{ {ZoneName: "az1"}, {ZoneName: "az2"}, }, } t.PatchValue(ec2.AvailabilityZoneAllocations, mock.AvailabilityZoneAllocations) var azArgs []string t.PatchValue(ec2.RunInstances, func(e *amzec2.EC2, ri *amzec2.RunInstances) (*amzec2.RunInstancesResp, error) { azArgs = append(azArgs, ri.AvailZone) return nil, runInstancesError }) _, _, _, err = testing.StartInstance(env, "1") c.Assert(err, gc.ErrorMatches, fmt.Sprintf( "cannot run instances: %s \\(%s\\)", regexp.QuoteMeta(runInstancesError.Message), runInstancesError.Code, )) c.Assert(azArgs, gc.DeepEquals, []string{"az1", "az2"}) }
func (s *BootstrapSuite) makeTestEnv(c *gc.C) { attrs := dummy.SampleConfig().Merge( testing.Attrs{ "agent-version": version.Current.Number.String(), "bootstrap-timeout": "123", }, ).Delete("admin-secret", "ca-private-key") cfg, err := config.New(config.NoDefaults, attrs) c.Assert(err, jc.ErrorIsNil) provider, err := environs.Provider(cfg.Type()) c.Assert(err, jc.ErrorIsNil) env, err := provider.PrepareForBootstrap(nullContext(), cfg) c.Assert(err, jc.ErrorIsNil) envtesting.MustUploadFakeTools(s.toolsStorage, cfg.AgentStream(), cfg.AgentStream()) inst, _, _, err := jujutesting.StartInstance(env, "0") c.Assert(err, jc.ErrorIsNil) s.instanceId = inst.Id() addresses, err := inst.Addresses() c.Assert(err, jc.ErrorIsNil) s.bootstrapName = network.SelectPublicAddress(addresses) s.envcfg = env.Config() s.b64yamlEnvcfg = b64yaml(s.envcfg.AllAttrs()).encode() }
func (s *localServerSuite) TestStartInstanceNetworkUnknownLabel(c *gc.C) { cfg, err := config.New(config.NoDefaults, s.TestConfig.Merge(coretesting.Attrs{ // A label that has no related network in the nova test service "network": "no-network-with-this-label", })) c.Assert(err, gc.IsNil) env, err := environs.New(cfg) c.Assert(err, gc.IsNil) inst, _, _, err := testing.StartInstance(env, "100") c.Check(inst, gc.IsNil) c.Assert(err, gc.ErrorMatches, "No networks exist with label .*") }
func (s *localServerSuite) TestStartInstanceNetworkUnknownId(c *gc.C) { cfg, err := config.New(config.NoDefaults, s.TestConfig.Merge(coretesting.Attrs{ // A valid UUID but no related network in the nova test service "network": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6", })) c.Assert(err, gc.IsNil) env, err := environs.New(cfg) c.Assert(err, gc.IsNil) inst, _, _, err := testing.StartInstance(env, "100") c.Check(inst, gc.IsNil) c.Assert(err, gc.ErrorMatches, "cannot run instance: (\\n|.)*"+ "caused by: "+ "request \\(.*/servers\\) returned unexpected status: "+ "404; error info: .*itemNotFound.*") }
func (s *environSuite) TestStartInstanceDistributionErrors(c *gc.C) { env := s.bootstrap(c) mock := mockAvailabilityZoneAllocations{ err: errors.New("AvailabilityZoneAllocations failed"), } s.PatchValue(&availabilityZoneAllocations, mock.AvailabilityZoneAllocations) _, _, _, err := testing.StartInstance(env, "1") c.Assert(err, gc.ErrorMatches, "cannot get availability zone allocations: AvailabilityZoneAllocations failed") mock.err = nil dgErr := errors.New("DistributionGroup failed") params := environs.StartInstanceParams{ DistributionGroup: func() ([]instance.Id, error) { return nil, dgErr }, } _, err = testing.StartInstanceWithParams(env, "1", params) c.Assert(err, gc.ErrorMatches, "cannot get distribution group: DistributionGroup failed") }
func (t *localServerSuite) TestStartInstanceDistributionErrors(c *gc.C) { env := t.Prepare(c) err := bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{}) c.Assert(err, jc.ErrorIsNil) mock := mockAvailabilityZoneAllocations{ err: fmt.Errorf("AvailabilityZoneAllocations failed"), } t.PatchValue(ec2.AvailabilityZoneAllocations, mock.AvailabilityZoneAllocations) _, _, _, err = testing.StartInstance(env, "1") c.Assert(errors.Cause(err), gc.Equals, mock.err) mock.err = nil dgErr := fmt.Errorf("DistributionGroup failed") params := environs.StartInstanceParams{ DistributionGroup: func() ([]instance.Id, error) { return nil, dgErr }, } _, err = testing.StartInstanceWithParams(env, "1", params, nil) c.Assert(errors.Cause(err), gc.Equals, dgErr) }
func (t *localServerSuite) TestStartInstanceAvailZoneAllConstrained(c *gc.C) { env := t.Prepare(c) envtesting.UploadFakeTools(c, env.Storage()) err := bootstrap.Bootstrap(coretesting.Context(c), env, bootstrap.BootstrapParams{}) c.Assert(err, gc.IsNil) mock := mockAvailabilityZoneAllocations{ result: []common.AvailabilityZoneInstances{ {ZoneName: "az1"}, {ZoneName: "az2"}, }, } t.PatchValue(ec2.AvailabilityZoneAllocations, mock.AvailabilityZoneAllocations) var azArgs []string t.PatchValue(ec2.RunInstances, func(e *amzec2.EC2, ri *amzec2.RunInstances) (*amzec2.RunInstancesResp, error) { azArgs = append(azArgs, ri.AvailZone) return nil, azConstrainedErr }) _, _, _, err = testing.StartInstance(env, "1") c.Assert(err, gc.ErrorMatches, `cannot run instances: The requested Availability Zone is currently constrained etc\. \(Unsupported\)`) c.Assert(azArgs, gc.DeepEquals, []string{"az1", "az2"}) }
func (t *localServerSuite) TestStartInstanceDistributionErrors(c *gc.C) { env := t.Prepare(c) envtesting.UploadFakeTools(c, env.Storage()) err := bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) mock := mockBestAvailabilityZoneAllocations{ err: fmt.Errorf("BestAvailabilityZoneAllocations failed"), } t.PatchValue(openstack.BestAvailabilityZoneAllocations, mock.BestAvailabilityZoneAllocations) _, _, _, err = testing.StartInstance(env, "1") c.Assert(err, gc.Equals, mock.err) mock.err = nil dgErr := fmt.Errorf("DistributionGroup failed") params := environs.StartInstanceParams{ DistributionGroup: func() ([]instance.Id, error) { return nil, dgErr }, } _, _, _, err = testing.StartInstanceWithParams(env, "1", params, nil) c.Assert(err, gc.Equals, dgErr) }
func (s *BootstrapSuite) makeTestEnv(c *gc.C) { attrs := dummy.SampleConfig().Merge( testing.Attrs{ "agent-version": jujuversion.Current.String(), "bootstrap-timeout": "123", }, ).Delete("admin-secret", "ca-private-key") cfg, err := config.New(config.NoDefaults, attrs) c.Assert(err, jc.ErrorIsNil) provider, err := environs.Provider(cfg.Type()) c.Assert(err, jc.ErrorIsNil) cfg, err = provider.BootstrapConfig(environs.BootstrapConfigParams{Config: cfg}) c.Assert(err, jc.ErrorIsNil) env, err := provider.PrepareForBootstrap(nullContext(), cfg) c.Assert(err, jc.ErrorIsNil) s.PatchValue(&juju.JujuPublicKey, sstesting.SignedMetadataPublicKey) envtesting.MustUploadFakeTools(s.toolsStorage, cfg.AgentStream(), cfg.AgentStream()) inst, _, _, err := jujutesting.StartInstance(env, "0") c.Assert(err, jc.ErrorIsNil) s.instanceId = inst.Id() addresses, err := inst.Addresses() c.Assert(err, jc.ErrorIsNil) addr, _ := network.SelectPublicAddress(addresses) s.bootstrapName = addr.Value s.envcfg = env.Config() s.b64yamlControllerModelConfig = b64yaml(s.envcfg.AllAttrs()).encode() s.hostedModelUUID = utils.MustNewUUID().String() hostedModelConfigAttrs := map[string]interface{}{ "name": "hosted-model", "uuid": s.hostedModelUUID, } s.b64yamlHostedModelConfig = b64yaml(hostedModelConfigAttrs).encode() }
func (suite *environSuite) TestStartInstanceStartsInstance(c *gc.C) { suite.setupFakeTools(c) env := suite.makeEnviron() // Create node 0: it will be used as the bootstrap node. suite.newNode(c, "node0", "host0", nil) suite.addSubnet(c, 9, 9, "node0") err := bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{ ControllerConfig: coretesting.FakeControllerConfig(), AdminSecret: testing.AdminSecret, CAPrivateKey: coretesting.CAKey, }) c.Assert(err, jc.ErrorIsNil) // The bootstrap node has been acquired and started. operations := suite.testMAASObject.TestServer.NodeOperations() actions, found := operations["node0"] c.Check(found, jc.IsTrue) c.Check(actions, gc.DeepEquals, []string{"acquire", "start"}) // Test the instance id is correctly recorded for the bootstrap node. // Check that ControllerInstances returns the id of the bootstrap machine. instanceIds, err := env.ControllerInstances(suite.controllerUUID) c.Assert(err, jc.ErrorIsNil) c.Assert(instanceIds, gc.HasLen, 1) insts, err := env.AllInstances() c.Assert(err, jc.ErrorIsNil) c.Assert(insts, gc.HasLen, 1) c.Check(insts[0].Id(), gc.Equals, instanceIds[0]) // Create node 1: it will be used as instance number 1. suite.newNode(c, "node1", "host1", nil) suite.addSubnet(c, 8, 8, "node1") instance, hc := testing.AssertStartInstance(c, env, suite.controllerUUID, "1") c.Assert(err, jc.ErrorIsNil) c.Check(instance, gc.NotNil) c.Assert(hc, gc.NotNil) c.Check(hc.String(), gc.Equals, fmt.Sprintf("arch=%s cores=1 mem=1024M availability-zone=test_zone", arch.HostArch())) // The instance number 1 has been acquired and started. actions, found = operations["node1"] c.Assert(found, jc.IsTrue) c.Check(actions, gc.DeepEquals, []string{"acquire", "start"}) // The value of the "user data" parameter used when starting the node // contains the run cmd used to write the machine information onto // the node's filesystem. requestValues := suite.testMAASObject.TestServer.NodeOperationRequestValues() nodeRequestValues, found := requestValues["node1"] c.Assert(found, jc.IsTrue) c.Assert(len(nodeRequestValues), gc.Equals, 2) userData := nodeRequestValues[1].Get("user_data") decodedUserData, err := decodeUserData(userData) c.Assert(err, jc.ErrorIsNil) info := machineInfo{"host1"} cloudcfg, err := cloudinit.New("precise") c.Assert(err, jc.ErrorIsNil) cloudinitRunCmd, err := info.cloudinitRunCmd(cloudcfg) c.Assert(err, jc.ErrorIsNil) data, err := goyaml.Marshal(cloudinitRunCmd) c.Assert(err, jc.ErrorIsNil) c.Check(string(decodedUserData), jc.Contains, string(data)) // Trash the tools and try to start another instance. suite.PatchValue(&envtools.DefaultBaseURL, "") instance, _, _, err = testing.StartInstance(env, suite.controllerUUID, "2") c.Check(instance, gc.IsNil) c.Check(err, jc.Satisfies, errors.IsNotFound) }
func (suite *maas2EnvironSuite) TestStartInstanceEndToEnd(c *gc.C) { suite.setupFakeTools(c) machine := newFakeMachine("gus", arch.HostArch(), "Deployed") file := &fakeFile{name: "agent-prefix-provider-state"} controller := newFakeControllerWithFiles(file) controller.machines = []gomaasapi.Machine{machine} controller.allocateMachine = machine controller.allocateMachineMatches = gomaasapi.ConstraintMatches{ Storage: make(map[string][]gomaasapi.BlockDevice), } env := suite.makeEnviron(c, controller) err := bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{}) c.Assert(err, jc.ErrorIsNil) machine.Stub.CheckCallNames(c, "Start") controller.Stub.CheckCallNames(c, "GetFile", "AddFile") addFileArgs, ok := controller.Stub.Calls()[1].Args[0].(gomaasapi.AddFileArgs) c.Assert(ok, jc.IsTrue) // Make it look like the right state was written to the file. buffer := new(bytes.Buffer) buffer.ReadFrom(addFileArgs.Reader) file.contents = buffer.Bytes() c.Check(string(buffer.Bytes()), gc.Equals, "state-instances:\n- gus\n") // Test the instance id is correctly recorded for the bootstrap node. // Check that ControllerInstances returns the id of the bootstrap machine. instanceIds, err := env.ControllerInstances() c.Assert(err, jc.ErrorIsNil) c.Assert(instanceIds, gc.HasLen, 1) insts, err := env.AllInstances() c.Assert(err, jc.ErrorIsNil) c.Assert(insts, gc.HasLen, 1) c.Check(insts[0].Id(), gc.Equals, instanceIds[0]) node1 := newFakeMachine("victor", arch.HostArch(), "Deployed") node1.hostname = "host1" node1.cpuCount = 1 node1.memory = 1024 node1.zoneName = "test_zone" controller.allocateMachine = node1 instance, hc := testing.AssertStartInstance(c, env, "1") c.Check(instance, gc.NotNil) c.Assert(hc, gc.NotNil) c.Check(hc.String(), gc.Equals, fmt.Sprintf("arch=%s cpu-cores=1 mem=1024M availability-zone=test_zone", arch.HostArch())) node1.Stub.CheckCallNames(c, "Start") startArgs, ok := node1.Stub.Calls()[0].Args[0].(gomaasapi.StartArgs) c.Assert(ok, jc.IsTrue) decodedUserData, err := decodeUserData(startArgs.UserData) c.Assert(err, jc.ErrorIsNil) info := machineInfo{"host1"} cloudcfg, err := cloudinit.New("precise") c.Assert(err, jc.ErrorIsNil) cloudinitRunCmd, err := info.cloudinitRunCmd(cloudcfg) c.Assert(err, jc.ErrorIsNil) data, err := goyaml.Marshal(cloudinitRunCmd) c.Assert(err, jc.ErrorIsNil) c.Check(string(decodedUserData), jc.Contains, string(data)) // Trash the tools and try to start another instance. suite.PatchValue(&envtools.DefaultBaseURL, "") instance, _, _, err = testing.StartInstance(env, "2") c.Check(instance, gc.IsNil) c.Check(err, jc.Satisfies, errors.IsNotFound) }
func (suite *environSuite) TestStartInstanceStartsInstance(c *gc.C) { suite.setupFakeTools(c) env := suite.makeEnviron() // Create node 0: it will be used as the bootstrap node. suite.testMAASObject.TestServer.NewNode(`{"system_id": "node0", "hostname": "host0"}`) lshwXML, err := suite.generateHWTemplate(map[string]string{"aa:bb:cc:dd:ee:f0": "eth0"}) c.Assert(err, gc.IsNil) suite.testMAASObject.TestServer.AddNodeDetails("node0", lshwXML) err = bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{}) c.Assert(err, gc.IsNil) // The bootstrap node has been acquired and started. operations := suite.testMAASObject.TestServer.NodeOperations() actions, found := operations["node0"] c.Check(found, gc.Equals, true) c.Check(actions, gc.DeepEquals, []string{"acquire", "start"}) // Test the instance id is correctly recorded for the bootstrap node. // Check that the state holds the id of the bootstrap machine. stateData, err := bootstrap.LoadState(env.Storage()) c.Assert(err, gc.IsNil) c.Assert(stateData.StateInstances, gc.HasLen, 1) insts, err := env.AllInstances() c.Assert(err, gc.IsNil) c.Assert(insts, gc.HasLen, 1) c.Check(insts[0].Id(), gc.Equals, stateData.StateInstances[0]) // Create node 1: it will be used as instance number 1. suite.testMAASObject.TestServer.NewNode(`{"system_id": "node1", "hostname": "host1"}`) lshwXML, err = suite.generateHWTemplate(map[string]string{"aa:bb:cc:dd:ee:f1": "eth0"}) c.Assert(err, gc.IsNil) suite.testMAASObject.TestServer.AddNodeDetails("node1", lshwXML) // TODO(wallyworld) - test instance metadata instance, _ := testing.AssertStartInstance(c, env, "1") c.Assert(err, gc.IsNil) c.Check(instance, gc.NotNil) // The instance number 1 has been acquired and started. actions, found = operations["node1"] c.Assert(found, gc.Equals, true) c.Check(actions, gc.DeepEquals, []string{"acquire", "start"}) // The value of the "user data" parameter used when starting the node // contains the run cmd used to write the machine information onto // the node's filesystem. requestValues := suite.testMAASObject.TestServer.NodeOperationRequestValues() nodeRequestValues, found := requestValues["node1"] c.Assert(found, gc.Equals, true) c.Assert(len(nodeRequestValues), gc.Equals, 2) userData := nodeRequestValues[1].Get("user_data") decodedUserData, err := decodeUserData(userData) c.Assert(err, gc.IsNil) info := machineInfo{"host1"} cloudinitRunCmd, err := info.cloudinitRunCmd() c.Assert(err, gc.IsNil) data, err := goyaml.Marshal(cloudinitRunCmd) c.Assert(err, gc.IsNil) c.Check(string(decodedUserData), gc.Matches, "(.|\n)*"+string(data)+"(\n|.)*") // Trash the tools and try to start another instance. envtesting.RemoveTools(c, env.Storage()) instance, _, _, err = testing.StartInstance(env, "2") c.Check(instance, gc.IsNil) c.Check(err, jc.Satisfies, errors.IsNotFound) }
func (suite *environSuite) TestStartInstanceStartsInstance(c *gc.C) { suite.setupFakeTools(c) env := suite.makeEnviron() // Create node 0: it will be used as the bootstrap node. suite.testMAASObject.TestServer.NewNode(fmt.Sprintf( `{"system_id": "node0", "hostname": "host0", "architecture": "%s/generic", "memory": 1024, "cpu_count": 1, "zone": {"name": "test_zone"}}`, arch.HostArch()), ) lshwXML, err := suite.generateHWTemplate(map[string]ifaceInfo{"aa:bb:cc:dd:ee:f0": {0, "eth0", false}}) c.Assert(err, jc.ErrorIsNil) suite.testMAASObject.TestServer.AddNodeDetails("node0", lshwXML) suite.addSubnet(c, 9, 9, "node0") err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{}) c.Assert(err, jc.ErrorIsNil) // The bootstrap node has been acquired and started. operations := suite.testMAASObject.TestServer.NodeOperations() actions, found := operations["node0"] c.Check(found, jc.IsTrue) c.Check(actions, gc.DeepEquals, []string{"acquire", "start"}) // Test the instance id is correctly recorded for the bootstrap node. // Check that ControllerInstances returns the id of the bootstrap machine. instanceIds, err := env.ControllerInstances() c.Assert(err, jc.ErrorIsNil) c.Assert(instanceIds, gc.HasLen, 1) insts, err := env.AllInstances() c.Assert(err, jc.ErrorIsNil) c.Assert(insts, gc.HasLen, 1) c.Check(insts[0].Id(), gc.Equals, instanceIds[0]) // Create node 1: it will be used as instance number 1. suite.testMAASObject.TestServer.NewNode(fmt.Sprintf( `{"system_id": "node1", "hostname": "host1", "architecture": "%s/generic", "memory": 1024, "cpu_count": 1, "zone": {"name": "test_zone"}}`, arch.HostArch()), ) lshwXML, err = suite.generateHWTemplate(map[string]ifaceInfo{"aa:bb:cc:dd:ee:f1": {0, "eth0", false}}) c.Assert(err, jc.ErrorIsNil) suite.testMAASObject.TestServer.AddNodeDetails("node1", lshwXML) suite.addSubnet(c, 8, 8, "node1") instance, hc := testing.AssertStartInstance(c, env, "1") c.Assert(err, jc.ErrorIsNil) c.Check(instance, gc.NotNil) c.Assert(hc, gc.NotNil) c.Check(hc.String(), gc.Equals, fmt.Sprintf("arch=%s cpu-cores=1 mem=1024M availability-zone=test_zone", arch.HostArch())) // The instance number 1 has been acquired and started. actions, found = operations["node1"] c.Assert(found, jc.IsTrue) c.Check(actions, gc.DeepEquals, []string{"acquire", "start"}) // The value of the "user data" parameter used when starting the node // contains the run cmd used to write the machine information onto // the node's filesystem. requestValues := suite.testMAASObject.TestServer.NodeOperationRequestValues() nodeRequestValues, found := requestValues["node1"] c.Assert(found, jc.IsTrue) c.Assert(len(nodeRequestValues), gc.Equals, 2) userData := nodeRequestValues[1].Get("user_data") decodedUserData, err := decodeUserData(userData) c.Assert(err, jc.ErrorIsNil) info := machineInfo{"host1"} cloudcfg, err := cloudinit.New("precise") c.Assert(err, jc.ErrorIsNil) cloudinitRunCmd, err := info.cloudinitRunCmd(cloudcfg) c.Assert(err, jc.ErrorIsNil) data, err := goyaml.Marshal(cloudinitRunCmd) c.Assert(err, jc.ErrorIsNil) c.Check(string(decodedUserData), jc.Contains, string(data)) // Trash the tools and try to start another instance. suite.PatchValue(&envtools.DefaultBaseURL, "") instance, _, _, err = testing.StartInstance(env, "2") c.Check(instance, gc.IsNil) c.Check(err, jc.Satisfies, errors.IsNotFound) }