Skip to content

Commit 6777bbc

Browse files
committed
feat: add usb 3.0 support
Introduces a `usb3` option for enabling USB 3.0 controllers and enforces validation to prevent simultaneous enabling of USB 2.0 and USB 3.0. Signed-off-by: Ryan Johnson <rya@tenthirtyam.org>
1 parent 46d75b7 commit 6777bbc

7 files changed

Lines changed: 339 additions & 6 deletions

File tree

.web-docs/components/builder/iso/README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,14 @@ JSON Example:
137137
- `usb` (bool) - Enable USB 2.0 controllers for the virtual machine.
138138
Defaults to `false`.
139139

140-
~> **Note:** To enable USB 3.0 controllers, set a `usb_xhci.present`
141-
key to `true` in the `vmx_data` option.
140+
~> **Note:** USB 2.0 and USB 3.0 controllers cannot be enabled
141+
simultaneously. Use either `usb` or `usb3`, but not both.
142+
143+
- `usb3` (bool) - Enable USB 3.0 controllers for the virtual machine.
144+
Defaults to `false`.
145+
146+
~> **Note:** USB 3.0 and USB 2.0 controllers cannot be enabled
147+
simultaneously. Use either `usb3` or `usb`, but not both.
142148

143149
- `serial` (string) - Add a serial port to the virtual machine. Use a format of
144150
`Type:option1,option2,...`. Allowed values for the field `Type` include:

