mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-12 23:38:30 +08:00
344 lines
9.4 KiB
Go
344 lines
9.4 KiB
Go
package azure
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"yunion.io/x/jsonutils"
|
|
"yunion.io/x/log"
|
|
|
|
"yunion.io/x/onecloud/pkg/cloudprovider"
|
|
"yunion.io/x/onecloud/pkg/compute/models"
|
|
"yunion.io/x/onecloud/pkg/util/ansible"
|
|
"yunion.io/x/onecloud/pkg/util/billing"
|
|
)
|
|
|
|
type SHost struct {
|
|
zone *SZone
|
|
}
|
|
|
|
func (self *SHost) GetMetadata() *jsonutils.JSONDict {
|
|
return nil
|
|
}
|
|
|
|
func (self *SHost) GetId() string {
|
|
return fmt.Sprintf("%s-%s", self.zone.region.client.providerId, self.zone.GetId())
|
|
}
|
|
|
|
func (self *SHost) GetName() string {
|
|
return fmt.Sprintf("%s/%s", self.zone.region.GetGlobalId(), self.zone.region.client.subscriptionId)
|
|
}
|
|
|
|
func (self *SHost) GetGlobalId() string {
|
|
return fmt.Sprintf("%s/%s", self.zone.region.GetGlobalId(), self.zone.region.SubscriptionID)
|
|
}
|
|
|
|
func (self *SHost) IsEmulated() bool {
|
|
return true
|
|
}
|
|
|
|
func (self *SHost) GetStatus() string {
|
|
return models.HOST_STATUS_RUNNING
|
|
}
|
|
|
|
func (self *SHost) Refresh() error {
|
|
return nil
|
|
}
|
|
|
|
func (self *SHost) searchNetorkInterface(IPAddr string, networkId string, secgroupId string) (*SInstanceNic, error) {
|
|
interfaces, err := self.zone.region.GetNetworkInterfaces()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for i, nic := range interfaces {
|
|
for _, ipConf := range nic.Properties.IPConfigurations {
|
|
if ipConf.Properties.PrivateIPAddress == IPAddr && networkId == ipConf.Properties.Subnet.ID && ipConf.Properties.PrivateIPAllocationMethod == "Static" {
|
|
if nic.Properties.NetworkSecurityGroup == nil || nic.Properties.NetworkSecurityGroup.ID != secgroupId {
|
|
nic.Properties.NetworkSecurityGroup = &SSecurityGroup{ID: secgroupId}
|
|
if err := self.zone.region.client.Update(jsonutils.Marshal(nic), nil); err != nil {
|
|
log.Errorf("assign secgroup %s for nic %s failed %d")
|
|
return nil, err
|
|
}
|
|
}
|
|
return &interfaces[i], nil
|
|
}
|
|
}
|
|
}
|
|
return nil, cloudprovider.ErrNotFound
|
|
}
|
|
|
|
func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int, memMB int,
|
|
networkId string, ipAddr string, desc string, passwd string, storageType string,
|
|
diskSizes []int, publicKey string, secgroupId string, userData string,
|
|
bc *billing.SBillingCycle) (cloudprovider.ICloudVM, error) {
|
|
net := self.zone.getNetworkById(networkId)
|
|
if net == nil {
|
|
return nil, fmt.Errorf("invalid network ID %s", networkId)
|
|
}
|
|
nic, err := self.searchNetorkInterface(ipAddr, net.GetId(), secgroupId)
|
|
if err != nil {
|
|
if err == cloudprovider.ErrNotFound {
|
|
nic, err = self.zone.region.CreateNetworkInterface(fmt.Sprintf("%s-ipconfig", name), ipAddr, net.GetId(), secgroupId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
return nil, err
|
|
}
|
|
}
|
|
vmId, err := self._createVM(name, imgId, int32(sysDiskSize), cpu, memMB, "", nic.ID, ipAddr, desc, passwd, storageType, diskSizes, publicKey, userData)
|
|
if err != nil {
|
|
self.zone.region.DeleteNetworkInterface(nic.ID)
|
|
return nil, err
|
|
}
|
|
if vm, err := self.zone.region.GetInstance(vmId); err != nil {
|
|
return nil, err
|
|
} else {
|
|
vm.host = self
|
|
return vm, err
|
|
}
|
|
}
|
|
|
|
func (self *SHost) CreateVM2(name string, imgId string, sysDiskSize int, instanceType string,
|
|
networkId string, ipAddr string, desc string, passwd string, storageType string,
|
|
diskSizes []int, publicKey string, secgroupId string, userData string, bc *billing.SBillingCycle) (cloudprovider.ICloudVM, error) {
|
|
net := self.zone.getNetworkById(networkId)
|
|
if net == nil {
|
|
return nil, fmt.Errorf("invalid network ID %s", networkId)
|
|
}
|
|
nic, err := self.searchNetorkInterface(ipAddr, net.GetId(), secgroupId)
|
|
if err != nil {
|
|
if err == cloudprovider.ErrNotFound {
|
|
nic, err = self.zone.region.CreateNetworkInterface(fmt.Sprintf("%s-ipconfig", name), ipAddr, net.GetId(), secgroupId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
return nil, err
|
|
}
|
|
}
|
|
vmId, err := self._createVM(name, imgId, int32(sysDiskSize), 0, 0, instanceType, nic.ID, ipAddr, desc, passwd, storageType, diskSizes, publicKey, userData)
|
|
if err != nil {
|
|
self.zone.region.DeleteNetworkInterface(nic.ID)
|
|
return nil, err
|
|
}
|
|
if vm, err := self.zone.region.GetInstance(vmId); err != nil {
|
|
return nil, err
|
|
} else {
|
|
vm.host = self
|
|
return vm, err
|
|
}
|
|
}
|
|
|
|
func (self *SHost) _createVM(name string, imgId string, sysDiskSize int32, cpu int, memMB int, instanceType string, nicId string, ipAddr string, desc string, passwd string, storageType string, diskSizes []int, publicKey string, userData string) (string, error) {
|
|
image, err := self.zone.region.GetImage(imgId)
|
|
if err != nil {
|
|
log.Errorf("Get Image %s fail %s", imgId, err)
|
|
return "", err
|
|
}
|
|
|
|
if image.Properties.ProvisioningState != ImageStatusAvailable {
|
|
log.Errorf("image %s status %s", imgId, image.Properties.ProvisioningState)
|
|
return "", fmt.Errorf("image not ready")
|
|
}
|
|
storage, err := self.zone.getStorageByType(storageType)
|
|
if err != nil {
|
|
return "", fmt.Errorf("Storage %s not avaiable: %s", storageType, err)
|
|
}
|
|
|
|
instance := SInstance{
|
|
Name: 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,
|
|
},
|
|
NetworkProfile: NetworkProfile{
|
|
NetworkInterfaces: []NetworkInterfaceReference{
|
|
{
|
|
ID: nicId,
|
|
},
|
|
},
|
|
},
|
|
StorageProfile: StorageProfile{
|
|
ImageReference: ImageReference{
|
|
ID: image.ID,
|
|
},
|
|
OsDisk: OSDisk{
|
|
Name: fmt.Sprintf("vdisk_%s_%d", name, time.Now().UnixNano()),
|
|
Caching: "ReadWrite",
|
|
ManagedDisk: &ManagedDiskParameters{
|
|
StorageAccountType: storage.Name,
|
|
},
|
|
CreateOption: "FromImage",
|
|
DiskSizeGB: &sysDiskSize,
|
|
OsType: image.GetOsType(),
|
|
},
|
|
},
|
|
},
|
|
Type: "Microsoft.Compute/virtualMachines",
|
|
}
|
|
if len(publicKey) > 0 {
|
|
instance.Properties.OsProfile.LinuxConfiguration = &LinuxConfiguration{
|
|
DisablePasswordAuthentication: false,
|
|
SSH: &SSHConfiguration{
|
|
PublicKeys: []SSHPublicKey{
|
|
{KeyData: publicKey},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
dataDisks := []DataDisk{}
|
|
for i := 0; i < len(diskSizes); i++ {
|
|
diskName := fmt.Sprintf("vdisk_%s_%d", name, time.Now().UnixNano())
|
|
size := int32(diskSizes[i])
|
|
lun := int32(i)
|
|
dataDisks = append(dataDisks, DataDisk{
|
|
Name: diskName,
|
|
DiskSizeGB: &size,
|
|
CreateOption: "Empty",
|
|
Lun: lun,
|
|
})
|
|
}
|
|
if len(dataDisks) > 0 {
|
|
instance.Properties.StorageProfile.DataDisks = dataDisks
|
|
}
|
|
|
|
if len(instanceType) > 0 {
|
|
instance.Properties.HardwareProfile.VMSize = instanceType
|
|
log.Debugf("Try HardwareProfile : %s", 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 not supported", instanceType)
|
|
}
|
|
return instance.ID, nil
|
|
}
|
|
|
|
for _, profile := range self.zone.region.getHardwareProfile(cpu, memMB) {
|
|
instance.Properties.HardwareProfile.VMSize = profile
|
|
log.Debugf("Try HardwareProfile : %s", profile)
|
|
err := self.zone.region.client.Create(jsonutils.Marshal(instance), &instance)
|
|
if err != nil {
|
|
log.Errorf("Failed for %s: %s", profile, err)
|
|
continue
|
|
}
|
|
return instance.ID, nil
|
|
}
|
|
return "", fmt.Errorf("Failed to create, specification not supported")
|
|
}
|
|
|
|
func (self *SHost) GetAccessIp() string {
|
|
return ""
|
|
}
|
|
|
|
func (self *SHost) GetAccessMac() string {
|
|
return ""
|
|
}
|
|
|
|
func (self *SHost) GetCpuCount() int8 {
|
|
return 0
|
|
}
|
|
|
|
func (self *SHost) GetCpuDesc() string {
|
|
return ""
|
|
}
|
|
|
|
func (self *SHost) GetCpuMhz() int {
|
|
return 0
|
|
}
|
|
|
|
func (self *SHost) GetMemSizeMB() int {
|
|
return 0
|
|
}
|
|
func (self *SHost) GetEnabled() bool {
|
|
return true
|
|
}
|
|
|
|
func (self *SHost) GetHostStatus() string {
|
|
return models.HOST_ONLINE
|
|
}
|
|
func (self *SHost) GetNodeCount() int8 {
|
|
return 0
|
|
}
|
|
|
|
func (self *SHost) GetHostType() string {
|
|
return models.HOST_TYPE_AZURE
|
|
}
|
|
|
|
func (self *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
|
return self.zone.GetIStorageById(id)
|
|
}
|
|
|
|
func (self *SHost) GetSysInfo() jsonutils.JSONObject {
|
|
info := jsonutils.NewDict()
|
|
info.Add(jsonutils.NewString(CLOUD_PROVIDER_AZURE), "manufacture")
|
|
return info
|
|
}
|
|
|
|
func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
|
return self.zone.istorages, nil
|
|
}
|
|
|
|
func (self *SHost) GetIVMById(instanceId string) (cloudprovider.ICloudVM, error) {
|
|
instance, err := self.zone.region.GetInstance(instanceId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
instance.host = self
|
|
return instance, nil
|
|
}
|
|
|
|
func (self *SHost) GetStorageSizeMB() int {
|
|
return 0
|
|
}
|
|
|
|
func (self *SHost) GetStorageType() string {
|
|
return models.DISK_TYPE_HYBRID
|
|
}
|
|
|
|
func (self *SHost) GetSN() string {
|
|
return ""
|
|
}
|
|
|
|
func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
|
|
vms, err := self.zone.region.GetInstances()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ivms := make([]cloudprovider.ICloudVM, len(vms))
|
|
for i := 0; i < len(vms); i++ {
|
|
vms[i].host = self
|
|
ivms[i] = &vms[i]
|
|
log.Debugf("find vm %s for host %s", vms[i].GetName(), self.GetName())
|
|
}
|
|
return ivms, nil
|
|
}
|
|
|
|
func (self *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) {
|
|
return self.zone.GetIWires()
|
|
}
|
|
|
|
func (self *SHost) GetManagerId() string {
|
|
return self.zone.region.client.providerId
|
|
}
|
|
|
|
func (host *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) {
|
|
return nil, cloudprovider.ErrNotSupported
|
|
}
|
|
|
|
func (host *SHost) GetIsMaintenance() bool {
|
|
return false
|
|
}
|
|
|
|
func (host *SHost) GetVersion() string {
|
|
return AZURE_API_VERSION
|
|
}
|