yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/azure/host.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package azure 16 17 import ( 18 "fmt" 19 "strings" 20 "time" 21 22 "yunion.io/x/jsonutils" 23 "yunion.io/x/log" 24 "yunion.io/x/pkg/errors" 25 "yunion.io/x/pkg/util/osprofile" 26 "yunion.io/x/pkg/utils" 27 28 api "yunion.io/x/cloudmux/pkg/apis/compute" 29 "yunion.io/x/cloudmux/pkg/cloudprovider" 30 "yunion.io/x/cloudmux/pkg/multicloud" 31 "yunion.io/x/onecloud/pkg/util/seclib2" 32 ) 33 34 type SHost struct { 35 multicloud.SHostBase 36 zone *SZone 37 } 38 39 func (self *SHost) GetId() string { 40 return fmt.Sprintf("%s-%s", self.zone.region.client.cpcfg.Id, self.zone.GetId()) 41 } 42 43 func (self *SHost) GetName() string { 44 return fmt.Sprintf("%s/%s", self.zone.region.GetGlobalId(), self.zone.region.client.subscriptionId) 45 } 46 47 func (self *SHost) GetGlobalId() string { 48 return fmt.Sprintf("%s/%s", self.zone.region.GetGlobalId(), self.zone.region.client.subscriptionId) 49 } 50 51 func (self *SHost) IsEmulated() bool { 52 return true 53 } 54 55 func (self *SHost) GetStatus() string { 56 return api.HOST_STATUS_RUNNING 57 } 58 59 func (self *SHost) Refresh() error { 60 return nil 61 } 62 63 func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) { 64 nic, err := self.zone.region.CreateNetworkInterface(desc.ProjectId, fmt.Sprintf("%s-ipconfig", desc.NameEn), desc.IpAddr, desc.ExternalNetworkId, desc.ExternalSecgroupId) 65 if err != nil { 66 return nil, errors.Wrapf(err, "CreateNetworkInterface") 67 } 68 69 instance, err := self.zone.region._createVM(desc, nic.ID) 70 if err != nil { 71 self.zone.region.DeleteNetworkInterface(nic.ID) 72 return nil, err 73 } 74 instance.host = self 75 return instance, nil 76 } 77 78 func (self *SRegion) _createVM(desc *cloudprovider.SManagedVMCreateConfig, nicId string) (*SInstance, error) { 79 image, err := self.GetImageById(desc.ExternalImageId) 80 if err != nil { 81 return nil, errors.Wrapf(err, "GetImageById(%s)", desc.ExternalImageId) 82 } 83 84 if len(desc.Password) == 0 { 85 //Azure创建必须要设置密码 86 desc.Password = seclib2.RandomPassword2(12) 87 } 88 89 if image.Properties.ProvisioningState != ImageStatusAvailable { 90 return nil, fmt.Errorf("image %s not ready status: %s", desc.ExternalImageId, image.Properties.ProvisioningState) 91 } 92 if !utils.IsInStringArray(desc.OsType, []string{osprofile.OS_TYPE_LINUX, osprofile.OS_TYPE_WINDOWS}) { 93 desc.OsType = string(image.GetOsType()) 94 } 95 computeName := desc.Hostname 96 for _, k := range "`~!@#$%^&*()=+_[]{}\\|;:.'\",<>/?" { 97 computeName = strings.Replace(computeName, string(k), "", -1) 98 } 99 if len(computeName) > 15 { 100 computeName = computeName[:15] 101 } 102 osProfile := map[string]string{ 103 "ComputerName": computeName, 104 "AdminUsername": api.VM_AZURE_DEFAULT_LOGIN_USER, 105 "AdminPassword": desc.Password, 106 } 107 if len(desc.UserData) > 0 { 108 osProfile["CustomData"] = desc.UserData 109 } 110 params := jsonutils.Marshal(map[string]interface{}{ 111 "Name": desc.NameEn, 112 "Location": self.Name, 113 "Properties": map[string]interface{}{ 114 "HardwareProfile": map[string]string{ 115 "VMSize": "", 116 }, 117 "OsProfile": osProfile, 118 "NetworkProfile": map[string]interface{}{ 119 "NetworkInterfaces": []map[string]string{ 120 map[string]string{ 121 "Id": nicId, 122 }, 123 }, 124 }, 125 "StorageProfile": map[string]interface{}{ 126 "ImageReference": image.getImageReference(), 127 "OsDisk": map[string]interface{}{ 128 "Name": fmt.Sprintf("vdisk_%s_%d", desc.Name, time.Now().UnixNano()), 129 "Caching": "ReadWrite", 130 "ManagedDisk": map[string]string{ 131 "StorageAccountType": desc.SysDisk.StorageType, 132 }, 133 "CreateOption": "FromImage", 134 "DiskSizeGB": desc.SysDisk.SizeGB, 135 "OsType": desc.OsType, 136 }, 137 }, 138 }, 139 "Type": "Microsoft.Compute/virtualMachines", 140 }).(*jsonutils.JSONDict) 141 if len(desc.PublicKey) > 0 && desc.OsType == osprofile.OS_TYPE_LINUX { 142 linuxConfiguration := map[string]interface{}{ 143 "DisablePasswordAuthentication": false, 144 "SSH": map[string]interface{}{ 145 "PublicKeys": []map[string]string{ 146 map[string]string{ 147 "KeyData": desc.PublicKey, 148 "Path": fmt.Sprintf("/home/%s/.ssh/authorized_keys", api.VM_AZURE_DEFAULT_LOGIN_USER), 149 }, 150 }, 151 }, 152 } 153 params.Add(jsonutils.Marshal(linuxConfiguration), "Properties", "OsProfile", "LinuxConfiguration") 154 } 155 if len(desc.Tags) > 0 { 156 params.Add(jsonutils.Marshal(desc.Tags), "tags") 157 } 158 159 dataDisks := jsonutils.NewArray() 160 for i := 0; i < len(desc.DataDisks); i++ { 161 dataDisk := jsonutils.Marshal(map[string]interface{}{ 162 "Name": fmt.Sprintf("vdisk_%s_%d", desc.Name, time.Now().UnixNano()), 163 "DiskSizeGB": desc.DataDisks[i].SizeGB, 164 "CreateOption": "Empty", 165 "ManagedDisk": map[string]string{ 166 "StorageAccountType": desc.DataDisks[i].StorageType, 167 }, 168 "Lun": i, 169 }) 170 dataDisks.Add(dataDisk) 171 } 172 if dataDisks.Length() > 0 { 173 params.Add(dataDisks, "Properties", "StorageProfile", "DataDisks") 174 } 175 176 instance := &SInstance{} 177 if len(desc.InstanceType) > 0 { 178 params.Add(jsonutils.NewString(desc.InstanceType), "Properties", "HardwareProfile", "VMSize") 179 log.Debugf("Try HardwareProfile : %s", desc.InstanceType) 180 err = self.create(desc.ProjectId, params, instance) 181 if err != nil { 182 return nil, errors.Wrapf(err, "create") 183 } 184 return instance, nil 185 } 186 187 for _, profile := range self.getHardwareProfile(desc.Cpu, desc.MemoryMB) { 188 params.Add(jsonutils.NewString(profile), "Properties", "HardwareProfile", "VMSize") 189 log.Debugf("Try HardwareProfile : %s", profile) 190 err = self.create(desc.ProjectId, params, &instance) 191 if err != nil { 192 for _, key := range []string{`"code":"InvalidParameter"`, `"code":"NicInUse"`} { 193 if strings.Contains(err.Error(), key) { 194 return nil, err 195 } 196 } 197 log.Errorf("Failed for %s: %s", profile, err) 198 continue 199 } 200 return instance, nil 201 } 202 if err != nil { 203 return nil, err 204 } 205 return nil, fmt.Errorf("instance type %dC%dMB not avaiable", desc.Cpu, desc.MemoryMB) 206 } 207 208 func (self *SHost) GetAccessIp() string { 209 return "" 210 } 211 212 func (self *SHost) GetAccessMac() string { 213 return "" 214 } 215 216 func (self *SHost) GetCpuCount() int { 217 return 0 218 } 219 220 func (self *SHost) GetCpuDesc() string { 221 return "" 222 } 223 224 func (self *SHost) GetCpuMhz() int { 225 return 0 226 } 227 228 func (self *SHost) GetMemSizeMB() int { 229 return 0 230 } 231 func (self *SHost) GetEnabled() bool { 232 return true 233 } 234 235 func (self *SHost) GetHostStatus() string { 236 return api.HOST_ONLINE 237 } 238 func (self *SHost) GetNodeCount() int8 { 239 return 0 240 } 241 242 func (self *SHost) GetHostType() string { 243 return api.HOST_TYPE_AZURE 244 } 245 246 func (self *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { 247 return self.zone.GetIStorageById(id) 248 } 249 250 func (self *SHost) GetSysInfo() jsonutils.JSONObject { 251 info := jsonutils.NewDict() 252 info.Add(jsonutils.NewString(CLOUD_PROVIDER_AZURE), "manufacture") 253 return info 254 } 255 256 func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) { 257 return self.zone.getIStorages(), nil 258 } 259 260 func (self *SHost) GetIVMById(instanceId string) (cloudprovider.ICloudVM, error) { 261 instance, err := self.zone.region.GetInstance(instanceId) 262 if err != nil { 263 return nil, err 264 } 265 instance.host = self 266 return instance, nil 267 } 268 269 func (self *SHost) GetStorageSizeMB() int { 270 return 0 271 } 272 273 func (self *SHost) GetStorageType() string { 274 return api.DISK_TYPE_HYBRID 275 } 276 277 func (self *SHost) GetSN() string { 278 return "" 279 } 280 281 func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) { 282 vms, err := self.zone.region.GetInstances() 283 if err != nil { 284 return nil, err 285 } 286 ivms := make([]cloudprovider.ICloudVM, len(vms)) 287 for i := 0; i < len(vms); i++ { 288 vms[i].host = self 289 ivms[i] = &vms[i] 290 log.Debugf("find vm %s for host %s", vms[i].GetName(), self.GetName()) 291 } 292 return ivms, nil 293 } 294 295 func (self *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) { 296 return self.zone.GetIWires() 297 } 298 299 func (host *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) { 300 return nil, cloudprovider.ErrNotSupported 301 } 302 303 func (host *SHost) GetIsMaintenance() bool { 304 return false 305 } 306 307 func (host *SHost) GetVersion() string { 308 return AZURE_API_VERSION 309 }