1package instance 2 3import ( 4 "fmt" 5 "time" 6 7 biblobstore "github.com/cloudfoundry/bosh-cli/blobstore" 8 bicloud "github.com/cloudfoundry/bosh-cli/cloud" 9 bidisk "github.com/cloudfoundry/bosh-cli/deployment/disk" 10 bideplmanifest "github.com/cloudfoundry/bosh-cli/deployment/manifest" 11 bisshtunnel "github.com/cloudfoundry/bosh-cli/deployment/sshtunnel" 12 bivm "github.com/cloudfoundry/bosh-cli/deployment/vm" 13 biinstallmanifest "github.com/cloudfoundry/bosh-cli/installation/manifest" 14 bistemcell "github.com/cloudfoundry/bosh-cli/stemcell" 15 biui "github.com/cloudfoundry/bosh-cli/ui" 16 bosherr "github.com/cloudfoundry/bosh-utils/errors" 17 boshlog "github.com/cloudfoundry/bosh-utils/logger" 18) 19 20type Manager interface { 21 FindCurrent() ([]Instance, error) 22 Create( 23 jobName string, 24 id int, 25 deploymentManifest bideplmanifest.Manifest, 26 cloudStemcell bistemcell.CloudStemcell, 27 registryConfig biinstallmanifest.Registry, 28 eventLoggerStage biui.Stage, 29 ) (Instance, []bidisk.Disk, error) 30 DeleteAll( 31 pingTimeout time.Duration, 32 pingDelay time.Duration, 33 skipDrain bool, 34 eventLoggerStage biui.Stage, 35 ) error 36} 37 38type manager struct { 39 cloud bicloud.Cloud 40 vmManager bivm.Manager 41 blobstore biblobstore.Blobstore 42 sshTunnelFactory bisshtunnel.Factory 43 instanceFactory Factory 44 logger boshlog.Logger 45 logTag string 46} 47 48func NewManager( 49 cloud bicloud.Cloud, 50 vmManager bivm.Manager, 51 blobstore biblobstore.Blobstore, 52 sshTunnelFactory bisshtunnel.Factory, 53 instanceFactory Factory, 54 logger boshlog.Logger, 55) Manager { 56 return &manager{ 57 cloud: cloud, 58 vmManager: vmManager, 59 blobstore: blobstore, 60 sshTunnelFactory: sshTunnelFactory, 61 instanceFactory: instanceFactory, 62 logger: logger, 63 logTag: "vmDeployer", 64 } 65} 66 67func (m *manager) FindCurrent() ([]Instance, error) { 68 instances := []Instance{} 69 70 // Only one current instance will exist (for now) 71 vm, found, err := m.vmManager.FindCurrent() 72 if err != nil { 73 return instances, bosherr.WrapError(err, "Finding currently deployed instances") 74 } 75 76 if found { 77 // TODO: store the name of the job for each instance in the repo, so that we can print it when deleting 78 jobName := "unknown" 79 instanceID := 0 80 81 instance := m.instanceFactory.NewInstance( 82 jobName, 83 instanceID, 84 vm, 85 m.vmManager, 86 m.sshTunnelFactory, 87 m.blobstore, 88 m.logger, 89 ) 90 instances = append(instances, instance) 91 } 92 93 return instances, nil 94} 95 96func (m *manager) Create( 97 jobName string, 98 id int, 99 deploymentManifest bideplmanifest.Manifest, 100 cloudStemcell bistemcell.CloudStemcell, 101 registryConfig biinstallmanifest.Registry, 102 eventLoggerStage biui.Stage, 103) (Instance, []bidisk.Disk, error) { 104 var vm bivm.VM 105 stepName := fmt.Sprintf("Creating VM for instance '%s/%d' from stemcell '%s'", jobName, id, cloudStemcell.CID()) 106 err := eventLoggerStage.Perform(stepName, func() error { 107 var err error 108 vm, err = m.vmManager.Create(cloudStemcell, deploymentManifest) 109 if err != nil { 110 return bosherr.WrapError(err, "Creating VM") 111 } 112 113 if err = cloudStemcell.PromoteAsCurrent(); err != nil { 114 return bosherr.WrapErrorf(err, "Promoting stemcell as current '%s'", cloudStemcell.CID()) 115 } 116 117 return nil 118 }) 119 if err != nil { 120 return nil, []bidisk.Disk{}, err 121 } 122 123 instance := m.instanceFactory.NewInstance(jobName, id, vm, m.vmManager, m.sshTunnelFactory, m.blobstore, m.logger) 124 125 if err := instance.WaitUntilReady(registryConfig, eventLoggerStage); err != nil { 126 return instance, []bidisk.Disk{}, bosherr.WrapError(err, "Waiting until instance is ready") 127 } 128 129 disks, err := instance.UpdateDisks(deploymentManifest, eventLoggerStage) 130 if err != nil { 131 return instance, disks, bosherr.WrapError(err, "Updating instance disks") 132 } 133 134 return instance, disks, err 135} 136 137func (m *manager) DeleteAll( 138 pingTimeout time.Duration, 139 pingDelay time.Duration, 140 skipDrain bool, 141 eventLoggerStage biui.Stage, 142) error { 143 instances, err := m.FindCurrent() 144 if err != nil { 145 return err 146 } 147 148 for _, instance := range instances { 149 if err = instance.Delete(pingTimeout, pingDelay, skipDrain, eventLoggerStage); err != nil { 150 return bosherr.WrapErrorf(err, "Deleting existing instance '%s/%d'", instance.JobName(), instance.ID()) 151 } 152 } 153 return nil 154} 155