func InitVMPoolDB(retryTimeout time.Duration, retryInterval time.Duration, logger boshlog.Logger) error { SQLITE_DB_FOLDER = common.GetOSEnvVariable("SQLITE_DB_FOLDER", "/var/vcap/store/director/") SQLITE_DB_FILE = common.GetOSEnvVariable("SQLITE_DB_FILE", "vm_pool.sqlite") SQLITE_DB_FILE_PATH = filepath.Join(SQLITE_DB_FOLDER, SQLITE_DB_FILE) err := os.MkdirAll(SQLITE_DB_FOLDER, os.ModePerm) if err != nil { return bosherr.WrapError(err, "Failed to make directory: "+SQLITE_DB_FOLDER) } db, err := OpenDB(SQLITE_DB_FILE_PATH) defer db.Close() if err != nil { return bosherr.WrapError(err, "Opening DB") } sqlStmt := `CREATE TABLE IF NOT EXISTS vms (id int not null primary key, name varchar(32), in_use varchar(32), public_ip varchar(32), private_ip varchar(32), root_pwd varchar(32), image_id varchar(64), agent_id varchar(32), timestamp timestamp)` err = exec(db, sqlStmt, retryTimeout, retryInterval, logger) if err != nil { return bosherr.WrapError(err, "Failed to execute sql statement: "+sqlStmt) } return nil }
func (vm SoftLayerVM) Delete(agentID string) error { if strings.ToUpper(common.GetOSEnvVariable("OS_RELOAD_ENABLED", "TRUE")) == "FALSE" { if strings.ToUpper(common.GetOSEnvVariable("DEL_NOT_ALLOWED", "FALSE")) == "FALSE" { return vm.DeleteVM() } else { return bosherr.Error("DEL_NOT_ALLOWED is set to TRUE, the VM deletion reqeust is refused.") } } err := bslcvmpool.InitVMPoolDB(bslcvmpool.DB_RETRY_TIMEOUT, bslcvmpool.DB_RETRY_INTERVAL, vm.logger) if err != nil { return bosherr.WrapError(err, "Failed to initialize VM pool DB") } db, err := bslcvmpool.OpenDB(bslcvmpool.SQLITE_DB_FILE_PATH) if err != nil { return bosherr.WrapError(err, "Opening DB") } vmInfoDB := bslcvmpool.NewVMInfoDB(vm.id, "", "", "", "", vm.logger, db) defer vmInfoDB.CloseDB() err = vmInfoDB.QueryVMInfobyID(bslcvmpool.DB_RETRY_TIMEOUT, bslcvmpool.DB_RETRY_INTERVAL) if err != nil { return bosherr.WrapError(err, fmt.Sprintf("Failed to query VM info by given ID %d", vm.id)) } vm.logger.Info(SOFTLAYER_VM_LOG_TAG, fmt.Sprintf("vmInfoDB.vmProperties.id is %d", vmInfoDB.VmProperties.Id)) if vmInfoDB.VmProperties.Id != 0 { if agentID != "" { vm.logger.Info(SOFTLAYER_VM_LOG_TAG, fmt.Sprintf("Release the VM with id %d back to the VM pool", vmInfoDB.VmProperties.Id)) vmInfoDB.VmProperties.InUse = "f" err = vmInfoDB.UpdateVMInfoByID(bslcvmpool.DB_RETRY_TIMEOUT, bslcvmpool.DB_RETRY_INTERVAL) if err != nil { return bosherr.WrapError(err, fmt.Sprintf("Failed to update in_use to %s by given ID %d", vmInfoDB.VmProperties.InUse, vm.id)) } else { return nil } } else { if strings.ToUpper(common.GetOSEnvVariable("DEL_NOT_ALLOWED", "FALSE")) == "FALSE" { return vm.DeleteVM() } else { return bosherr.Error("DEL_NOT_ALLOWED is set to TRUE, the VM deletion reqeust is refused.") } } } else { if strings.ToUpper(common.GetOSEnvVariable("DEL_NOT_ALLOWED", "FALSE")) == "FALSE" { return vm.DeleteVM() } else { return bosherr.Error("DEL_NOT_ALLOWED is set to TRUE, the VM deletion reqeust is refused.") } } }
func (vm SoftLayerVM) DeleteVM() error { virtualGuestService, err := vm.softLayerClient.GetSoftLayer_Virtual_Guest_Service() if err != nil { return bosherr.WrapError(err, "Creating SoftLayer VirtualGuestService from client") } vmCID := vm.ID() err = bslcommon.WaitForVirtualGuestToHaveNoRunningTransactions(vm.softLayerClient, vmCID) if err != nil { if !strings.Contains(err.Error(), "HTTP error code") { return bosherr.WrapError(err, fmt.Sprintf("Waiting for VirtualGuest `%d` to have no pending transactions before deleting vm", vmCID)) } } deleted, err := virtualGuestService.DeleteObject(vm.ID()) if err != nil { if !strings.Contains(err.Error(), "HTTP error code") { return bosherr.WrapError(err, "Deleting SoftLayer VirtualGuest from client") } } if !deleted { return bosherr.WrapError(nil, "Did not delete SoftLayer VirtualGuest from client") } err = vm.postCheckActiveTransactionsForDeleteVM(vm.softLayerClient, vmCID) if err != nil { if !strings.Contains(err.Error(), "HTTP error code") { return err } } if strings.ToUpper(common.GetOSEnvVariable("OS_RELOAD_ENABLED", "TRUE")) == "TRUE" { db, err := bslcvmpool.OpenDB(bslcvmpool.SQLITE_DB_FILE_PATH) if err != nil { return bosherr.WrapError(err, "Opening DB") } vmInfoDB := bslcvmpool.NewVMInfoDB(vm.ID(), "", "", "", "", vm.logger, db) err = vmInfoDB.DeleteVMFromVMDB(bslcvmpool.DB_RETRY_TIMEOUT, bslcvmpool.DB_RETRY_INTERVAL) if err != nil { return bosherr.WrapError(err, "Failed to delete the record from VM pool DB") } } return nil }
func (c SoftLayerCreator) CreateNewVM(agentID string, stemcell bslcstem.Stemcell, cloudProps VMCloudProperties, networks Networks, env Environment) (VM, error) { virtualGuestTemplate, err := CreateVirtualGuestTemplate(stemcell, cloudProps) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Creating virtual guest template") } virtualGuestService, err := c.softLayerClient.GetSoftLayer_Virtual_Guest_Service() if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Creating VirtualGuestService from SoftLayer client") } virtualGuest, err := virtualGuestService.CreateObject(virtualGuestTemplate) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Creating VirtualGuest from SoftLayer client") } if cloudProps.EphemeralDiskSize == 0 { err = bslcommon.WaitForVirtualGuestLastCompleteTransaction(c.softLayerClient, virtualGuest.Id, "Service Setup") if err != nil { return SoftLayerVM{}, bosherr.WrapErrorf(err, "Waiting for VirtualGuest `%d` has Service Setup transaction complete", virtualGuest.Id) } } else { err = bslcommon.AttachEphemeralDiskToVirtualGuest(c.softLayerClient, virtualGuest.Id, cloudProps.EphemeralDiskSize, c.logger) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, fmt.Sprintf("Attaching ephemeral disk to VirtualGuest `%d`", virtualGuest.Id)) } } virtualGuest, err = bslcommon.GetObjectDetailsOnVirtualGuest(c.softLayerClient, virtualGuest.Id) if err != nil { return SoftLayerVM{}, bosherr.WrapErrorf(err, "Cannot get details from virtual guest with id: %d.", virtualGuest.Id) } softlayerFileService := NewSoftlayerFileService(util.GetSshClient(), virtualGuest, c.logger, c.uuidGenerator, c.fs) agentEnvService := c.agentEnvServiceFactory.New(softlayerFileService, strconv.Itoa(virtualGuest.Id)) if len(cloudProps.BoshIp) == 0 { // update /etc/hosts file of bosh-init vm c.updateEtcHostsOfBoshInit(fmt.Sprintf("%s %s", virtualGuest.PrimaryBackendIpAddress, virtualGuest.FullyQualifiedDomainName)) // Update mbus url setting for bosh director: construct mbus url with new director ip mbus, err := c.parseMbusURL(c.agentOptions.Mbus, virtualGuest.PrimaryBackendIpAddress) if err != nil { return SoftLayerVM{}, bosherr.WrapErrorf(err, "Cannot construct mbus url.") } c.agentOptions.Mbus = mbus } else { // Update mbus url setting mbus, err := c.parseMbusURL(c.agentOptions.Mbus, cloudProps.BoshIp) if err != nil { return SoftLayerVM{}, bosherr.WrapErrorf(err, "Cannot construct mbus url.") } c.agentOptions.Mbus = mbus // Update blobstore setting switch c.agentOptions.Blobstore.Provider { case BlobstoreTypeDav: davConf := DavConfig(c.agentOptions.Blobstore.Options) c.updateDavConfig(&davConf, cloudProps.BoshIp) } } agentEnv := CreateAgentUserData(agentID, cloudProps, networks, env, c.agentOptions) if err != nil { return SoftLayerVM{}, bosherr.WrapErrorf(err, "Cannot agent env for virtual guest with id: %d.", virtualGuest.Id) } err = agentEnvService.Update(agentEnv) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Updating VM's agent env") } vm := NewSoftLayerVM(virtualGuest.Id, c.softLayerClient, util.GetSshClient(), agentEnvService, c.logger) if strings.ToUpper(common.GetOSEnvVariable("OS_RELOAD_ENABLED", "TRUE")) == "TRUE" && !strings.Contains(cloudProps.VmNamePrefix, "-worker") { db, err := bslcvmpool.OpenDB(bslcvmpool.SQLITE_DB_FILE_PATH) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Opening DB") } vmInfoDB := bslcvmpool.NewVMInfoDB(vm.ID(), virtualGuestTemplate.Hostname+"."+virtualGuestTemplate.Domain, "t", stemcell.Uuid(), agentID, c.logger, db) err = vmInfoDB.InsertVMInfo(bslcvmpool.DB_RETRY_TIMEOUT, bslcvmpool.DB_RETRY_INTERVAL) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Failed to insert the record into VM pool DB") } } if len(c.agentOptions.VcapPassword) > 0 { err = c.SetVcapPassword(vm, virtualGuest, c.agentOptions.VcapPassword) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Updating VM's vcap password") } } return vm, nil }
func (c SoftLayerCreator) Create(agentID string, stemcell bslcstem.Stemcell, cloudProps VMCloudProperties, networks Networks, env Environment) (VM, error) { if strings.ToUpper(common.GetOSEnvVariable("OS_RELOAD_ENABLED", "TRUE")) == "FALSE" { return c.CreateNewVM(agentID, stemcell, cloudProps, networks, env) } err := bslcvmpool.InitVMPoolDB(bslcvmpool.DB_RETRY_TIMEOUT, bslcvmpool.DB_RETRY_INTERVAL, c.logger) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Failed to initialize VM pool DB") } if strings.Contains(cloudProps.VmNamePrefix, "-worker") { vm, err := c.CreateNewVM(agentID, stemcell, cloudProps, networks, env) return vm, err } db, err := bslcvmpool.OpenDB(bslcvmpool.SQLITE_DB_FILE_PATH) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Opening DB") } vmInfoDB := bslcvmpool.NewVMInfoDB(0, "", "f", "", agentID, c.logger, db) defer vmInfoDB.CloseDB() err = vmInfoDB.QueryVMInfobyAgentID(bslcvmpool.DB_RETRY_TIMEOUT, bslcvmpool.DB_RETRY_INTERVAL) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Failed to query VM info by given agent ID "+agentID) } if vmInfoDB.VmProperties.Id != 0 { c.logger.Info(SOFTLAYER_VM_CREATOR_LOG_TAG, fmt.Sprintf("OS reload on the server id %d with stemcell %d", vmInfoDB.VmProperties.Id, stemcell.ID())) vm := NewSoftLayerVM(vmInfoDB.VmProperties.Id, c.softLayerClient, util.GetSshClient(), nil, c.logger) bslcommon.TIMEOUT = 2 * time.Hour err = vm.ReloadOS(stemcell) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Failed to reload OS") } if cloudProps.EphemeralDiskSize == 0 { err = bslcommon.WaitForVirtualGuestLastCompleteTransaction(c.softLayerClient, vmInfoDB.VmProperties.Id, "Service Setup") if err != nil { return SoftLayerVM{}, bosherr.WrapErrorf(err, "Waiting for VirtualGuest `%d` has Service Setup transaction complete", vmInfoDB.VmProperties.Id) } } else { err = bslcommon.AttachEphemeralDiskToVirtualGuest(c.softLayerClient, vmInfoDB.VmProperties.Id, cloudProps.EphemeralDiskSize, c.logger) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, fmt.Sprintf("Attaching ephemeral disk to VirtualGuest `%d`", vmInfoDB.VmProperties.Id)) } } virtualGuest, err := bslcommon.GetObjectDetailsOnVirtualGuest(c.softLayerClient, vmInfoDB.VmProperties.Id) if err != nil { return SoftLayerVM{}, bosherr.WrapErrorf(err, "Cannot get details from virtual guest with id: %d.", virtualGuest.Id) } softlayerFileService := NewSoftlayerFileService(util.GetSshClient(), virtualGuest, c.logger, c.uuidGenerator, c.fs) agentEnvService := c.agentEnvServiceFactory.New(softlayerFileService, strconv.Itoa(virtualGuest.Id)) if len(cloudProps.BoshIp) == 0 { // update /etc/hosts file of bosh-init vm c.updateEtcHostsOfBoshInit(fmt.Sprintf("%s %s", virtualGuest.PrimaryBackendIpAddress, virtualGuest.FullyQualifiedDomainName)) // Update mbus url setting for bosh director: construct mbus url with new director ip mbus, err := c.parseMbusURL(c.agentOptions.Mbus, virtualGuest.PrimaryBackendIpAddress) if err != nil { return SoftLayerVM{}, bosherr.WrapErrorf(err, "Cannot construct mbus url.") } c.agentOptions.Mbus = mbus } else { // Update mbus url setting mbus, err := c.parseMbusURL(c.agentOptions.Mbus, cloudProps.BoshIp) if err != nil { return SoftLayerVM{}, bosherr.WrapErrorf(err, "Cannot construct mbus url.") } c.agentOptions.Mbus = mbus // Update blobstore setting switch c.agentOptions.Blobstore.Provider { case BlobstoreTypeDav: davConf := DavConfig(c.agentOptions.Blobstore.Options) c.updateDavConfig(&davConf, cloudProps.BoshIp) } } agentEnv := CreateAgentUserData(agentID, cloudProps, networks, env, c.agentOptions) if err != nil { return SoftLayerVM{}, bosherr.WrapErrorf(err, "Cannot agent env for virtual guest with id: %d.", virtualGuest.Id) } err = agentEnvService.Update(agentEnv) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Updating VM's agent env") } vm = NewSoftLayerVM(virtualGuest.Id, c.softLayerClient, util.GetSshClient(), agentEnvService, c.logger) c.logger.Info(SOFTLAYER_VM_CREATOR_LOG_TAG, fmt.Sprintf("Updated in_use flag to 't' for the VM %d in VM pool", vmInfoDB.VmProperties.Id)) vmInfoDB.VmProperties.InUse = "t" err = vmInfoDB.UpdateVMInfoByID(bslcvmpool.DB_RETRY_TIMEOUT, bslcvmpool.DB_RETRY_INTERVAL) if err != nil { return vm, bosherr.WrapError(err, fmt.Sprintf("Failed to query VM info by given ID %d", vm.ID())) } else { if len(c.agentOptions.VcapPassword) > 0 { err = c.SetVcapPassword(vm, virtualGuest, c.agentOptions.VcapPassword) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Updating VM's vcap password") } } return vm, nil } } vmInfoDB.VmProperties.InUse = "" err = vmInfoDB.QueryVMInfobyAgentID(bslcvmpool.DB_RETRY_TIMEOUT, bslcvmpool.DB_RETRY_INTERVAL) if err != nil { return SoftLayerVM{}, bosherr.WrapError(err, "Failed to query VM info by given agent ID "+agentID) } if vmInfoDB.VmProperties.Id != 0 { return SoftLayerVM{}, bosherr.WrapError(err, "Wrong in_use status in VM with agent ID "+agentID+", Do not create a new VM") } else { return c.CreateNewVM(agentID, stemcell, cloudProps, networks, env) } }