builder/vmware/common/hw_config.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,15 @@ type HWConfig struct {
4848
// Enable USB 2.0 controllers for the virtual machine.
4949
// Defaults to `false`.
5050
//
51-
// ~> **Note:** To enable USB 3.0 controllers, set a `usb_xhci.present`
52-
// key to `true` in the `vmx_data` option.
51+
// ~> **Note:** USB 2.0 and USB 3.0 controllers cannot be enabled
52+
// simultaneously. Use either `usb` or `usb3`, but not both.
5353
USB bool `mapstructure:"usb" required:"false"`
54+
// Enable USB 3.0 controllers for the virtual machine.
55+
// Defaults to `false`.
56+
//
57+
// ~> **Note:** USB 3.0 and USB 2.0 controllers cannot be enabled
58+
// simultaneously. Use either `usb3` or `usb`, but not both.
59+
USB3 bool `mapstructure:"usb3" required:"false"`
5460
// Add a serial port to the virtual machine. Use a format of
5561
// `Type:option1,option2,...`. Allowed values for the field `Type` include:
5662
// `FILE`, `DEVICE`, `PIPE`, `AUTO`, or `NONE`.
@@ -147,6 +153,15 @@ func (c *HWConfig) Prepare(ctx *interpolate.Context) []error {
147153
c.USB = false
148154
}
149155

156+
if !c.USB3 {
157+
c.USB3 = false
158+
}
159+
160+
// Validate USB configuration - prevent simultaneous USB 2.0 and USB 3.0
161+
if c.USB && c.USB3 {
162+
errs = append(errs, fmt.Errorf("USB 2.0 and USB 3.0 controllers cannot be enabled simultaneously; use either 'usb' or 'usb3', but not both"))
163+
}
164+
150165
if c.Parallel == "" {
151166
c.Parallel = "none"
152167
}

builder/vmware/common/hw_config_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ func TestHWConfigPrepare(t *testing.T) {
3939
t.Errorf("peripheral choice (usb) should be conservative: %t", c.USB)
4040
}
4141

42+
if c.USB3 {
43+
t.Errorf("peripheral choice (usb3) should be conservative: %t", c.USB3)
44+
}
45+
4246
if strings.ToUpper(c.Parallel) != "NONE" {
4347
t.Errorf("parallel port should not be defined: %s", c.Parallel)
4448
}
@@ -327,3 +331,81 @@ func TestHWConfigSerial_None(t *testing.T) {
327331
t.Errorf("serial port shouldn't exist")
328332
}
329333
}
334+
335+
func TestHWConfigUSBValidation_USB3Only(t *testing.T) {
336+
c := new(HWConfig)
337+
c.NetworkAdapterType = "vmxnet3"
338+
c.USB3 = true
339+
340+
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
341+
t.Fatalf("err: %#v", errs)
342+
}
343+
344+
if !c.USB3 {
345+
t.Errorf("USB 3.0 should be enabled: %t", c.USB3)
346+
}
347+
348+
if c.USB {
349+
t.Errorf("USB 2.0 should remain disabled: %t", c.USB)
350+
}
351+
}
352+
353+
func TestHWConfigUSBValidation_USB2Only(t *testing.T) {
354+
c := new(HWConfig)
355+
c.NetworkAdapterType = "vmxnet3"
356+
c.USB = true
357+
358+
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
359+
t.Fatalf("err: %#v", errs)
360+
}
361+
362+
if !c.USB {
363+
t.Errorf("USB 2.0 should be enabled: %t", c.USB)
364+
}
365+
366+
if c.USB3 {
367+
t.Errorf("USB 3.0 should remain disabled: %t", c.USB3)
368+
}
369+
}
370+
371+
func TestHWConfigUSBValidation_BothDisabled(t *testing.T) {
372+
c := new(HWConfig)
373+
c.NetworkAdapterType = "vmxnet3"
374+
375+
if errs := c.Prepare(interpolate.NewContext()); len(errs) > 0 {
376+
t.Fatalf("err: %#v", errs)
377+
}
378+
379+
if c.USB {
380+
t.Errorf("USB 2.0 should be disabled by default: %t", c.USB)
381+
}
382+
383+
if c.USB3 {
384+
t.Errorf("USB 3.0 should be disabled by default: %t", c.USB3)
385+
}
386+
}
387+
388+
func TestHWConfigUSBValidation_BothEnabled_ShouldError(t *testing.T) {
389+
c := new(HWConfig)
390+
c.NetworkAdapterType = "vmxnet3"
391+
c.USB = true
392+
c.USB3 = true
393+
394+
errs := c.Prepare(interpolate.NewContext())
395+
if len(errs) == 0 {
396+
t.Fatal("expected validation error when both USB 2.0 and USB 3.0 are enabled")
397+
}
398+
399+
expectedError := "USB 2.0 and USB 3.0 controllers cannot be enabled simultaneously; use either 'usb' or 'usb3', but not both"
400+
found := false
401+
for _, err := range errs {
402+
if err.Error() == expectedError {
403+
found = true
404+
break
405+
}
406+
}
407+
408+
if !found {
409+
t.Errorf("expected error message not found. Got errors: %v", errs)
410+
}
411+
}

builder/vmware/iso/config.hcl2spec.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

builder/vmware/iso/step_create_vmx.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type vmxTemplateData struct {
4040

4141
SoundPresent string
4242
UsbPresent string
43+
Usb3Present string
4344

4445
SerialPresent string
4546
SerialType string
@@ -175,6 +176,7 @@ func (s *stepCreateVMX) Run(ctx context.Context, state multistep.StateBag) multi
175176

176177
SoundPresent: map[bool]string{true: "TRUE", false: "FALSE"}[config.Sound],
177178
UsbPresent: map[bool]string{true: "TRUE", false: "FALSE"}[config.USB],
179+
Usb3Present: map[bool]string{true: "TRUE", false: "FALSE"}[config.USB3],
178180

179181
SerialPresent: "FALSE",
180182
ParallelPresent: "FALSE",
@@ -509,6 +511,10 @@ sound.autodetect = "TRUE"
509511
usb.pciSlotNumber = "32"
510512
usb.present = "{{ .UsbPresent }}"
511513
514+
// USB 3.0
515+
usb_xhci.present = "{{ .Usb3Present }}"
516+
usb_xhci.pciSlotNumber = "-1"
517+
512518
// Serial
513519
serial0.present = "{{ .SerialPresent }}"
514520
serial0.startConnected = "{{ .SerialPresent }}"

0 commit comments

Comments
 (0)