yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/esxi/devtools.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 esxi 16 17 import ( 18 "fmt" 19 "reflect" 20 21 "github.com/vmware/govmomi/vim25/types" 22 23 "yunion.io/x/log" 24 "yunion.io/x/pkg/errors" 25 ) 26 27 type SDiskConfig struct { 28 SizeMb int64 29 Uuid string 30 ControllerKey int32 31 UnitNumber int32 32 Key int32 33 ImagePath string 34 IsRoot bool 35 Datastore *SDatastore 36 } 37 38 // In fact, it is the default lable of first one disk 39 const rootDiskMark = "Hard disk 1" 40 41 func NewDiskDev(sizeMb int64, config SDiskConfig) *types.VirtualDisk { 42 device := types.VirtualDisk{} 43 diskFile := types.VirtualDiskFlatVer2BackingInfo{} 44 diskFile.DiskMode = "persistent" 45 thinProvisioned := true 46 diskFile.ThinProvisioned = &thinProvisioned 47 diskFile.Uuid = config.Uuid 48 if len(config.ImagePath) > 0 { 49 diskFile.FileName = config.ImagePath 50 } 51 if config.Datastore != nil { 52 ref := config.Datastore.getDatastoreObj().Reference() 53 diskFile.Datastore = &ref 54 } 55 device.Backing = &diskFile 56 57 if sizeMb > 0 { 58 device.CapacityInKB = sizeMb * 1024 59 } 60 61 device.ControllerKey = config.ControllerKey 62 device.Key = config.Key 63 device.UnitNumber = &config.UnitNumber 64 65 var label string 66 if config.IsRoot { 67 label = rootDiskMark 68 device.DeviceInfo = &types.Description{Label: label} 69 } 70 71 return &device 72 } 73 74 func addDevSpec(device types.BaseVirtualDevice) *types.VirtualDeviceConfigSpec { 75 spec := types.VirtualDeviceConfigSpec{} 76 spec.Operation = types.VirtualDeviceConfigSpecOperationAdd 77 spec.Device = device 78 return &spec 79 } 80 81 func NewSCSIDev(key, ctlKey int32, driver string) types.BaseVirtualDevice { 82 desc := types.Description{Label: "SCSI controller 0", Summary: "VMware virtual SCSI"} 83 84 if driver == "pvscsi" { 85 device := types.ParaVirtualSCSIController{} 86 device.DeviceInfo = &desc 87 device.Key = key 88 device.ControllerKey = ctlKey 89 device.SharedBus = "noSharing" 90 return &device 91 } 92 device := types.VirtualLsiLogicController{} 93 device.DeviceInfo = &desc 94 device.Key = key 95 device.ControllerKey = ctlKey 96 device.SharedBus = "noSharing" 97 return &device 98 } 99 100 func NewAHCIDev(key, ctlKey int32) types.BaseVirtualDevice { 101 device := types.VirtualAHCIController{} 102 device.DeviceInfo = &types.Description{Label: "SATA controller 0", Summary: "AHCI"} 103 device.ControllerKey = ctlKey 104 device.Key = key 105 return &device 106 } 107 108 func NewSVGADev(key, ctlKey int32) types.BaseVirtualDevice { 109 device := types.VirtualMachineVideoCard{} 110 device.DeviceInfo = &types.Description{Label: "Video card", Summary: "Video card"} 111 device.ControllerKey = ctlKey 112 device.Key = key 113 device.VideoRamSizeInKB = 16 * 1024 114 return &device 115 } 116 117 func NewIDEDev(key, index int32) types.BaseVirtualDevice { 118 device := types.VirtualIDEController{} 119 s := fmt.Sprintf("IDE %d", index) 120 device.DeviceInfo = &types.Description{Label: s, Summary: s} 121 device.Key = key + index 122 device.BusNumber = index 123 return &device 124 } 125 126 func NewCDROMDev(path string, key, ctlKey int32) types.BaseVirtualDevice { 127 device := types.VirtualCdrom{} 128 device.DeviceInfo = &types.Description{Label: "CD/DVD drive 1", Summary: "Local ISO Emulated CD-ROM"} 129 device.ControllerKey = ctlKey 130 device.Key = key 131 132 connectable := types.VirtualDeviceConnectInfo{AllowGuestControl: true, Status: "untried"} 133 if len(path) != 0 { 134 device.Backing = &types.VirtualCdromIsoBackingInfo{ 135 VirtualDeviceFileBackingInfo: types.VirtualDeviceFileBackingInfo{ 136 FileName: path, 137 }, 138 } 139 connectable.StartConnected = true 140 } else { 141 device.Backing = &types.VirtualCdromRemoteAtapiBackingInfo{} 142 connectable.StartConnected = false 143 } 144 145 device.Connectable = &connectable 146 return &device 147 } 148 149 func NewUSBController(key *int32) types.BaseVirtualDevice { 150 device := types.VirtualUSBController{} 151 device.DeviceInfo = &types.Description{ 152 Label: "USB controller", 153 } 154 if key != nil { 155 device.Key = *key 156 } 157 return &device 158 } 159 160 var getNetwork func(bridge, vlanId string) (IVMNetwork, error) 161 162 func NewVNICDev(host *SHost, mac, driver string, bridge string, vlanId int32, key, ctlKey, index int32) (types.BaseVirtualDevice, error) { 163 desc := types.Description{Label: fmt.Sprintf("Network adapter %d", index+1), Summary: "VM Network"} 164 165 newGetNetwork := func(bridge string, vlanId int32) (IVMNetwork, error) { 166 if len(bridge) == 0 { 167 log.Warningf("empty bridge for host %s, vlanId %d, mac %s", host.GetGlobalId(), vlanId, mac) 168 return nil, nil 169 } 170 vs, err := findVirtualSwitch(host, bridge) 171 if err != nil { 172 return nil, errors.Wrapf(err, "findVirtualSwitch for host %s bridge %s", host.GetGlobalId(), bridge) 173 } 174 if vs == nil { 175 log.Infof("can't find vs via host %s, bridge %s", host.GetId(), bridge) 176 return nil, nil 177 } 178 network, err := vs.FindNetworkByVlanID(vlanId) 179 if err != nil { 180 return nil, errors.Wrapf(err, "FindNetworkByVlanID for vlanId %q", vlanId) 181 } 182 return network, nil 183 } 184 185 oldGetNework := func(bridge string, vlanId int32) (IVMNetwork, error) { 186 var inet IVMNetwork 187 var err error 188 if (vlanId == 0 || vlanId == 1) && len(bridge) > 0 { 189 inet, err = host.findDVPGById(bridge) 190 if err != nil { 191 log.Errorf("fail to find dvportgroup by name %s: %s", bridge, err) 192 } 193 } 194 if inet == nil || reflect.ValueOf(inet).IsNil() { 195 inet, err = host.FindNetworkByVlanID(vlanId) 196 if err != nil { 197 log.Errorf("fail to find network by vlanid %d: %s", vlanId, err) 198 } 199 } 200 if inet == nil || reflect.ValueOf(inet).IsNil() { 201 return nil, nil 202 } 203 return inet, nil 204 } 205 206 inet, err := newGetNetwork(bridge, vlanId) 207 if err != nil { 208 return nil, err 209 } 210 if inet == nil { 211 log.Infof("no find network via new method") 212 inet, err = oldGetNework(bridge, vlanId) 213 if err != nil { 214 return nil, err 215 } 216 } 217 218 if inet == nil { 219 return nil, errors.Error(fmt.Sprintf("Brige %s VLAN %d not found", bridge, vlanId)) 220 } 221 222 var ( 223 False = false 224 True = true 225 ) 226 var backing types.BaseVirtualDeviceBackingInfo 227 switch inet.(type) { 228 case *SDistributedVirtualPortgroup: 229 net := inet.(*SDistributedVirtualPortgroup) 230 dvpg := net.getMODVPortgroup() 231 uuid, err := net.GetDVSUuid() 232 if err != nil { 233 return nil, errors.Wrap(err, "GetDVSUuid") 234 } 235 portCon := types.DistributedVirtualSwitchPortConnection{ 236 PortgroupKey: dvpg.Key, 237 SwitchUuid: uuid, 238 } 239 backing = &types.VirtualEthernetCardDistributedVirtualPortBackingInfo{Port: portCon} 240 case *SNetwork: 241 monet := inet.(*SNetwork).getMONetwork() 242 backing = &types.VirtualEthernetCardNetworkBackingInfo{ 243 VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{ 244 DeviceName: monet.Name, 245 UseAutoDetect: &False, 246 }, 247 Network: &monet.Self, 248 } 249 default: 250 return nil, errors.Error(fmt.Sprintf("Unsuppport network type %s", reflect.TypeOf(inet).Name())) 251 } 252 253 connectable := types.VirtualDeviceConnectInfo{ 254 StartConnected: true, 255 AllowGuestControl: true, 256 Connected: false, 257 Status: "untried", 258 } 259 260 nic := types.VirtualEthernetCard{ 261 VirtualDevice: types.VirtualDevice{ 262 DeviceInfo: &desc, 263 Backing: backing, 264 }, 265 WakeOnLanEnabled: &True, 266 } 267 nic.Connectable = &connectable 268 nic.ControllerKey = ctlKey 269 nic.Key = key + index 270 if len(mac) != 0 { 271 nic.AddressType = "Manual" 272 nic.MacAddress = mac 273 } else { 274 nic.AddressType = "Generated" 275 } 276 if driver == "e1000" { 277 return &types.VirtualE1000{ 278 VirtualEthernetCard: nic, 279 }, nil 280 } 281 282 return &types.VirtualVmxnet3{ 283 VirtualVmxnet: types.VirtualVmxnet{ 284 VirtualEthernetCard: nic, 285 }, 286 }, nil 287 }