@@ -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
0 commit comments