Skip to content

Commit 1280b76

Browse files
committed
feat: expand switch / adapter configuration.
Signed-off-by: Greg Althaus <[email protected]>
1 parent 90f3b30 commit 1280b76

32 files changed

+801
-627
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
main
22
dist/*
33
packer-plugin-scaffolding
4+
packer-plugin-hyperv
45
.docs

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,10 @@ created, must be empty prior to running the builder. By default this is
258258
try and determine the switch to use by looking for an external switch
259259
that is up and running.
260260

261-
- `switches_names` ([]string) - The name of the switches to connect the virtual
261+
- `switch_type` (string) - The type of the main switch to connect the virtual
262262
machine to. By default, leaving this value unset will cause Packer to
263-
not use any additional switches.
263+
try and determine the switch to use by looking for an external switch
264+
that is up and running.
264265

265266
- `switch_vlan_id` (string) - This is the VLAN of the virtual switch's
266267
network card. By default, none is set. If none is set then a VLAN is not
@@ -271,14 +272,16 @@ created, must be empty prior to running the builder. By default this is
271272
the default main virtual network card. The MAC address must be a string with
272273
no delimiters, for example "0000deadbeef".
273274

274-
- `mac_addresses` ([]string) - This allows a specific MAC addresses to be used on
275-
the optional virtual network cards set in `switches_names` array. The MAC addresses must be strings with
276-
no delimiters, for example "0000deadbeef".
277-
278275
- `vlan_id` (string) - This is the VLAN of the virtual machine's network
279276
card for the new virtual machine. By default none is set. If none is set
280277
then VLANs are not set on the virtual machine's network card.
281278

279+
- `switch_config` ([]SwitchConfig) - This allows for multiple switches to be configured.
280+
This should be used exclusively with SwitchName, SwitchVlanId, and MacAddress.
281+
282+
- `adapter_config` ([]AdapterConfig) - This allows for multiple switches to be configured.
283+
This should be used exclusively with MacAddress and VlanId.
284+
282285
- `cpus` (uint) - The number of CPUs the virtual machine should use. If
283286
this isn't specified, the default is 1 CPU.
284287

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,10 @@ In HCL2:
285285
try and determine the switch to use by looking for an external switch
286286
that is up and running.
287287

288-
- `switches_names` ([]string) - The name of the switches to connect the virtual
288+
- `switch_type` (string) - The type of the main switch to connect the virtual
289289
machine to. By default, leaving this value unset will cause Packer to
290-
not use any additional switches.
290+
try and determine the switch to use by looking for an external switch
291+
that is up and running.
291292

292293
- `switch_vlan_id` (string) - This is the VLAN of the virtual switch's
293294
network card. By default, none is set. If none is set then a VLAN is not
@@ -298,14 +299,16 @@ In HCL2:
298299
the default main virtual network card. The MAC address must be a string with
299300
no delimiters, for example "0000deadbeef".
300301

301-
- `mac_addresses` ([]string) - This allows a specific MAC addresses to be used on
302-
the optional virtual network cards set in `switches_names` array. The MAC addresses must be strings with
303-
no delimiters, for example "0000deadbeef".
304-
305302
- `vlan_id` (string) - This is the VLAN of the virtual machine's network
306303
card for the new virtual machine. By default none is set. If none is set
307304
then VLANs are not set on the virtual machine's network card.
308305

306+
- `switch_config` ([]SwitchConfig) - This allows for multiple switches to be configured.
307+
This should be used exclusively with SwitchName, SwitchVlanId, and MacAddress.
308+
309+
- `adapter_config` ([]AdapterConfig) - This allows for multiple switches to be configured.
310+
This should be used exclusively with MacAddress and VlanId.
311+
309312
- `cpus` (uint) - The number of CPUs the virtual machine should use. If
310313
this isn't specified, the default is 1 CPU.
311314

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
//go:generate packer-sdc struct-markdown
5+
//go:generate packer-sdc mapstructure-to-hcl2 -type AdapterConfig
6+
7+
package common
8+
9+
import (
10+
"github.com/hashicorp/packer-plugin-sdk/common"
11+
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
12+
)
13+
14+
type AdapterConfig struct {
15+
// The name of the network adapter.
16+
// By default, leaving this value unset will cause Packer to
17+
// try and determine the switch to use by looking for an external switch
18+
// that is up and running.
19+
Name string `mapstructure:"adapter_name" required:"false"`
20+
// The name of the switch for this adapter
21+
SwitchName string `mapstructure:"switch_name" required:"false"`
22+
// This is the VLAN of the virtual switch's
23+
// network card. By default, none is set. If none is set then a VLAN is not
24+
// set on the switch's network card. If this value is set it should match
25+
// the VLAN specified in by vlan_id.
26+
VlanId string `mapstructure:"vlan_id" required:"false"`
27+
// This allows a specific MAC address to be used on
28+
// the default main virtual network card. The MAC address must be a string with
29+
// no delimiters, for example "037777777777deadbeef".
30+
MacAddress string `mapstructure:"mac_address" required:"false"`
31+
}
32+
33+
func (ac AdapterConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig) ([]error, []string) {
34+
return nil, nil
35+
}

builder/hyperv/common/adapter_config.hcl2spec.go

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

builder/hyperv/common/config.go

Lines changed: 115 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ type CommonConfig struct {
7979
// try and determine the switch to use by looking for an external switch
8080
// that is up and running.
8181
SwitchName string `mapstructure:"switch_name" required:"false"`
82-
// The name of the switches to connect the virtual
82+
// The type of the main switch to connect the virtual
8383
// machine to. By default, leaving this value unset will cause Packer to
84-
// not use any additional switches.
85-
SwitchesNames []string `mapstructure:"switches_names" required:"false"`
84+
// try and determine the switch to use by looking for an external switch
85+
// that is up and running.
86+
SwitchType string `mapstructure:"switch_type" required:"false"`
8687
// This is the VLAN of the virtual switch's
8788
// network card. By default, none is set. If none is set then a VLAN is not
8889
// set on the switch's network card. If this value is set it should match
@@ -92,14 +93,16 @@ type CommonConfig struct {
9293
// the default main virtual network card. The MAC address must be a string with
9394
// no delimiters, for example "0000deadbeef".
9495
MacAddress string `mapstructure:"mac_address" required:"false"`
95-
// This allows a specific MAC addresses to be used on
96-
// the optional virtual network cards set in `switches_names` array. The MAC addresses must be strings with
97-
// no delimiters, for example "0000deadbeef".
98-
MacAddresses []string `mapstructure:"mac_addresses" required:"false"`
9996
// This is the VLAN of the virtual machine's network
10097
// card for the new virtual machine. By default none is set. If none is set
10198
// then VLANs are not set on the virtual machine's network card.
10299
VlanId string `mapstructure:"vlan_id" required:"false"`
100+
// This allows for multiple switches to be configured.
101+
// This should be used exclusively with SwitchName, SwitchVlanId, and MacAddress.
102+
SwitchConfigs []SwitchConfig `mapstructure:"switch_config" required:"false"`
103+
// This allows for multiple switches to be configured.
104+
// This should be used exclusively with MacAddress and VlanId.
105+
AdapterConfigs []AdapterConfig `mapstructure:"adapter_config" required:"false"`
103106
// The number of CPUs the virtual machine should use. If
104107
// this isn't specified, the default is 1 CPU.
105108
Cpu uint `mapstructure:"cpus" required:"false"`
@@ -205,9 +208,110 @@ func (c *CommonConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig
205208
log.Printf("%s: %v", "VMName", c.VMName)
206209
}
207210

208-
if c.SwitchName == "" {
209-
c.SwitchName = c.detectSwitchName(pc.PackerBuildName)
210-
log.Printf("Using switch %s", c.SwitchName)
211+
// Validation of switch config and switch parameters
212+
// The end result of this section is the unification of all Switch Parameters into SwitchConfigs.
213+
if (c.SwitchName != "" || c.SwitchType != "" || c.SwitchVlanId != "" || c.MacAddress != "" || c.VlanId != "") &&
214+
(len(c.AdapterConfigs) > 0 || len(c.SwitchConfigs) > 0) {
215+
err := fmt.Errorf("SwitchName/SwitchType/SwitchVlanId/MacAddress/VlanId and SwitchConfig/AdapterConfig not allowed.")
216+
errs = append(errs, err)
217+
} else {
218+
if c.SwitchName != "" || c.SwitchType != "" || c.SwitchVlanId != "" || c.MacAddress != "" || c.VlanId != "" {
219+
if c.SwitchType != "" {
220+
warns = append(warns, "SwitchType is deprecated and should be converted to SwitchConfigs")
221+
}
222+
if c.SwitchName != "" {
223+
warns = append(warns, "SwitchName is deprecated and should be converted to SwitchConfigs")
224+
} else {
225+
c.SwitchName = c.detectSwitchName(pc.PackerBuildName)
226+
if c.SwitchType == "" {
227+
c.SwitchType = SwitchTypeExternal
228+
}
229+
log.Printf("Using switch %s", c.SwitchName)
230+
}
231+
if c.SwitchVlanId != "" {
232+
warns = append(warns, "SwitchVlanId is deprecated and should be converted to SwitchConfigs")
233+
}
234+
if c.MacAddress != "" {
235+
warns = append(warns, "MacAddress is deprecated and should be converted to SwitchConfigs")
236+
}
237+
if c.VlanId != "" {
238+
warns = append(warns, "VlanId is deprecated and should be converted to SwitchConfigs")
239+
}
240+
if c.SwitchVlanId != "" {
241+
if c.SwitchVlanId != c.VlanId {
242+
warning := fmt.Sprintf("Switch network adaptor vlan should match virtual machine network adaptor " +
243+
"vlan. The switch will not be able to see traffic from the VM.")
244+
warns = Appendwarns(warns, warning)
245+
}
246+
}
247+
248+
c.SwitchConfigs = []SwitchConfig{{
249+
SwitchName: c.SwitchName,
250+
SwitchType: c.SwitchType,
251+
SwitchVlanId: c.SwitchVlanId,
252+
}}
253+
c.AdapterConfigs = []AdapterConfig{{
254+
Name: c.VMName,
255+
VlanId: c.VlanId,
256+
MacAddress: c.MacAddress,
257+
SwitchName: c.SwitchName,
258+
}}
259+
260+
// Make sure we don't get confused....
261+
c.VlanId = ""
262+
c.MacAddress = ""
263+
c.SwitchName = ""
264+
c.SwitchType = ""
265+
c.SwitchVlanId = ""
266+
} else {
267+
// If switchConfigs and adapterConfigs are not 0, assume the user knows what they are doing somewhat.
268+
// Make sure the structs are valid, but don't create things for them.
269+
if len(c.SwitchConfigs) == 0 {
270+
swname := c.detectSwitchName(pc.PackerBuildName)
271+
log.Printf("Using switch %s", swname)
272+
c.SwitchConfigs = []SwitchConfig{{SwitchName: swname}}
273+
}
274+
for ii, sw := range c.SwitchConfigs {
275+
if sw.SwitchName == "" {
276+
err := fmt.Errorf("SwitchName for Switch(%d) requires a name", ii)
277+
errs = append(errs, err)
278+
}
279+
}
280+
if c.SwitchConfigs[0].SwitchType == "" {
281+
c.SwitchConfigs[0].SwitchType = SwitchTypeExternal
282+
}
283+
if len(c.AdapterConfigs) == 0 {
284+
c.AdapterConfigs = []AdapterConfig{}
285+
for ii, sw := range c.SwitchConfigs {
286+
name := c.VMName
287+
if ii != 0 {
288+
name = fmt.Sprintf("%s-%d", c.VMName, ii)
289+
}
290+
c.AdapterConfigs = append(c.AdapterConfigs, AdapterConfig{Name: name, SwitchName: sw.SwitchName})
291+
}
292+
} else {
293+
for ii, adp := range c.AdapterConfigs {
294+
found := false
295+
for _, sw := range c.SwitchConfigs {
296+
if sw.SwitchName == adp.SwitchName {
297+
found = true
298+
break
299+
}
300+
}
301+
if !found {
302+
err := fmt.Errorf("Network Adapter %d (%s) requires a switch that is not defined: %s", ii, adp.Name, adp.SwitchName)
303+
errs = append(errs, err)
304+
}
305+
if adp.Name == "" {
306+
name := c.VMName
307+
if ii != 0 {
308+
name = fmt.Sprintf("%s-%d", c.VMName, ii)
309+
}
310+
adp.Name = name
311+
}
312+
}
313+
}
314+
}
211315
}
212316

213317
if c.Generation < 1 || c.Generation > 2 {
@@ -341,14 +445,6 @@ func (c *CommonConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig
341445
}
342446
}
343447

344-
if c.SwitchVlanId != "" {
345-
if c.SwitchVlanId != c.VlanId {
346-
warning := fmt.Sprintf("Switch network adaptor vlan should match virtual machine network adaptor " +
347-
"vlan. The switch will not be able to see traffic from the VM.")
348-
warns = Appendwarns(warns, warning)
349-
}
350-
}
351-
352448
err := c.checkDiskBlockSize()
353449
if err != nil {
354450
errs = append(errs, err)
@@ -396,7 +492,7 @@ func (c *CommonConfig) checkHostAvailableMemory() string {
396492
freeMB := powershell.GetHostAvailableMemory()
397493

398494
if (freeMB - float64(c.RamSize)) < LowRam {
399-
return "Hyper-V might fail to create a VM if there is not enough free memory in the system."
495+
return fmt.Sprintf("Hyper-V might fail to create a VM if there is not enough free memory in the system. (%v, %v, %v)", freeMB, float64(c.RamSize), LowRam)
400496
}
401497
}
402498

builder/hyperv/common/driver.go

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,35 +54,32 @@ type Driver interface {
5454
GetVirtualMachineNetworkAdapterAddress(string) (string, error)
5555

5656
//Set the vlan to use for switch
57-
SetNetworkAdapterVlanId(string, string) error
58-
59-
//Set the vlan to use for machine
57+
CreateVirtualMachineNetworkAdapter(string, string, string, bool) error
6058
SetVirtualMachineVlanId(string, string) error
61-
59+
//Set the vlan to use for machine
60+
SetNetworkAdapterVlanId(string, string) error
6261
SetVmNetworkAdapterMacAddress(string, string) error
6362

6463
//Replace the network adapter with a (non-)legacy adapter
6564
ReplaceVirtualMachineNetworkAdapter(string, bool) error
6665

66+
// Not used currently and likely broken.
6767
UntagVirtualMachineNetworkAdapterVlan(string, string) error
68-
69-
CreateExternalVirtualSwitch(string, string) error
70-
71-
GetVirtualMachineSwitchName(string) (string, error)
72-
7368
ConnectVirtualMachineNetworkAdapterToSwitch(string, string) error
69+
GetVirtualMachineSwitchName(string) (string, error)
7470

71+
// Switch Management Functions
7572
CreateVirtualSwitch(string, string) (bool, error)
76-
73+
CreateExternalVirtualSwitch(string) (bool, error)
7774
DeleteVirtualSwitch(string) error
7875

7976
CheckVMName(string) error
8077

81-
CreateVirtualMachine(string, string, string, int64, int64, int64, string, []string, []string, uint, bool, bool, string) error
78+
CreateVirtualMachine(string, string, string, int64, int64, int64, string, uint, bool, bool, string) error
8279

8380
AddVirtualMachineHardDrive(string, string, string, int64, int64, string) error
8481

85-
CloneVirtualMachine(string, string, string, bool, string, string, string, int64, string, []string, []string, bool) error
82+
CloneVirtualMachine(string, string, string, bool, string, string, string, int64, string, bool) error
8683

8784
ResizeVirtualMachineVhd(string, uint64) error
8885

0 commit comments

Comments
 (0)