diff --git a/cloud/cloud.go b/cloud/cloud.go index d861a875d..cb62799f2 100644 --- a/cloud/cloud.go +++ b/cloud/cloud.go @@ -23,6 +23,7 @@ type Cloud interface { agentID string, stemcellCID string, cloudProperties biproperty.Map, + diskCIDS []string, networksInterfaces map[string]biproperty.Map, env biproperty.Map, ) (vmCID string, err error) @@ -153,14 +154,14 @@ func (c cloud) CreateVM( agentID string, stemcellCID string, cloudProperties biproperty.Map, + diskCIDS []string, networksInterfaces map[string]biproperty.Map, env biproperty.Map, ) (string, error) { var ( - ok bool - cidString string - method = "create_vm" - diskLocality = []interface{}{} // not used with bosh-init + ok bool + cidString string + method = "create_vm" ) cpiInfo, err := c.Info() @@ -176,7 +177,7 @@ func (c cloud) CreateVM( stemcellCID, cloudProperties, networksInterfaces, - diskLocality, + diskCIDS, env, ) diff --git a/cloud/cloud_test.go b/cloud/cloud_test.go index 863892125..cc91b7d7f 100644 --- a/cloud/cloud_test.go +++ b/cloud/cloud_test.go @@ -373,6 +373,7 @@ var _ = Describe("Cloud", func() { stemcellCID string cloudProperties biproperty.Map networkInterfaces map[string]biproperty.Map + diskCIDs []string env biproperty.Map ) @@ -387,6 +388,7 @@ var _ = Describe("Cloud", func() { }, }, } + diskCIDs = []string{"fake-disk-cid"} cloudProperties = biproperty.Map{ "fake-cloud-property-key": "fake-cloud-property-value", } @@ -408,7 +410,7 @@ var _ = Describe("Cloud", func() { }) It("executes the cpi job script with the director UUID and stemcell CID", func() { - _, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, networkInterfaces, env) + _, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, diskCIDs, networkInterfaces, env) Expect(err).NotTo(HaveOccurred()) Expect(fakeCPICmdRunner.CurrentRunInput).To(HaveLen(2)) Expect(fakeCPICmdRunner.CurrentRunInput[1]).To(Equal(fakebicloud.RunInput{ @@ -419,7 +421,7 @@ var _ = Describe("Cloud", func() { stemcellCID, cloudProperties, networkInterfaces, - []interface{}{}, + diskCIDs, env, }, ApiVersion: 1, @@ -427,7 +429,7 @@ var _ = Describe("Cloud", func() { }) It("returns the cid returned from executing the cpi script", func() { - cid, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, networkInterfaces, env) + cid, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, diskCIDs, networkInterfaces, env) Expect(err).NotTo(HaveOccurred()) Expect(cid).To(Equal("fake-vm-cid")) }) @@ -448,7 +450,7 @@ var _ = Describe("Cloud", func() { }) It("returns the vm cid", func() { - cid, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, networkInterfaces, env) + cid, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, diskCIDs, networkInterfaces, env) Expect(err).NotTo(HaveOccurred()) Expect(cid).To(Equal("fake-vm-cid")) }) @@ -468,7 +470,7 @@ var _ = Describe("Cloud", func() { }) It("returns error", func() { - _, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, networkInterfaces, env) + _, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, diskCIDs, networkInterfaces, env) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Unexpected external CPI command result: '[]interface {}")) }) @@ -489,7 +491,7 @@ var _ = Describe("Cloud", func() { }) It("returns an error", func() { - _, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, networkInterfaces, env) + _, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, diskCIDs, networkInterfaces, env) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Unexpected external CPI command result: '1'")) }) @@ -501,14 +503,14 @@ var _ = Describe("Cloud", func() { }) It("returns an error", func() { - _, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, networkInterfaces, env) + _, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, diskCIDs, networkInterfaces, env) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-run-error")) }) }) itHandlesCPIErrors("create_vm", func() error { - _, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, networkInterfaces, env) + _, err := cloud.CreateVM(agentID, stemcellCID, cloudProperties, diskCIDs, networkInterfaces, env) return err }) diff --git a/cloud/fakes/fake_cloud.go b/cloud/fakes/fake_cloud.go index d426583b1..44850ce79 100644 --- a/cloud/fakes/fake_cloud.go +++ b/cloud/fakes/fake_cloud.go @@ -64,6 +64,7 @@ type CreateVMInput struct { AgentID string StemcellCID string CloudProperties biproperty.Map + DiskCIDs []string NetworksInterfaces map[string]biproperty.Map Env biproperty.Map } @@ -130,6 +131,7 @@ func (c *FakeCloud) CreateVM( agentID string, stemcellCID string, cloudProperties biproperty.Map, + diskCIDs []string, networksInterfaces map[string]biproperty.Map, env biproperty.Map, ) (string, error) { @@ -137,6 +139,7 @@ func (c *FakeCloud) CreateVM( AgentID: agentID, StemcellCID: stemcellCID, CloudProperties: cloudProperties, + DiskCIDs: diskCIDs, NetworksInterfaces: networksInterfaces, Env: env, } diff --git a/cloud/mocks/mocks.go b/cloud/mocks/mocks.go index c0ee044ed..d64fef881 100644 --- a/cloud/mocks/mocks.go +++ b/cloud/mocks/mocks.go @@ -82,18 +82,18 @@ func (mr *MockCloudMockRecorder) CreateStemcell(arg0, arg1 interface{}) *gomock. } // CreateVM mocks base method. -func (m *MockCloud) CreateVM(arg0, arg1 string, arg2 property.Map, arg3 map[string]property.Map, arg4 property.Map) (string, error) { +func (m *MockCloud) CreateVM(arg0, arg1 string, arg2 property.Map, arg3 []string, arg4 map[string]property.Map, arg5 property.Map) (string, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateVM", arg0, arg1, arg2, arg3, arg4) + ret := m.ctrl.Call(m, "CreateVM", arg0, arg1, arg2, arg3, arg4, arg5) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } // CreateVM indicates an expected call of CreateVM. -func (mr *MockCloudMockRecorder) CreateVM(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { +func (mr *MockCloudMockRecorder) CreateVM(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateVM", reflect.TypeOf((*MockCloud)(nil).CreateVM), arg0, arg1, arg2, arg3, arg4) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateVM", reflect.TypeOf((*MockCloud)(nil).CreateVM), arg0, arg1, arg2, arg3, arg4, arg5) } // DeleteDisk mocks base method. diff --git a/cmd/create_env_test.go b/cmd/create_env_test.go index 0e6afb5f1..787e81bc1 100644 --- a/cmd/create_env_test.go +++ b/cmd/create_env_test.go @@ -436,8 +436,6 @@ var _ = Describe("CreateEnvCmd", func() { }).Return(installation, nil).AnyTimes() mockInstaller.EXPECT().Cleanup(installation).AnyTimes() - // mockDeployment := mock_deployment.NewMockDeployment(mockCtrl) - expectDeploy = mockDeployer.EXPECT().Deploy( mockCloud, boshDeploymentManifest, @@ -446,7 +444,8 @@ var _ = Describe("CreateEnvCmd", func() { mockBlobstore, expectedSkipDrain, gomock.Any(), - ).Do(func(_, _, _, _, _, _ interface{}, stage boshui.Stage) { + gomock.Any(), + ).Do(func(_, _, _, _, _, _ interface{}, _ interface{}, stage boshui.Stage) { Expect(fakeStage.SubStages).To(ContainElement(stage)) }).Return(nil, expectedDeployError).AnyTimes() @@ -1067,6 +1066,7 @@ var _ = Describe("CreateEnvCmd", func() { mockBlobstore, expectedSkipDrain, gomock.Any(), + gomock.Any(), ).Return(nil, expectedDeployError).AnyTimes() previousDeploymentState := biconfig.DeploymentState{ @@ -1117,5 +1117,33 @@ var _ = Describe("CreateEnvCmd", func() { Expect(err).ToNot(HaveOccurred()) }) }) + + Context("the deployment state file exists", func() { + It("reads the disks out of the file and passes their CIDs to the deployer", func() { + err := fs.WriteFileString(deploymentStatePath, ` + { + "disks": [ + { + "id": "bc5dd497-b882-4397-6e9f-22f862277217", + "cid": "disk-cid-from-state", + "size": 51200, + "cloud_properties": { + "datastores": [ + "sharedVmfs-0" + ], + "type": "thin" + } + } + ] + }`) + Expect(err).ToNot(HaveOccurred()) + + expectDeploy.Do(func(_, _, _, _, _, _ interface{}, diskCIDs []string, _ interface{}) { + Expect(diskCIDs).To(ConsistOf("disk-cid-from-state")) + }) + err = command.Run(fakeStage, defaultCreateEnvOpts) + Expect(err).NotTo(HaveOccurred()) + }) + }) }) }) diff --git a/cmd/deployment_preparer.go b/cmd/deployment_preparer.go index e5cfbaad1..31cd1d049 100644 --- a/cmd/deployment_preparer.go +++ b/cmd/deployment_preparer.go @@ -199,7 +199,6 @@ func (c *DeploymentPreparer) PrepareDeployment(stage biui.Stage, recreate bool, deploy := func() error { return c.deploy( - installation, deploymentState, extractedStemcell, installationManifest, @@ -230,7 +229,6 @@ func (c *DeploymentPreparer) PrepareDeployment(stage biui.Stage, recreate bool, } func (c *DeploymentPreparer) deploy( - installation biinstall.Installation, deploymentState biconfig.DeploymentState, extractedStemcell bistemcell.ExtractedStemcell, installationManifest biinstallmanifest.Manifest, @@ -271,6 +269,7 @@ func (c *DeploymentPreparer) deploy( vmManager, blobstore, skipDrain, + c.extractDiskCIDsFromState(deploymentState), deployStage, ) if err != nil { @@ -305,3 +304,13 @@ func (c *DeploymentPreparer) stemcellApiVersion(stemcell bistemcell.ExtractedSte } return stemcellApiVersion } + +// These disk CIDs get passed all the way to the create_vm cpi call +func (c *DeploymentPreparer) extractDiskCIDsFromState(deploymentState biconfig.DeploymentState) []string { + var diskCIDs []string + for _, disk := range deploymentState.Disks { + diskCIDs = append(diskCIDs, disk.CID) + } + + return diskCIDs +} diff --git a/deployment/deployer.go b/deployment/deployer.go index cbd4fcb23..25e1fb1d3 100644 --- a/deployment/deployer.go +++ b/deployment/deployer.go @@ -18,13 +18,14 @@ import ( type Deployer interface { Deploy( - bicloud.Cloud, - bideplmanifest.Manifest, - bistemcell.CloudStemcell, - bivm.Manager, - biblobstore.Blobstore, - bool, - biui.Stage, + cloud bicloud.Cloud, + deploymentManifest bideplmanifest.Manifest, + cloudStemcell bistemcell.CloudStemcell, + vmManager bivm.Manager, + blobstore biblobstore.Blobstore, + skipDrain bool, + diskCIDs []string, + deployStage biui.Stage, ) (Deployment, error) } @@ -58,6 +59,7 @@ func (d *deployer) Deploy( vmManager bivm.Manager, blobstore biblobstore.Blobstore, skipDrain bool, + diskCIDs []string, deployStage biui.Stage, ) (Deployment, error) { instanceManager := d.instanceManagerFactory.NewManager(cloud, vmManager, blobstore) @@ -68,7 +70,7 @@ func (d *deployer) Deploy( return nil, err } - instances, disks, err := d.createAllInstances(deploymentManifest, instanceManager, cloudStemcell, deployStage) + instances, disks, err := d.createAllInstances(deploymentManifest, instanceManager, cloudStemcell, diskCIDs, deployStage) if err != nil { return nil, err } @@ -81,6 +83,7 @@ func (d *deployer) createAllInstances( deploymentManifest bideplmanifest.Manifest, instanceManager biinstance.Manager, cloudStemcell bistemcell.CloudStemcell, + diskCIDs []string, deployStage biui.Stage, ) ([]biinstance.Instance, []bidisk.Disk, error) { instances := []biinstance.Instance{} @@ -95,7 +98,7 @@ func (d *deployer) createAllInstances( return instances, disks, bosherr.Errorf("Job '%s' must have only one instance, found %d", jobSpec.Name, jobSpec.Instances) } for instanceID := 0; instanceID < jobSpec.Instances; instanceID++ { - instance, instanceDisks, err := instanceManager.Create(jobSpec.Name, instanceID, deploymentManifest, cloudStemcell, deployStage) + instance, instanceDisks, err := instanceManager.Create(jobSpec.Name, instanceID, deploymentManifest, cloudStemcell, diskCIDs, deployStage) if err != nil { return instances, disks, bosherr.WrapErrorf(err, "Creating instance '%s/%d'", jobSpec.Name, instanceID) } diff --git a/deployment/deployer_test.go b/deployment/deployer_test.go index d5e439f22..f8662b8e6 100644 --- a/deployment/deployer_test.go +++ b/deployment/deployer_test.go @@ -54,6 +54,7 @@ var _ = Describe("Deployer", func() { fakeStage *fakebiui.FakeStage fakeVM *fakebivm.FakeVM skipDrain bool + diskCIDs []string cloudStemcell bistemcell.CloudStemcell @@ -94,6 +95,7 @@ var _ = Describe("Deployer", func() { } skipDrain = false + diskCIDs = []string{"fake-disk-cid-1"} cloud = fakebicloud.NewFakeCloud() mockAgentClientFactory = mock_httpagent.NewMockAgentClientFactory(mockCtrl) @@ -178,7 +180,7 @@ var _ = Describe("Deployer", func() { }) It("deletes existing vm", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).NotTo(HaveOccurred()) Expect(fakeExistingVM.DeleteCalled).To(Equal(1)) @@ -196,7 +198,7 @@ var _ = Describe("Deployer", func() { Context("when skip-drain is specified", func() { It("skips draining", func() { skipDrain = true - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).NotTo(HaveOccurred()) Expect(fakeExistingVM.DeleteCalled).To(Equal(1)) @@ -213,17 +215,18 @@ var _ = Describe("Deployer", func() { }) It("creates a vm", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).NotTo(HaveOccurred()) Expect(fakeVMManager.CreateInput).To(Equal(fakebivm.CreateInput{ Stemcell: cloudStemcell, Manifest: deploymentManifest, + DiskCIDs: diskCIDs, })) }) It("waits for the vm", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).NotTo(HaveOccurred()) Expect(fakeVM.WaitUntilReadyInputs).To(ContainElement(fakebivm.WaitUntilReadyInput{ Timeout: 10 * time.Minute, @@ -232,7 +235,7 @@ var _ = Describe("Deployer", func() { }) It("logs start and stop events to the eventLogger", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).NotTo(HaveOccurred()) Expect(fakeStage.PerformCalls[1]).To(Equal(&fakebiui.PerformCall{ @@ -250,7 +253,7 @@ var _ = Describe("Deployer", func() { }) It("logs start and stop events to the eventLogger", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-wait-error")) @@ -262,7 +265,7 @@ var _ = Describe("Deployer", func() { }) It("updates the vm", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).NotTo(HaveOccurred()) Expect(fakeVM.ApplyInputs).To(Equal([]fakebivm.ApplyInput{ @@ -272,14 +275,14 @@ var _ = Describe("Deployer", func() { }) It("starts the agent", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).NotTo(HaveOccurred()) Expect(fakeVM.StartCalled).To(Equal(1)) }) It("waits until agent reports state as running", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).NotTo(HaveOccurred()) Expect(fakeVM.WaitToBeRunningInputs).To(ContainElement(fakebivm.WaitInput{ @@ -294,13 +297,13 @@ var _ = Describe("Deployer", func() { }) It("returns an error", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).To(HaveOccurred()) }) }) It("logs instance update ui stages", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).NotTo(HaveOccurred()) Expect(fakeStage.PerformCalls[2:4]).To(Equal([]*fakebiui.PerformCall{ @@ -315,7 +318,7 @@ var _ = Describe("Deployer", func() { }) It("fails with descriptive error", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(Equal("Applying the initial agent state: fake-apply-error")) }) @@ -327,7 +330,7 @@ var _ = Describe("Deployer", func() { }) It("logs start and stop events to the eventLogger", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-start-error")) @@ -347,7 +350,7 @@ var _ = Describe("Deployer", func() { }) It("logs start and stop events to the eventLogger", func() { - _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, fakeStage) + _, err := deployer.Deploy(cloud, deploymentManifest, cloudStemcell, fakeVMManager, mockBlobstore, skipDrain, diskCIDs, fakeStage) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-wait-running-error")) diff --git a/deployment/instance/manager.go b/deployment/instance/manager.go index 7cbd32db8..e85eb754c 100644 --- a/deployment/instance/manager.go +++ b/deployment/instance/manager.go @@ -24,6 +24,7 @@ type Manager interface { id int, deploymentManifest bideplmanifest.Manifest, cloudStemcell bistemcell.CloudStemcell, + diskCIDs []string, eventLoggerStage biui.Stage, ) (Instance, []bidisk.Disk, error) DeleteAll( @@ -97,13 +98,14 @@ func (m *manager) Create( id int, deploymentManifest bideplmanifest.Manifest, cloudStemcell bistemcell.CloudStemcell, + diskCIDs []string, eventLoggerStage biui.Stage, ) (Instance, []bidisk.Disk, error) { var vm bivm.VM stepName := fmt.Sprintf("Creating VM for instance '%s/%d' from stemcell '%s'", jobName, id, cloudStemcell.CID()) err := eventLoggerStage.Perform(stepName, func() error { var err error - vm, err = m.vmManager.Create(cloudStemcell, deploymentManifest) + vm, err = m.vmManager.Create(cloudStemcell, deploymentManifest, diskCIDs) if err != nil { return bosherr.WrapError(err, "Creating VM") } diff --git a/deployment/instance/manager_test.go b/deployment/instance/manager_test.go index 7a8a77286..298533bf6 100644 --- a/deployment/instance/manager_test.go +++ b/deployment/instance/manager_test.go @@ -98,6 +98,7 @@ var _ = Describe("Manager", func() { diskPool bideplmanifest.DiskPool deploymentManifest bideplmanifest.Manifest fakeCloudStemcell *fakebistemcell.FakeCloudStemcell + diskCIDs []string expectedInstance Instance expectedDisk *fakebidisk.FakeDisk @@ -164,6 +165,8 @@ var _ = Describe("Manager", func() { fakeCloudStemcell = fakebistemcell.NewFakeCloudStemcell("fake-stemcell-cid", "fake-stemcell-name", "fake-stemcell-version", apiVersion) + diskCIDs = []string{"fake-disk-cid"} + fakeVM = fakebivm.NewFakeVM("fake-vm-cid") fakeVMManager.CreateVM = fakeVM @@ -194,6 +197,7 @@ var _ = Describe("Manager", func() { 0, deploymentManifest, fakeCloudStemcell, + diskCIDs, fakeStage, ) Expect(err).NotTo(HaveOccurred()) @@ -202,6 +206,7 @@ var _ = Describe("Manager", func() { Expect(fakeVMManager.CreateInput).To(Equal(fakebivm.CreateInput{ Stemcell: fakeCloudStemcell, Manifest: deploymentManifest, + DiskCIDs: diskCIDs, })) }) @@ -211,6 +216,7 @@ var _ = Describe("Manager", func() { 0, deploymentManifest, fakeCloudStemcell, + diskCIDs, fakeStage, ) Expect(err).NotTo(HaveOccurred()) @@ -224,6 +230,7 @@ var _ = Describe("Manager", func() { 0, deploymentManifest, fakeCloudStemcell, + diskCIDs, fakeStage, ) Expect(err).NotTo(HaveOccurred()) @@ -240,6 +247,7 @@ var _ = Describe("Manager", func() { 0, deploymentManifest, fakeCloudStemcell, + diskCIDs, fakeStage, ) Expect(err).NotTo(HaveOccurred()) @@ -262,6 +270,7 @@ var _ = Describe("Manager", func() { 0, deploymentManifest, fakeCloudStemcell, + diskCIDs, fakeStage, ) Expect(err).NotTo(HaveOccurred()) @@ -286,6 +295,7 @@ var _ = Describe("Manager", func() { 0, deploymentManifest, fakeCloudStemcell, + diskCIDs, fakeStage, ) Expect(err).To(HaveOccurred()) @@ -298,6 +308,7 @@ var _ = Describe("Manager", func() { 0, deploymentManifest, fakeCloudStemcell, + diskCIDs, fakeStage, ) Expect(err).To(HaveOccurred()) diff --git a/deployment/instance/mocks/mocks.go b/deployment/instance/mocks/mocks.go index 0b123a6e7..d99f1a0ff 100644 --- a/deployment/instance/mocks/mocks.go +++ b/deployment/instance/mocks/mocks.go @@ -191,9 +191,9 @@ func (m *MockManager) EXPECT() *MockManagerMockRecorder { } // Create mocks base method. -func (m *MockManager) Create(arg0 string, arg1 int, arg2 manifest.Manifest, arg3 stemcell.CloudStemcell, arg4 ui.Stage) (instance.Instance, []disk.Disk, error) { +func (m *MockManager) Create(arg0 string, arg1 int, arg2 manifest.Manifest, arg3 stemcell.CloudStemcell, arg4 []string, arg5 ui.Stage) (instance.Instance, []disk.Disk, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Create", arg0, arg1, arg2, arg3, arg4) + ret := m.ctrl.Call(m, "Create", arg0, arg1, arg2, arg3, arg4, arg5) ret0, _ := ret[0].(instance.Instance) ret1, _ := ret[1].([]disk.Disk) ret2, _ := ret[2].(error) @@ -201,9 +201,9 @@ func (m *MockManager) Create(arg0 string, arg1 int, arg2 manifest.Manifest, arg3 } // Create indicates an expected call of Create. -func (mr *MockManagerMockRecorder) Create(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { +func (mr *MockManagerMockRecorder) Create(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockManager)(nil).Create), arg0, arg1, arg2, arg3, arg4) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockManager)(nil).Create), arg0, arg1, arg2, arg3, arg4, arg5) } // DeleteAll mocks base method. diff --git a/deployment/mocks/mocks.go b/deployment/mocks/mocks.go index d53d9c010..477a805a1 100644 --- a/deployment/mocks/mocks.go +++ b/deployment/mocks/mocks.go @@ -146,18 +146,18 @@ func (m *MockDeployer) EXPECT() *MockDeployerMockRecorder { } // Deploy mocks base method. -func (m *MockDeployer) Deploy(arg0 cloud.Cloud, arg1 manifest.Manifest, arg2 stemcell.CloudStemcell, arg3 vm.Manager, arg4 blobstore.Blobstore, arg5 bool, arg6 ui.Stage) (deployment.Deployment, error) { +func (m *MockDeployer) Deploy(arg0 cloud.Cloud, arg1 manifest.Manifest, arg2 stemcell.CloudStemcell, arg3 vm.Manager, arg4 blobstore.Blobstore, arg5 bool, arg6 []string, arg7 ui.Stage) (deployment.Deployment, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Deploy", arg0, arg1, arg2, arg3, arg4, arg5, arg6) + ret := m.ctrl.Call(m, "Deploy", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) ret0, _ := ret[0].(deployment.Deployment) ret1, _ := ret[1].(error) return ret0, ret1 } // Deploy indicates an expected call of Deploy. -func (mr *MockDeployerMockRecorder) Deploy(arg0, arg1, arg2, arg3, arg4, arg5, arg6 interface{}) *gomock.Call { +func (mr *MockDeployerMockRecorder) Deploy(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Deploy", reflect.TypeOf((*MockDeployer)(nil).Deploy), arg0, arg1, arg2, arg3, arg4, arg5, arg6) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Deploy", reflect.TypeOf((*MockDeployer)(nil).Deploy), arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) } // MockManager is a mock of Manager interface. diff --git a/deployment/vm/fakes/fake_manager.go b/deployment/vm/fakes/fake_manager.go index 975881ae5..2285566f2 100644 --- a/deployment/vm/fakes/fake_manager.go +++ b/deployment/vm/fakes/fake_manager.go @@ -9,6 +9,7 @@ import ( type CreateInput struct { Stemcell bistemcell.CloudStemcell Manifest bideplmanifest.Manifest + DiskCIDs []string } type FakeManager struct { @@ -33,10 +34,11 @@ func (m *FakeManager) FindCurrent() (bivm.VM, bool, error) { return m.findCurrentBehaviour.vm, m.findCurrentBehaviour.found, m.findCurrentBehaviour.err } -func (m *FakeManager) Create(stemcell bistemcell.CloudStemcell, deploymentManifest bideplmanifest.Manifest) (bivm.VM, error) { +func (m *FakeManager) Create(stemcell bistemcell.CloudStemcell, deploymentManifest bideplmanifest.Manifest, diskCIDs []string) (bivm.VM, error) { input := CreateInput{ Stemcell: stemcell, Manifest: deploymentManifest, + DiskCIDs: diskCIDs, } m.CreateInput = input diff --git a/deployment/vm/manager.go b/deployment/vm/manager.go index f7608803d..946f45afe 100644 --- a/deployment/vm/manager.go +++ b/deployment/vm/manager.go @@ -20,7 +20,7 @@ import ( type Manager interface { FindCurrent() (VM, bool, error) - Create(bistemcell.CloudStemcell, bideplmanifest.Manifest) (VM, error) + Create(stemcell bistemcell.CloudStemcell, deploymentManifest bideplmanifest.Manifest, diskCIDs []string) (VM, error) } type manager struct { @@ -86,7 +86,7 @@ func (m *manager) FindCurrent() (VM, bool, error) { return vm, true, err } -func (m *manager) Create(stemcell bistemcell.CloudStemcell, deploymentManifest bideplmanifest.Manifest) (VM, error) { +func (m *manager) Create(stemcell bistemcell.CloudStemcell, deploymentManifest bideplmanifest.Manifest, diskCIDs []string) (VM, error) { jobName := deploymentManifest.JobName() networkInterfaces, err := deploymentManifest.NetworkInterfaces(jobName) m.logger.Debug(m.logTag, "Creating VM with network interfaces: %#v", networkInterfaces) @@ -113,7 +113,7 @@ func (m *manager) Create(stemcell bistemcell.CloudStemcell, deploymentManifest b } } } - cid, err := m.createAndRecordVM(agentID, stemcell, resourcePool, networkInterfaces) + cid, err := m.createAndRecordVM(agentID, stemcell, resourcePool, diskCIDs, networkInterfaces) if err != nil { return nil, err } @@ -158,8 +158,8 @@ func (m *manager) Create(stemcell bistemcell.CloudStemcell, deploymentManifest b return vm, nil } -func (m *manager) createAndRecordVM(agentID string, stemcell bistemcell.CloudStemcell, resourcePool bideplmanifest.ResourcePool, networkInterfaces map[string]biproperty.Map) (string, error) { - cid, err := m.cloud.CreateVM(agentID, stemcell.CID(), resourcePool.CloudProperties, networkInterfaces, resourcePool.Env) +func (m *manager) createAndRecordVM(agentID string, stemcell bistemcell.CloudStemcell, resourcePool bideplmanifest.ResourcePool, diskCIDs []string, networkInterfaces map[string]biproperty.Map) (string, error) { + cid, err := m.cloud.CreateVM(agentID, stemcell.CID(), resourcePool.CloudProperties, diskCIDs, networkInterfaces, resourcePool.Env) if err != nil { return "", bosherr.WrapErrorf(err, "Creating vm with stemcell cid '%s'", stemcell.CID()) } diff --git a/deployment/vm/manager_test.go b/deployment/vm/manager_test.go index 42d2f0412..5068b862c 100644 --- a/deployment/vm/manager_test.go +++ b/deployment/vm/manager_test.go @@ -38,6 +38,7 @@ var _ = Describe("Manager", func() { fakeDiskDeployer *fakebivm.FakeDiskDeployer fakeAgentClient *fakebiagentclient.FakeAgentClient stemcell bistemcell.CloudStemcell + diskCIDs []string fs *fakesys.FakeFileSystem fakeTimeService Clock ) @@ -56,6 +57,7 @@ var _ = Describe("Manager", func() { fakeDiskDeployer = fakebivm.NewFakeDiskDeployer() fakeTime := time.Date(2016, time.November, 10, 23, 0, 0, 0, time.UTC) fakeTimeService = &FakeClock{Times: []time.Time{fakeTime, time.Now().Add(10 * time.Minute)}} + diskCIDs = []string{"fake-disk-cid-1"} manager = NewManager( fakeVMRepo, @@ -124,7 +126,7 @@ var _ = Describe("Manager", func() { Describe("Create", func() { It("creates a VM", func() { - vm, err := manager.Create(stemcell, deploymentManifest) + vm, err := manager.Create(stemcell, deploymentManifest, diskCIDs) Expect(err).ToNot(HaveOccurred()) expectedVM := NewVMWithMetadata( "fake-vm-cid", @@ -153,6 +155,7 @@ var _ = Describe("Manager", func() { AgentID: "fake-uuid-0", StemcellCID: "fake-stemcell-cid", CloudProperties: expectedCloudProperties, + DiskCIDs: diskCIDs, NetworksInterfaces: expectedNetworkInterfaces, Env: expectedEnv, }, @@ -160,7 +163,7 @@ var _ = Describe("Manager", func() { }) It("sets the vm metadata", func() { - _, err := manager.Create(stemcell, deploymentManifest) + _, err := manager.Create(stemcell, deploymentManifest, diskCIDs) Expect(err).ToNot(HaveOccurred()) Expect(fakeCloud.SetVMMetadataCid).To(Equal("fake-vm-cid")) Expect(fakeCloud.SetVMMetadataMetadata).To(Equal(cloud.VMMetadata{ @@ -191,7 +194,7 @@ var _ = Describe("Manager", func() { }, } - _, err := manager.Create(stemcell, deploymentManifest) + _, err := manager.Create(stemcell, deploymentManifest, diskCIDs) Expect(err).ToNot(HaveOccurred()) Expect(fakeCloud.CreateVMInput).To(Equal( @@ -199,6 +202,7 @@ var _ = Describe("Manager", func() { AgentID: "fake-uuid-0", StemcellCID: "fake-stemcell-cid", CloudProperties: expectedCloudProperties, + DiskCIDs: diskCIDs, NetworksInterfaces: expectedNetworkInterfaces, Env: expectedEnv, }, @@ -228,7 +232,7 @@ var _ = Describe("Manager", func() { "name": "awesome-name", } - _, err := manager.Create(stemcell, deploymentManifest) + _, err := manager.Create(stemcell, deploymentManifest, diskCIDs) Expect(err).ToNot(HaveOccurred()) Expect(fakeCloud.SetVMMetadataMetadata).To(Equal(cloud.VMMetadata{ @@ -245,7 +249,7 @@ var _ = Describe("Manager", func() { }) It("updates the current vm record", func() { - _, err := manager.Create(stemcell, deploymentManifest) + _, err := manager.Create(stemcell, deploymentManifest, diskCIDs) Expect(err).ToNot(HaveOccurred()) Expect(fakeVMRepo.UpdateCurrentCID).To(Equal("fake-vm-cid")) @@ -257,13 +261,13 @@ var _ = Describe("Manager", func() { }) It("returns an error", func() { - _, err := manager.Create(stemcell, deploymentManifest) + _, err := manager.Create(stemcell, deploymentManifest, diskCIDs) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-set-metadata-error")) }) It("still updates the current vm record", func() { - _, err := manager.Create(stemcell, deploymentManifest) + _, err := manager.Create(stemcell, deploymentManifest, diskCIDs) Expect(err).To(HaveOccurred()) Expect(fakeVMRepo.UpdateCurrentCID).To(Equal("fake-vm-cid")) }) @@ -276,7 +280,7 @@ var _ = Describe("Manager", func() { }) fakeCloud.SetVMMetadataError = notImplementedCloudError - _, err := manager.Create(stemcell, deploymentManifest) + _, err := manager.Create(stemcell, deploymentManifest, diskCIDs) Expect(err).ToNot(HaveOccurred()) }) }) @@ -287,7 +291,7 @@ var _ = Describe("Manager", func() { }) It("returns an error", func() { - _, err := manager.Create(stemcell, deploymentManifest) + _, err := manager.Create(stemcell, deploymentManifest, diskCIDs) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-create-error")) }) diff --git a/integration/create_env_test.go b/integration/create_env_test.go index 3433d7f55..3bcb0bf56 100644 --- a/integration/create_env_test.go +++ b/integration/create_env_test.go @@ -495,7 +495,7 @@ cloud_provider: gomock.InOrder( mockCloud.EXPECT().Info().Return(bicloud.CpiInfo{ApiVersion: cpiApiVersion}, nil).AnyTimes(), mockCloud.EXPECT().CreateStemcell(filepath.Join("fake-stemcell-extracted-dir", "image"), stemcellCloudProperties).Return(stemcellCID, nil), - mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, networkInterfaces, vmEnv).Return(vmCID, nil), + mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, gomock.Any(), networkInterfaces, vmEnv).Return(vmCID, nil), mockCloud.EXPECT().SetVMMetadata(vmCID, gomock.Any()).Return(nil), mockAgentClient.EXPECT().Ping().Return("any-state", nil), @@ -542,7 +542,7 @@ cloud_provider: mockCloud.EXPECT().DeleteVM(oldVMCID), // create new vm - mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, networkInterfaces, vmEnv).Return(newVMCID, nil), + mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, []string{oldDiskCID}, networkInterfaces, vmEnv).Return(newVMCID, nil), mockCloud.EXPECT().SetVMMetadata(newVMCID, gomock.Any()).Return(nil), mockAgentClient.EXPECT().Ping().Return("any-state", nil), @@ -594,7 +594,7 @@ cloud_provider: expectDeleteVM1, // create new vm - mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, networkInterfaces, vmEnv).Return(newVMCID, nil), + mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, []string{oldDiskCID}, networkInterfaces, vmEnv).Return(newVMCID, nil), mockCloud.EXPECT().SetVMMetadata(newVMCID, gomock.Any()).Return(nil), mockAgentClient.EXPECT().Ping().Return("any-state", nil), @@ -649,7 +649,7 @@ cloud_provider: mockCloud.EXPECT().DeleteVM(oldVMCID), // create new vm - mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, networkInterfaces, vmEnv).Return(newVMCID, nil), + mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, []string{oldDiskCID}, networkInterfaces, vmEnv).Return(newVMCID, nil), mockCloud.EXPECT().SetVMMetadata(newVMCID, gomock.Any()).Return(nil), mockAgentClient.EXPECT().Ping().Return("any-state", nil), @@ -687,7 +687,7 @@ cloud_provider: mockCloud.EXPECT().DeleteVM(oldVMCID), // create new vm - mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, networkInterfaces, vmEnv).Return(newVMCID, nil), + mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, []string{oldDiskCID}, networkInterfaces, vmEnv).Return(newVMCID, nil), mockCloud.EXPECT().SetVMMetadata(newVMCID, gomock.Any()).Return(nil), mockAgentClient.EXPECT().Ping().Return("any-state", nil), @@ -709,7 +709,7 @@ cloud_provider: ) } - var expectDeployWithDiskMigrationRepair = func() { + var expectDeployWithDiskMigrationRepair = func(failedMigrationDiskCID string) { agentID := "fake-uuid-2" oldVMCID := "fake-vm-cid-2" newVMCID := "fake-vm-cid-3" @@ -731,7 +731,7 @@ cloud_provider: mockAgentClient.EXPECT().UnmountDisk(oldDiskCID), mockCloud.EXPECT().DeleteVM(oldVMCID), - mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, networkInterfaces, vmEnv).Return(newVMCID, nil), + mockCloud.EXPECT().CreateVM(agentID, stemcellCID, vmCloudProperties, []string{oldDiskCID, failedMigrationDiskCID}, networkInterfaces, vmEnv).Return(newVMCID, nil), mockCloud.EXPECT().SetVMMetadata(newVMCID, gomock.Any()).Return(nil), mockAgentClient.EXPECT().Ping().Return("any-state", nil), @@ -980,9 +980,10 @@ cloud_provider: }) It("deletes unused disks", func() { - expectDeployWithDiskMigrationRepair() + failedMigrationDiskCID := "fake-disk-cid-2" + expectDeployWithDiskMigrationRepair(failedMigrationDiskCID) - mockCloud.EXPECT().DeleteDisk("fake-disk-cid-2") + mockCloud.EXPECT().DeleteDisk(failedMigrationDiskCID) err := newCreateEnvCmd().Run(fakeStage, newDeployOpts(deploymentManifestPath, "")) Expect(err).ToNot(HaveOccurred()) @@ -1002,7 +1003,7 @@ cloud_provider: var expectNoDeployHappened = func() { expectDeleteVM := mockCloud.EXPECT().DeleteVM(gomock.Any()) expectDeleteVM.Times(0) - expectCreateVM := mockCloud.EXPECT().CreateVM(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) + expectCreateVM := mockCloud.EXPECT().CreateVM(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) expectCreateVM.Times(0) mockCloud.EXPECT().HasVM(gomock.Any()).Return(true, nil).AnyTimes()