yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/proxmox/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 proxmox 16 17 import ( 18 "fmt" 19 "net/url" 20 "strconv" 21 "strings" 22 23 "yunion.io/x/jsonutils" 24 "yunion.io/x/pkg/errors" 25 26 api "yunion.io/x/cloudmux/pkg/apis/compute" 27 "yunion.io/x/cloudmux/pkg/cloudprovider" 28 "yunion.io/x/cloudmux/pkg/multicloud" 29 ) 30 31 type SHost struct { 32 multicloud.SHostBase 33 ProxmoxTags 34 zone *SZone 35 36 Id string 37 Node string 38 39 Uptime int `json:"uptime"` 40 Wait int `json:"wait"` 41 Idle int `json:"idle"` 42 Kversion string `json:"kversion"` 43 Pveversion string `json:"pveversion"` 44 CPU int `json:"cpu"` 45 Loadavg []string `json:"loadavg"` 46 Rootfs Rootfs `json:"rootfs"` 47 Swap Swap `json:"swap"` 48 Memory Memory `json:"memory"` 49 Cpuinfo Cpuinfo `json:"cpuinfo"` 50 Ksm Ksm `json:"ksm"` 51 } 52 53 type Rootfs struct { 54 Used int64 `json:"used"` 55 Total int64 `json:"total"` 56 Avail int64 `json:"avail"` 57 Free int64 `json:"free"` 58 } 59 60 type Swap struct { 61 Free int64 `json:"free"` 62 Used int64 `json:"used"` 63 Total int64 `json:"total"` 64 } 65 66 type Memory struct { 67 Free int64 `json:"free"` 68 Used int64 `json:"used"` 69 Total int64 `json:"total"` 70 } 71 72 type Cpuinfo struct { 73 Flags string `json:"flags"` 74 Hvm string `json:"hvm"` 75 Cores int `json:"cores"` 76 Model string `json:"model"` 77 Mhz float64 `json:"mhz"` 78 Cpus int `json:"cpus"` 79 UserHz int `json:"user_hz"` 80 Sockets int `json:"sockets"` 81 } 82 83 type Ksm struct { 84 Shared int `json:"shared"` 85 } 86 87 func (self *SHost) GetId() string { 88 return self.Id 89 } 90 91 func (self *SHost) GetGlobalId() string { 92 return self.Id 93 } 94 95 func (self *SHost) GetName() string { 96 return self.Node 97 } 98 99 func (self *SHost) GetEnabled() bool { 100 return true 101 } 102 103 func (self *SHost) GetHostStatus() string { 104 return api.HOST_ONLINE 105 } 106 107 func (self *SHost) GetStatus() string { 108 return api.HOST_STATUS_RUNNING 109 } 110 111 func (self *SHost) GetAccessIp() string { 112 return "" 113 } 114 115 func (self *SHost) GetAccessMac() string { 116 return "" 117 } 118 119 func (self *SHost) GetSysInfo() jsonutils.JSONObject { 120 return jsonutils.NewDict() 121 } 122 123 func (self *SHost) GetSN() string { 124 return "" 125 } 126 127 func (self *SHost) GetCpuCount() int { 128 return int(self.Cpuinfo.Cores) 129 } 130 131 func (self *SHost) GetNodeCount() int8 { 132 return int8(self.Cpuinfo.Sockets) 133 } 134 135 func (self *SHost) GetCpuDesc() string { 136 return self.Cpuinfo.Model 137 } 138 139 func (self *SHost) GetCpuMhz() int { 140 return int(self.Cpuinfo.Mhz) 141 } 142 143 func (self *SHost) GetCpuCmtbound() float32 { 144 return 1 145 } 146 147 func (self *SHost) GetMemSizeMB() int { 148 return int(self.Memory.Total / 1024 / 1024) 149 } 150 151 func (self *SHost) GetMemCmtbound() float32 { 152 return 1 153 } 154 155 func (self *SHost) GetReservedMemoryMb() int { 156 return 0 157 } 158 159 func (self *SHost) GetStorageSizeMB() int { 160 return int(self.Rootfs.Total / 1024 / 1024) 161 } 162 163 func (self *SHost) GetStorageType() string { 164 return api.STORAGE_LOCAL 165 } 166 167 func (self *SHost) GetHostType() string { 168 return api.HOST_TYPE_PROXMOX 169 } 170 171 func (self *SHost) GetIsMaintenance() bool { 172 return false 173 } 174 175 func (self *SHost) GetVersion() string { 176 return self.Pveversion 177 } 178 179 func (self *SHost) CreateVM(opts *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) { 180 181 vmId := self.zone.region.GetClusterVmMaxId() 182 if vmId == -1 { 183 return nil, errors.Errorf("failed to get vm number by %d", vmId) 184 } else { 185 vmId++ 186 } 187 188 splited := strings.Split(opts.SysDisk.StorageExternalId, "/") 189 storage := splited[2] 190 191 body := map[string]interface{}{ 192 "vmid": vmId, 193 "name": opts.Name, 194 "ostype": "other", 195 "sockets": 1, 196 "cores": opts.Cpu, 197 "cpu": "host", 198 "kvm": 1, 199 "hotplug": "network,disk,usb", 200 "memory": opts.MemoryMB, 201 "description": opts.OsDistribution, 202 "scsihw": "virtio-scsi-pci", 203 "scsi0": fmt.Sprintf("%s:%d", storage, opts.SysDisk.SizeGB), 204 } 205 206 res := fmt.Sprintf("/nodes/%s/qemu", self.Node) 207 _, err := self.zone.region.post(res, jsonutils.Marshal(body)) 208 if err != nil { 209 return nil, err 210 } 211 212 vmIdRet := strconv.Itoa(vmId) 213 vm, err := self.zone.region.GetInstance(vmIdRet) 214 if err != nil { 215 return nil, err 216 } 217 218 for k, _ := range vm.QemuDisks { 219 _, diskName := ParseSubConf(k, ":") 220 opts.SysDisk.Name = diskName.(string) 221 break 222 } 223 224 vm.host = self 225 return vm, nil 226 } 227 228 func (self *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) { 229 return nil, cloudprovider.ErrNotImplemented 230 } 231 232 func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) { 233 vms, err := self.zone.region.GetInstances(self.Id) 234 if err != nil { 235 return nil, errors.Wrapf(err, "GetInstances") 236 } 237 ret := []cloudprovider.ICloudVM{} 238 for i := range vms { 239 vms[i].host = self 240 ret = append(ret, &vms[i]) 241 } 242 return ret, nil 243 } 244 245 func (self *SHost) GetIVMById(id string) (cloudprovider.ICloudVM, error) { 246 vm, err := self.zone.region.GetInstance(id) 247 if err != nil { 248 return nil, err 249 } 250 hostId := fmt.Sprintf("node/%s", vm.Node) 251 if hostId != self.Id { 252 return nil, cloudprovider.ErrNotFound 253 } 254 vm.host = self 255 return vm, nil 256 } 257 258 func (self *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) { 259 wires, err := self.zone.region.GetWires() 260 if err != nil { 261 return nil, err 262 } 263 ret := []cloudprovider.ICloudWire{} 264 for i := range wires { 265 wires[i].region = self.zone.region 266 ret = append(ret, &wires[i]) 267 } 268 return ret, nil 269 } 270 271 func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) { 272 storages, err := self.zone.region.GetStoragesByHost(self.Id) 273 if err != nil { 274 return nil, err 275 } 276 ret := []cloudprovider.ICloudStorage{} 277 for i := range storages { 278 storages[i].zone = self.zone 279 ret = append(ret, &storages[i]) 280 } 281 return ret, nil 282 } 283 284 func (self *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { 285 storage, err := self.zone.region.GetStorage(id) 286 if err != nil { 287 return nil, err 288 } 289 storage.zone = self.zone 290 291 return storage, nil 292 } 293 294 func (self *SRegion) GetHosts() ([]SHost, error) { 295 hosts := []SHost{} 296 resources, err := self.GetClusterNodeResources() 297 if err != nil { 298 return nil, err 299 } 300 301 for _, res := range resources { 302 host := &SHost{} 303 status := fmt.Sprintf("nodes/%s/status", res.Node) 304 err := self.get(status, url.Values{}, host) 305 if err != nil { 306 return nil, err 307 } 308 host.Id = res.Id 309 host.Node = res.Node 310 hosts = append(hosts, *host) 311 } 312 313 return hosts, nil 314 } 315 316 func (self *SRegion) GetHost(id string) (*SHost, error) { 317 ret := &SHost{} 318 nodeName := "" 319 320 //"id": "node/nodeNAME", 321 splited := strings.Split(id, "/") 322 if len(splited) == 2 { 323 nodeName = splited[1] 324 } 325 326 res := fmt.Sprintf("nodes/%s/status", nodeName) 327 err := self.get(res, url.Values{}, ret) 328 if err != nil { 329 return nil, err 330 } 331 ret.Id = id 332 ret.Node = nodeName 333 334 return ret, nil 335 }