Merge pull request #577 from ioito/hotfix/qx-azure-rebuild-root

Azure重装系统支持初始化密码
This commit is contained in:
yunion-ci-robot
2019-04-24 22:13:12 +08:00
committed by GitHub
15 changed files with 257 additions and 139 deletions
+2 -1
View File
@@ -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"
+1 -2
View File
@@ -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) {
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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()
}
-4
View File
@@ -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) {
+18 -1
View File
@@ -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
+18 -1
View File
@@ -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 {
+47 -28
View File
@@ -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 {
+117 -68
View File
@@ -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
+4
View File
@@ -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)
}
+4 -3
View File
@@ -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"
}
+13 -6
View File
@@ -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)
+26 -18
View File
@@ -74,19 +74,21 @@ func init() {
return nil
})
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"`
type InstanceCreateOptions struct {
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)
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
}
@@ -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 {
+2 -2
View File
@@ -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