github.com/vmware/govmomi@v0.37.1/govc/device/pci/add.go (about) 1 /* 2 Copyright (c) 2020-2023 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package pci 18 19 import ( 20 "context" 21 "errors" 22 "flag" 23 "fmt" 24 25 "github.com/vmware/govmomi/govc/cli" 26 "github.com/vmware/govmomi/govc/flags" 27 "github.com/vmware/govmomi/vim25/types" 28 ) 29 30 type add struct { 31 *flags.VirtualMachineFlag 32 } 33 34 func init() { 35 cli.Register("device.pci.add", &add{}) 36 } 37 38 func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) { 39 cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx) 40 cmd.VirtualMachineFlag.Register(ctx, f) 41 } 42 43 func (cmd *add) Description() string { 44 return `Add PCI Passthrough device to VM. 45 46 Examples: 47 govc device.pci.ls -vm $vm 48 govc device.pci.add -vm $vm $pci_address 49 govc device.info -vm $vm 50 51 Assuming vm name is helloworld, list command has below output 52 53 $ govc device.pci.ls -vm helloworld 54 System ID Address Vendor Name Device Name 55 5b087ce4-ce46-72c0-c7c2-28ac9e22c3c2 0000:60:00.0 Pensando Ethernet Controller 1 56 5b087ce4-ce46-72c0-c7c2-28ac9e22c3c2 0000:61:00.0 Pensando Ethernet Controller 2 57 58 To add only 'Ethernet Controller 1', command should be as below. No output upon success. 59 60 $ govc device.pci.add -vm helloworld 0000:60:00.0 61 62 To add both 'Ethernet Controller 1' and 'Ethernet Controller 2', command should be as below. 63 No output upon success. 64 65 $ govc device.pci.add -vm helloworld 0000:60:00.0 0000:61:00.0 66 67 $ govc device.info -vm helloworld 68 ... 69 Name: pcipassthrough-13000 70 Type: VirtualPCIPassthrough 71 Label: PCI device 0 72 Summary: 73 Key: 13000 74 Controller: pci-100 75 Unit number: 18 76 Name: pcipassthrough-13001 77 Type: VirtualPCIPassthrough 78 Label: PCI device 1 79 Summary: 80 Key: 13001 81 Controller: pci-100 82 Unit number: 19` 83 } 84 85 func (cmd *add) Usage() string { 86 return "PCI_ADDRESS..." 87 } 88 89 func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error { 90 if len(f.Args()) == 0 { 91 return flag.ErrHelp 92 } 93 94 reqDevices := map[string]*types.VirtualMachinePciPassthroughInfo{} 95 for _, n := range f.Args() { 96 reqDevices[n] = nil 97 } 98 99 vm, err := cmd.VirtualMachine() 100 if err != nil { 101 return err 102 } 103 if vm == nil { 104 return flag.ErrHelp 105 } 106 107 vmConfigOptions, err := queryConfigTarget(ctx, vm) 108 if err != nil { 109 return err 110 } 111 112 for _, d := range vmConfigOptions.PciPassthrough { 113 info := d.GetVirtualMachinePciPassthroughInfo() 114 if info == nil { 115 return errors.New("received invalid pci passthrough info") 116 } 117 118 _, ok := reqDevices[info.PciDevice.Id] 119 if !ok { 120 continue 121 } 122 reqDevices[info.PciDevice.Id] = info 123 } 124 125 newDevices := []types.BaseVirtualDevice{} 126 for id, d := range reqDevices { 127 if d == nil { 128 return fmt.Errorf("%s is not found in allowed PCI passthrough device list", id) 129 } 130 device := &types.VirtualPCIPassthrough{} 131 device.Backing = &types.VirtualPCIPassthroughDeviceBackingInfo{ 132 Id: d.PciDevice.Id, DeviceId: fmt.Sprintf("%x", d.PciDevice.DeviceId), 133 SystemId: d.SystemId, VendorId: d.PciDevice.VendorId, 134 } 135 device.Connectable = &types.VirtualDeviceConnectInfo{StartConnected: true, Connected: true} 136 newDevices = append(newDevices, device) 137 } 138 139 return vm.AddDevice(ctx, newDevices...) 140 }