From f64c2d8af79f84851de097b095cf1f7383f16048 Mon Sep 17 00:00:00 2001 From: ioito Date: Mon, 22 Apr 2019 18:51:14 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E9=87=8D=E8=A3=85=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=88=9D=E5=A7=8B=E5=8C=96=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/apis/compute/guest_const.go | 3 +- pkg/compute/guestdrivers/azure.go | 3 +- pkg/util/azure/azure.go | 2 +- pkg/util/azure/debug.go | 4 - pkg/util/azure/disk.go | 19 ++- pkg/util/azure/eip.go | 19 ++- pkg/util/azure/host.go | 75 +++++++----- pkg/util/azure/instance.go | 185 +++++++++++++++++++----------- pkg/util/azure/instancenic.go | 4 + pkg/util/azure/publisher.go | 7 +- pkg/util/azure/region.go | 19 ++- pkg/util/azure/shell/instance.go | 40 ++++--- 12 files changed, 249 insertions(+), 131 deletions(-) diff --git a/pkg/apis/compute/guest_const.go b/pkg/apis/compute/guest_const.go index a96c1889eb..f28ea13428 100644 --- a/pkg/apis/compute/guest_const.go +++ b/pkg/apis/compute/guest_const.go @@ -186,7 +186,8 @@ var HOSTTYPE_HYPERVISOR = map[string]string{ } const ( - VM_AWS_DEFAULT_LOGIN_USER = "ec2user" + VM_AWS_DEFAULT_LOGIN_USER = "ec2user" + VM_AZURE_DEFAULT_LOGIN_USER = "toor" VM_METADATA_APP_TAGS = "app_tags" VM_METADATA_CREATE_PARAMS = "create_params" diff --git a/pkg/compute/guestdrivers/azure.go b/pkg/compute/guestdrivers/azure.go index 57384f8620..ae98a49b68 100644 --- a/pkg/compute/guestdrivers/azure.go +++ b/pkg/compute/guestdrivers/azure.go @@ -29,7 +29,6 @@ import ( "yunion.io/x/onecloud/pkg/compute/models" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" - "yunion.io/x/onecloud/pkg/util/ansible" "yunion.io/x/onecloud/pkg/util/billing" ) @@ -142,7 +141,7 @@ func (self *SAzureGuestDriver) GetGuestInitialStateAfterRebuild() string { } func (self *SAzureGuestDriver) GetLinuxDefaultAccount(desc cloudprovider.SManagedVMCreateConfig) string { - return ansible.PUBLIC_CLOUD_ANSIBLE_USER + return api.VM_AZURE_DEFAULT_LOGIN_USER } func (self *SAzureGuestDriver) GetGuestSecgroupVpcid(guest *models.SGuest) (string, error) { diff --git a/pkg/util/azure/azure.go b/pkg/util/azure/azure.go index 9ab6e9d637..762bb8253a 100644 --- a/pkg/util/azure/azure.go +++ b/pkg/util/azure/azure.go @@ -128,7 +128,7 @@ func (self *SAzureClient) getDefaultClient() (*autorest.Client, error) { return nil, err } client.Authorizer = authorizer - if DEBUG { + if self.debug { client.RequestInspector = LogRequest() client.ResponseInspector = LogResponse() } diff --git a/pkg/util/azure/debug.go b/pkg/util/azure/debug.go index 3ce68ac95f..504a842a92 100644 --- a/pkg/util/azure/debug.go +++ b/pkg/util/azure/debug.go @@ -23,10 +23,6 @@ import ( "yunion.io/x/log" ) -const ( - DEBUG = false -) - func LogRequest() autorest.PrepareDecorator { return func(p autorest.Preparer) autorest.Preparer { return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { diff --git a/pkg/util/azure/disk.go b/pkg/util/azure/disk.go index 744021b225..f4097d86c6 100644 --- a/pkg/util/azure/disk.go +++ b/pkg/util/azure/disk.go @@ -124,7 +124,24 @@ func (self *SRegion) DeleteDisk(diskId string) error { func (self *SRegion) deleteDisk(diskId string) error { if !strings.HasPrefix(diskId, "https://") { - return self.client.Delete(diskId) + startTime := time.Now() + timeout := 5 * time.Minute + for { + err := self.client.Delete(diskId) + if err == nil { + return nil + } + // Disk vdisk_stress-testvm-azure-1-1_1555940308395625000 is attached to VM /subscriptions/d4f0ec08-3e28-4ae5-bdf9-3dc7c5b0eeca/resourceGroups/Default/providers/Microsoft.Compute/virtualMachines/stress-testvm-azure-1. + // 更换系统盘后,数据未刷新会出现如上错误,多尝试几次即可 + if strings.Contains(err.Error(), "is attached to VM") { + time.Sleep(time.Second * 5) + } else { + return err + } + if time.Now().Sub(startTime) > timeout { + return err + } + } } //TODO return cloudprovider.ErrNotImplemented diff --git a/pkg/util/azure/eip.go b/pkg/util/azure/eip.go index 0375ed44e1..4d383b878d 100644 --- a/pkg/util/azure/eip.go +++ b/pkg/util/azure/eip.go @@ -123,7 +123,24 @@ func (self *SEipAddress) Delete() error { } func (region *SRegion) DeallocateEIP(eipId string) error { - return region.client.Delete(eipId) + startTime := time.Now() + timeout := time.Minute * 3 + for { + err := region.client.Delete(eipId) + if err == nil { + return nil + } + // {"error":{"code":"PublicIPAddressCannotBeDeleted","details":[],"message":"Public IP address /subscriptions/d4f0ec08-3e28-4ae5-bdf9-3dc7c5b0eeca/resourceGroups/Default/providers/Microsoft.Network/publicIPAddresses/eip-for-test-wwl can not be deleted since it is still allocated to resource /subscriptions/d4f0ec08-3e28-4ae5-bdf9-3dc7c5b0eeca/resourceGroups/Default/providers/Microsoft.Network/networkInterfaces/test-wwl-ipconfig."}} + // 刚解绑eip后可能数据未刷新,需要再次尝试 + if strings.Contains(err.Error(), "it is still allocated to resource") { + time.Sleep(time.Second * 5) + } else { + return err + } + if time.Now().Sub(startTime) > timeout { + return err + } + } } func (self *SEipAddress) Dissociate() error { diff --git a/pkg/util/azure/host.go b/pkg/util/azure/host.go index 77167bdaf8..956f1b76e9 100644 --- a/pkg/util/azure/host.go +++ b/pkg/util/azure/host.go @@ -16,14 +16,17 @@ package azure import ( "fmt" + "strings" "time" + "yunion.io/x/pkg/util/osprofile" + "yunion.io/x/pkg/utils" + "yunion.io/x/jsonutils" "yunion.io/x/log" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudprovider" - "yunion.io/x/onecloud/pkg/util/ansible" "yunion.io/x/onecloud/pkg/util/seclib2" ) @@ -103,7 +106,7 @@ func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudpr desc.Password = seclib2.RandomPassword2(12) } - vmId, err := self._createVM(desc.Name, desc.ExternalImageId, desc.SysDisk, desc.Cpu, desc.MemoryMB, desc.InstanceType, nic.ID, desc.IpAddr, desc.Description, desc.Password, desc.DataDisks, desc.PublicKey, desc.UserData) + vmId, err := self._createVM(desc, nic.ID) if err != nil { self.zone.region.DeleteNetworkInterface(nic.ID) return nil, err @@ -116,34 +119,45 @@ func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudpr } } -func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SDiskInfo, cpu int, memMB int, instanceType string, nicId string, ipAddr string, desc string, passwd string, dataDisks []cloudprovider.SDiskInfo, publicKey string, userData string) (string, error) { - image, err := self.zone.region.GetImageById(imgId) +func (self *SHost) _createVM(desc *cloudprovider.SManagedVMCreateConfig, nicId string) (string, error) { + image, err := self.zone.region.GetImageById(desc.ExternalImageId) if err != nil { - log.Errorf("Get Image %s fail %s", imgId, err) + log.Errorf("Get Image %s fail %s", desc.ExternalImageId, err) return "", err } if image.Properties.ProvisioningState != ImageStatusAvailable { - log.Errorf("image %s status %s", imgId, image.Properties.ProvisioningState) + log.Errorf("image %s status %s", desc.ExternalImageId, image.Properties.ProvisioningState) return "", fmt.Errorf("image not ready") } - storage, err := self.zone.getStorageByType(sysDisk.StorageType) + storage, err := self.zone.getStorageByType(desc.SysDisk.StorageType) if err != nil { - return "", fmt.Errorf("Storage %s not avaiable: %s", sysDisk.StorageType, err) + return "", fmt.Errorf("Storage %s not avaiable: %s", desc.SysDisk.StorageType, err) + } + if !utils.IsInStringArray(desc.OsType, []string{osprofile.OS_TYPE_LINUX, osprofile.OS_TYPE_WINDOWS}) { + desc.OsType = image.GetOsType() + } + sysDiskSize := int32(desc.SysDisk.SizeGB) + computeName := desc.Name + for _, k := range []string{"`", "~", "!", "@", "#", "$", `%`, "^", "&", "*", "(", ")", "=", "+", "_", "[", "]", "{", "}", "\\", "|", ";", ":", ".", "'", `"`, ",", "<", ">", "/", "?"} { + computeName = strings.Replace(computeName, k, "", -1) + } + if len(computeName) > 15 { + computeName = computeName[:15] } - sysDiskSize := int32(sysDisk.SizeGB) instance := SInstance{ - Name: name, + Name: desc.Name, Location: self.zone.region.Name, Properties: VirtualMachineProperties{ HardwareProfile: HardwareProfile{ VMSize: "", }, OsProfile: OsProfile{ - ComputerName: name, - AdminUsername: ansible.PUBLIC_CLOUD_ANSIBLE_USER, - AdminPassword: passwd, - CustomData: userData, + // Windows computer name cannot be more than 15 characters long, be entirely numeric, or contain the following characters: ` ~ ! @ # $ % ^ & * ( ) = + _ [ ] { } \\ | ; : . ' \" , < > / ?." + ComputerName: computeName, + AdminUsername: api.VM_AZURE_DEFAULT_LOGIN_USER, + AdminPassword: desc.Password, + CustomData: desc.UserData, }, NetworkProfile: NetworkProfile{ NetworkInterfaces: []NetworkInterfaceReference{ @@ -155,34 +169,34 @@ func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SD StorageProfile: StorageProfile{ ImageReference: image.getImageReference(), OsDisk: OSDisk{ - Name: fmt.Sprintf("vdisk_%s_%d", name, time.Now().UnixNano()), + Name: fmt.Sprintf("vdisk_%s_%d", desc.Name, time.Now().UnixNano()), Caching: "ReadWrite", ManagedDisk: &ManagedDiskParameters{ StorageAccountType: storage.Name, }, CreateOption: "FromImage", DiskSizeGB: &sysDiskSize, - OsType: image.GetOsType(), + OsType: desc.OsType, }, }, }, Type: "Microsoft.Compute/virtualMachines", } - if len(publicKey) > 0 { + if len(desc.PublicKey) > 0 { instance.Properties.OsProfile.LinuxConfiguration = &LinuxConfiguration{ DisablePasswordAuthentication: false, SSH: &SSHConfiguration{ PublicKeys: []SSHPublicKey{ - {KeyData: publicKey}, + {KeyData: desc.PublicKey}, }, }, } } _dataDisks := []DataDisk{} - for i := 0; i < len(dataDisks); i++ { - diskName := fmt.Sprintf("vdisk_%s_%d", name, time.Now().UnixNano()) - size := int32(dataDisks[i].SizeGB) + for i := 0; i < len(desc.DataDisks); i++ { + diskName := fmt.Sprintf("vdisk_%s_%d", desc.Name, time.Now().UnixNano()) + size := int32(desc.DataDisks[i].SizeGB) lun := int32(i) _dataDisks = append(_dataDisks, DataDisk{ Name: diskName, @@ -195,28 +209,33 @@ func (self *SHost) _createVM(name string, imgId string, sysDisk cloudprovider.SD instance.Properties.StorageProfile.DataDisks = _dataDisks } - if len(instanceType) > 0 { - instance.Properties.HardwareProfile.VMSize = instanceType - log.Debugf("Try HardwareProfile : %s", instanceType) + if len(desc.InstanceType) > 0 { + instance.Properties.HardwareProfile.VMSize = desc.InstanceType + log.Debugf("Try HardwareProfile : %s", desc.InstanceType) err = self.zone.region.client.Create(jsonutils.Marshal(instance), &instance) if err != nil { - log.Errorf("Failed for %s: %s", instanceType, err) - return "", fmt.Errorf("Failed to create specification %s.%s", instanceType, err.Error()) + log.Errorf("Failed for %s: %s", desc.InstanceType, err) + return "", fmt.Errorf("Failed to create specification %s.%s", desc.InstanceType, err.Error()) } return instance.ID, nil } - for _, profile := range self.zone.region.getHardwareProfile(cpu, memMB) { + for _, profile := range self.zone.region.getHardwareProfile(desc.Cpu, desc.MemoryMB) { instance.Properties.HardwareProfile.VMSize = profile log.Debugf("Try HardwareProfile : %s", profile) err = self.zone.region.client.Create(jsonutils.Marshal(instance), &instance) if err != nil { + for _, key := range []string{`"code":"InvalidParameter"`, `"code":"NicInUse"`} { + if strings.Contains(err.Error(), key) { + return "", err + } + } log.Errorf("Failed for %s: %s", profile, err) continue } return instance.ID, nil } - return "", fmt.Errorf("instance type %dC%dMB not avaiable", cpu, memMB) + return "", fmt.Errorf("instance type %dC%dMB not avaiable", desc.Cpu, desc.MemoryMB) } func (self *SHost) GetAccessIp() string { diff --git a/pkg/util/azure/instance.go b/pkg/util/azure/instance.go index bdbfd05ad9..af1304422b 100644 --- a/pkg/util/azure/instance.go +++ b/pkg/util/azure/instance.go @@ -134,13 +134,22 @@ type Statuses struct { //Time time.Time } -type VMAgent struct { - VmAgentVersion string `json:"vmAgentVersion,omitempty"` - Statuses Statuses `json:"statuses,omitempty"` +type SVMAgent struct { + VmAgentVersion string `json:"vmAgentVersion,omitempty"` + Statuses []Statuses `json:"statuses,omitempty"` +} + +type SExtension struct { + Name string + Type string + TypeHandlerVersion string `json:"typeHandlerVersion,omitempty"` + Statuses []Statuses `json:"statuses,omitempty"` } type VirtualMachineInstanceView struct { - Statuses []Statuses `json:"statuses,omitempty"` + Statuses []Statuses `json:"statuses,omitempty"` + VMAgent SVMAgent `json:"vmAgent,omitempty"` + Extensions []SExtension `json:"extensions,omitempty"` } type DomainName struct { @@ -257,6 +266,50 @@ func (self *SInstance) GetInstanceType() string { return self.Properties.HardwareProfile.VMSize } +func (self *SInstance) WaitEnableVMAccessReady() error { + if self.Properties.InstanceView == nil { + return fmt.Errorf("instance may not install VMAgent or VMAgent not running") + } + if len(self.Properties.InstanceView.VMAgent.VmAgentVersion) > 0 { + startTime := time.Now() + timeout := time.Minute * 5 + for { + status := "" + for _, vmAgent := range self.Properties.InstanceView.VMAgent.Statuses { + status = vmAgent.DisplayStatus + if status == "Ready" { + break + } + log.Debugf("vmAgent %s status: %s waite for ready", self.Properties.InstanceView.VMAgent.VmAgentVersion, vmAgent.DisplayStatus) + time.Sleep(time.Second * 5) + } + if status == "Ready" { + break + } + self.Refresh() + if time.Now().Sub(startTime) > timeout { + return fmt.Errorf("timeout for waitting vmAgent ready, current status: %s", status) + } + } + return nil + } + + for _, extension := range self.Properties.InstanceView.Extensions { + if extension.Name == "enablevmaccess" { + displayStatus := "" + for _, status := range extension.Statuses { + displayStatus = status.DisplayStatus + if displayStatus == "Provisioning succeeded" { + return nil + } + } + return self.host.zone.region.deleteExtension(self.ID, "enablevmaccess") + } + } + + return fmt.Errorf("instance may not install VMAgent or VMAgent not running") +} + func (self *SInstance) getOsDisk() (*SDisk, error) { diskId := self.Properties.StorageProfile.OsDisk.ManagedDisk.ID if osDisk, err := self.getDiskWithStore(diskId); err != nil { @@ -603,6 +656,13 @@ func (region *SRegion) ChangeVMConfig(ctx context.Context, instanceId string, nc } func (self *SInstance) DeployVM(ctx context.Context, name string, password string, publicKey string, deleteKeypair bool, description string) error { + if len(publicKey) > 0 || len(password) > 0 { + // 先判断系统是否安装了vmAgent,然后等待扩展准备完成后再重置密码 + err := self.WaitEnableVMAccessReady() + if err != nil { + return err + } + } return self.host.zone.region.DeployVM(ctx, self.ID, name, password, publicKey, deleteKeypair, description) } @@ -704,33 +764,21 @@ func (region *SRegion) DeployVM(ctx context.Context, instanceId, name, password, if len(publicKey) > 0 { return region.resetPublicKey(instanceId, instance.Properties.OsProfile.AdminUsername, publicKey) } - return region.resetPassword(instanceId, instance.Properties.OsProfile.AdminUsername, password) + if len(password) > 0 { + return region.resetPassword(instanceId, instance.Properties.OsProfile.AdminUsername, password) + } + return nil } func (self *SInstance) RebuildRoot(ctx context.Context, imageId string, passwd string, publicKey string, sysSizeGB int) (string, error) { - return self.host.zone.region.ReplaceSystemDisk(self.ID, imageId, passwd, publicKey, int32(sysSizeGB)) + cpu := self.GetVcpuCount() + memoryMb := self.GetVmemSizeMB() + self.StopVM(ctx, true) + return self.host.zone.region.ReplaceSystemDisk(self, cpu, memoryMb, imageId, passwd, publicKey, sysSizeGB) } -func (region *SRegion) ReplaceSystemDisk(instanceId, imageId, passwd, publicKey string, sysSizeGB int32) (string, error) { - log.Debugf("ReplaceSystemDisk %s image: %s", instanceId, imageId) - instance, err := region.GetInstance(instanceId) - if err != nil { - return "", err - } - image, err := region.GetImageById(imageId) - if err != nil { - return "", err - } - err = region.StopVM(instanceId, true) - if err != nil { - return "", err - } - orgOsType := instance.GetOSType() - destOsType := image.GetOsType() - if orgOsType != destOsType { - return "", fmt.Errorf("Cannot replease osType %s => %s", orgOsType, destOsType) - } - diskName := fmt.Sprintf("vdisk_%s_%d", instance.Name, time.Now().UnixNano()) +func (region *SRegion) ReplaceSystemDisk(instance *SInstance, cpu int8, memoryMb int, imageId, passwd, publicKey string, sysSizeGB int) (string, error) { + log.Debugf("ReplaceSystemDisk %s image: %s", instance.ID, imageId) storageType := instance.Properties.StorageProfile.OsDisk.ManagedDisk.StorageAccountType if len(storageType) == 0 { _disk, err := region.GetDisk(instance.Properties.StorageProfile.OsDisk.ManagedDisk.ID) @@ -739,58 +787,55 @@ func (region *SRegion) ReplaceSystemDisk(instanceId, imageId, passwd, publicKey } storageType = _disk.Sku.Name } - oldDiskId := instance.Properties.StorageProfile.OsDisk.ManagedDisk.ID - disk, err := region.CreateDisk(storageType, diskName, sysSizeGB, "", imageId) + if len(instance.Properties.NetworkProfile.NetworkInterfaces) == 0 { + return "", fmt.Errorf("failed to find network for instance: %s", instance.Name) + } + nicId := instance.Properties.NetworkProfile.NetworkInterfaces[0].ID + nic, err := region.GetNetworkInterfaceDetail(nicId) if err != nil { - log.Errorf("Create system disk error: %v", err) + log.Errorf("failed to find nic %s error: %v", nicId, err) return "", err } - instance.Properties.StorageProfile.OsDisk.Name = disk.Name - instance.Properties.StorageProfile.OsDisk.ManagedDisk.ID = disk.ID - instance.Properties.StorageProfile.OsDisk.ManagedDisk.StorageAccountType = storageType - - instance.Properties.OsProfile.AdminPassword = passwd - if len(publicKey) > 0 { - instance.Properties.OsProfile.LinuxConfiguration = &LinuxConfiguration{ - SSH: &SSHConfiguration{ - PublicKeys: []SSHPublicKey{ - { - KeyData: publicKey, - }, - }, - }, - } + if len(nic.Properties.IPConfigurations) == 0 { + return "", fmt.Errorf("failed to find networkId for nic %s", nicId) } - for i := 0; i < len(instance.Properties.StorageProfile.DataDisks); i++ { - //避免因size更新不及时导致更换系统盘失败 - instance.Properties.StorageProfile.DataDisks[i].DiskSizeGB = nil + if instance.Properties.StorageProfile.OsDisk.DiskSizeGB != nil && *instance.Properties.StorageProfile.OsDisk.DiskSizeGB > int32(sysSizeGB) { + sysSizeGB = int(*instance.Properties.StorageProfile.OsDisk.DiskSizeGB) + } + image, err := region.GetImageById(imageId) + if err != nil { + return "", err + } + if minOsDiskSizeGB := image.GetMinOsDiskSizeGb(); minOsDiskSizeGB > sysSizeGB { + sysSizeGB = minOsDiskSizeGB } + networkId := nic.Properties.IPConfigurations[0].Properties.Subnet.ID + osType := instance.Properties.StorageProfile.OsDisk.OsType + newInstance, err := region.CreateInstanceSimple(instance.Name+"-1", imageId, osType, cpu, memoryMb, sysSizeGB, storageType, []int{}, networkId, passwd, publicKey) + if err != nil { + return "", err + } + + newInstance.StopVM(context.Background(), true) + cloudprovider.WaitStatus(newInstance, api.VM_READY, time.Second*5, time.Minute*5) + + newInstance.deleteVM(context.Background(), true) + + //交换系统盘 + instance.Properties.StorageProfile.OsDisk.ManagedDisk.ID, newInstance.Properties.StorageProfile.OsDisk.ManagedDisk.ID = newInstance.Properties.StorageProfile.OsDisk.ManagedDisk.ID, instance.Properties.StorageProfile.OsDisk.ManagedDisk.ID + instance.Properties.StorageProfile.OsDisk.Name = "" instance.Properties.ProvisioningState = "" instance.Properties.InstanceView = nil err = region.client.Update(jsonutils.Marshal(instance), nil) if err != nil { + // 更新失败,需要删除之前交换过的系统盘 + region.DeleteDisk(instance.Properties.StorageProfile.OsDisk.ManagedDisk.ID) return "", err } - for i := 0; i < 3; i++ { - log.Debugf("try delete old disk: %s", oldDiskId) - if err := region.deleteDisk(oldDiskId); err == nil { - break - } - time.Sleep(time.Second * time.Duration(i*10)) - } - // Azure 数据刷新不及时,需要稍作等待 - for i := 0; i < 3; i++ { - instance, err := region.GetInstance(instanceId) - if err != nil { - return "", err - } - if instance.Properties.StorageProfile.OsDisk.ManagedDisk.ID == disk.ID { - break - } - time.Sleep(time.Second * time.Duration(i*10)) - } - return disk.ID, nil + // 交换成功需要删掉旧的系统盘 + region.DeleteDisk(newInstance.Properties.StorageProfile.OsDisk.ManagedDisk.ID) + return strings.ToLower(instance.Properties.StorageProfile.OsDisk.ManagedDisk.ID), nil } func (self *SInstance) UpdateVM(ctx context.Context, name string) error { @@ -813,7 +858,7 @@ func (self *SRegion) DeleteVM(instanceId string) error { return self.doDeleteVM(instanceId) } -func (self *SInstance) DeleteVM(ctx context.Context) error { +func (self *SInstance) deleteVM(ctx context.Context, keepSysDisk bool) error { sysDiskId := "" if self.Properties.StorageProfile.OsDisk.ManagedDisk != nil { sysDiskId = self.Properties.StorageProfile.OsDisk.ManagedDisk.ID @@ -822,7 +867,7 @@ func (self *SInstance) DeleteVM(ctx context.Context) error { if err != nil { return err } - if len(sysDiskId) > 0 { + if len(sysDiskId) > 0 && !keepSysDisk { err := self.host.zone.region.deleteDisk(sysDiskId) if err != nil { return err @@ -843,6 +888,10 @@ func (self *SInstance) DeleteVM(ctx context.Context) error { return nil } +func (self *SInstance) DeleteVM(ctx context.Context) error { + return self.deleteVM(ctx, false) +} + func (self *SInstance) getDiskWithStore(diskId string) (*SDisk, error) { if disk, err := self.host.zone.region.GetDisk(diskId); err != nil { return nil, err diff --git a/pkg/util/azure/instancenic.go b/pkg/util/azure/instancenic.go index c3acd837f9..7a35af2f48 100644 --- a/pkg/util/azure/instancenic.go +++ b/pkg/util/azure/instancenic.go @@ -169,5 +169,9 @@ func (self *SRegion) CreateNetworkInterface(nicName string, ipAddr string, subne Type: "Microsoft.Network/networkInterfaces", } + if len(ipAddr) == 0 { + instancenic.Properties.IPConfigurations[0].Properties.PrivateIPAllocationMethod = "Dynamic" + } + return &instancenic, self.client.Create(jsonutils.Marshal(&instancenic), &instancenic) } diff --git a/pkg/util/azure/publisher.go b/pkg/util/azure/publisher.go index 4cd617c5c1..47ae996163 100644 --- a/pkg/util/azure/publisher.go +++ b/pkg/util/azure/publisher.go @@ -180,9 +180,10 @@ func publisherGetName(publisher, offer, sku, version string) string { } func publisherGetOsType(publisher string) string { - driver, ok := publisherDrivers[publisher] - if ok { - return driver.OsType + for _publisher, driver := range publisherDrivers { + if strings.ToLower(_publisher) == strings.ToLower(publisher) { + return driver.OsType + } } return "Linux" } diff --git a/pkg/util/azure/region.go b/pkg/util/azure/region.go index 0ad52416bf..538b71cc6f 100644 --- a/pkg/util/azure/region.go +++ b/pkg/util/azure/region.go @@ -414,7 +414,7 @@ func (self *SRegion) fetchInfrastructure() error { return nil } -func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, memGB int, storageType string, dataDiskSizesGB []int, networkId string, passwd string, publicKey string) (*SInstance, error) { +func (self *SRegion) CreateInstanceSimple(name string, imgId, osType string, cpu int8, memMb int, sysDiskSizeGB int, storageType string, dataDiskSizesGB []int, networkId string, passwd string, publicKey string) (*SInstance, error) { izones, err := self.GetIZones() if err != nil { return nil, err @@ -427,22 +427,29 @@ func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, me desc := &cloudprovider.SManagedVMCreateConfig{ Name: name, ExternalImageId: imgId, - SysDisk: cloudprovider.SDiskInfo{SizeGB: 0, StorageType: storageType}, - Cpu: cpu, - MemoryMB: memGB * 1024, + SysDisk: cloudprovider.SDiskInfo{SizeGB: sysDiskSizeGB, StorageType: storageType}, + Cpu: int(cpu), + MemoryMB: memMb, ExternalNetworkId: networkId, Password: seclib2.RandomPassword2(12), DataDisks: []cloudprovider.SDiskInfo{}, PublicKey: publicKey, + OsType: osType, + } + if len(passwd) > 0 { + desc.Password = passwd } for _, sizeGB := range dataDiskSizesGB { desc.DataDisks = append(desc.DataDisks, cloudprovider.SDiskInfo{SizeGB: sizeGB, StorageType: storageType}) } - inst, err := z.getHost().CreateVM(desc) + host := z.getHost() + inst, err := host.CreateVM(desc) if err != nil { return nil, err } - return inst.(*SInstance), nil + instance := inst.(*SInstance) + instance.host = host + return instance, nil } } return nil, fmt.Errorf("cannot find network %s", networkId) diff --git a/pkg/util/azure/shell/instance.go b/pkg/util/azure/shell/instance.go index 0bab4f11e0..6b653091f5 100644 --- a/pkg/util/azure/shell/instance.go +++ b/pkg/util/azure/shell/instance.go @@ -75,18 +75,20 @@ func init() { }) type InstanceCrateOptions struct { - NAME string `help:"name of instance"` - IMAGE string `help:"image ID"` - CPU int `help:"CPU count"` - MEMORYGB int `help:"MemoryGB"` - Disk []int `help:"Data disk sizes int GB"` - STORAGE string `help:"Storage type"` - NETWORK string `help:"Network ID"` - PASSWD string `help:"password"` - PublicKey string `help:"PublicKey"` + NAME string `help:"Name of instance"` + IMAGE string `help:"image ID"` + CPU int8 `help:"CPU count"` + MEMORYGB int `help:"MemoryGB"` + SYSDISKSIZEGB int `help:"System Disk Size"` + Disk []int `help:"Data disk sizes int GB"` + STORAGE string `help:"Storage type"` + NETWORK string `help:"Network ID"` + PASSWD string `help:"password"` + PublicKey string `help:"PublicKey"` + OsType string `help:"Operation system type" choices:"Linux|Windows"` } shellutils.R(&InstanceCrateOptions{}, "instance-create", "Create a instance", func(cli *azure.SRegion, args *InstanceCrateOptions) error { - instance, e := cli.CreateInstanceSimple(args.NAME, args.IMAGE, args.CPU, args.MEMORYGB, args.STORAGE, args.Disk, args.NETWORK, args.PASSWD, args.PublicKey) + instance, e := cli.CreateInstanceSimple(args.NAME, args.IMAGE, args.OsType, args.CPU, args.MEMORYGB, args.SYSDISKSIZEGB, args.STORAGE, args.Disk, args.NETWORK, args.PASSWD, args.PublicKey) if e != nil { return e } @@ -120,18 +122,24 @@ func init() { type InstanceRebuildOptions struct { ID string `help:"Instance ID"` - Image string `help:"Image ID"` + CPU int8 `help:"Instance CPU core"` + MEMORYMB int `help:"Instance Memory MB"` + IMAGE string `help:"Image ID"` Password string `help:"pasword"` PublicKey string `help:"Public Key"` - Size int32 `help:"system disk size in GB"` + Size int `help:"system disk size in GB"` } shellutils.R(&InstanceRebuildOptions{}, "instance-rebuild-root", "Reinstall virtual server system image", func(cli *azure.SRegion, args *InstanceRebuildOptions) error { - if diskID, err := cli.ReplaceSystemDisk(args.ID, args.Image, args.Password, args.PublicKey, args.Size); err != nil { + instance, err := cli.GetInstance(args.ID) + if err != nil { return err - } else { - fmt.Printf("New diskID is %s", diskID) - return nil } + diskId, err := cli.ReplaceSystemDisk(instance, args.CPU, args.MEMORYMB, args.IMAGE, args.Password, args.PublicKey, args.Size) + if err != nil { + return err + } + fmt.Printf("New diskId is %s", diskId) + return nil }) type InstanceDiskOptions struct { From af341a0dce56d9113d43db29a655ce86a1cd84bd Mon Sep 17 00:00:00 2001 From: ioito Date: Wed, 24 Apr 2019 22:06:41 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dtypo=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/util/aliyun/shell/instance.go | 4 ++-- pkg/util/aws/shell/instance.go | 4 ++-- pkg/util/azure/shell/instance.go | 4 ++-- pkg/util/qcloud/shell/instance.go | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkg/util/aliyun/shell/instance.go b/pkg/util/aliyun/shell/instance.go index d78df3f684..ad2958504a 100644 --- a/pkg/util/aliyun/shell/instance.go +++ b/pkg/util/aliyun/shell/instance.go @@ -37,7 +37,7 @@ func init() { return nil }) - type InstanceCrateOptions struct { + type InstanceCreateOptions struct { NAME string `help:"name of instance"` IMAGE string `help:"image ID"` CPU int `help:"CPU count"` @@ -48,7 +48,7 @@ func init() { PASSWD string `help:"password"` PublicKey string `help:"PublicKey"` } - shellutils.R(&InstanceCrateOptions{}, "instance-create", "Create a instance", func(cli *aliyun.SRegion, args *InstanceCrateOptions) error { + shellutils.R(&InstanceCreateOptions{}, "instance-create", "Create a instance", func(cli *aliyun.SRegion, args *InstanceCreateOptions) error { instance, e := cli.CreateInstanceSimple(args.NAME, args.IMAGE, args.CPU, args.MEMORYGB, args.STORAGE, args.Disk, args.VSWITCH, args.PASSWD, args.PublicKey) if e != nil { return e diff --git a/pkg/util/aws/shell/instance.go b/pkg/util/aws/shell/instance.go index 7b7849c4cd..08179dcd0f 100644 --- a/pkg/util/aws/shell/instance.go +++ b/pkg/util/aws/shell/instance.go @@ -39,7 +39,7 @@ func init() { return nil }) - type InstanceCrateOptions struct { + type InstanceCreateOptions struct { NAME string `help:"name of instance"` IMAGE string `help:"image ID"` CPU int `help:"CPU count"` @@ -49,7 +49,7 @@ func init() { NETWORK string `help:"Network ID"` PUBLICKEY string `help:"PublicKey file path"` } - shellutils.R(&InstanceCrateOptions{}, "instance-create", "Create a instance", func(cli *aws.SRegion, args *InstanceCrateOptions) error { + shellutils.R(&InstanceCreateOptions{}, "instance-create", "Create a instance", func(cli *aws.SRegion, args *InstanceCreateOptions) error { content, err := ioutil.ReadFile(args.PUBLICKEY) if err != nil { return err diff --git a/pkg/util/azure/shell/instance.go b/pkg/util/azure/shell/instance.go index 6b653091f5..e979783338 100644 --- a/pkg/util/azure/shell/instance.go +++ b/pkg/util/azure/shell/instance.go @@ -74,7 +74,7 @@ func init() { return nil }) - type InstanceCrateOptions struct { + type InstanceCreateOptions struct { NAME string `help:"Name of instance"` IMAGE string `help:"image ID"` CPU int8 `help:"CPU count"` @@ -87,7 +87,7 @@ func init() { PublicKey string `help:"PublicKey"` OsType string `help:"Operation system type" choices:"Linux|Windows"` } - shellutils.R(&InstanceCrateOptions{}, "instance-create", "Create a instance", func(cli *azure.SRegion, args *InstanceCrateOptions) error { + shellutils.R(&InstanceCreateOptions{}, "instance-create", "Create a instance", func(cli *azure.SRegion, args *InstanceCreateOptions) error { instance, e := cli.CreateInstanceSimple(args.NAME, args.IMAGE, args.OsType, args.CPU, args.MEMORYGB, args.SYSDISKSIZEGB, args.STORAGE, args.Disk, args.NETWORK, args.PASSWD, args.PublicKey) if e != nil { return e diff --git a/pkg/util/qcloud/shell/instance.go b/pkg/util/qcloud/shell/instance.go index 6673d67a3a..8ae8656fa0 100644 --- a/pkg/util/qcloud/shell/instance.go +++ b/pkg/util/qcloud/shell/instance.go @@ -37,7 +37,7 @@ func init() { return nil }) - type InstanceCrateOptions struct { + type InstanceCreateOptions struct { NAME string `help:"name of instance"` IMAGE string `help:"image ID"` CPU int `help:"CPU count"` @@ -49,7 +49,7 @@ func init() { PublicKey string `help:"PublicKey"` } - shellutils.R(&InstanceCrateOptions{}, "instance-create", "Create a instance", func(cli *qcloud.SRegion, args *InstanceCrateOptions) error { + shellutils.R(&InstanceCreateOptions{}, "instance-create", "Create a instance", func(cli *qcloud.SRegion, args *InstanceCreateOptions) error { instance, e := cli.CreateInstanceSimple(args.NAME, args.IMAGE, args.CPU, args.MEMORYGB, args.STORAGE, args.Disk, args.NETWORK, args.PASSWD, args.PublicKey) if e != nil { return e