Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support vlan_id and vlan_operation_mode on the hyperv_network_swtch resource #254

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,6 @@ website/vendor
/.vs
/.idea
/.terraform

# Ignore output binary
terraform-provider-hyperv
39 changes: 38 additions & 1 deletion api/hyperv-winrm/vm_switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ $SetVmSwitchArgs.DefaultQueueVrssEnabled=$vmSwitch.DefaultQueueVrssEnabled

Set-VMSwitch @SetVmSwitchArgs

if ($vmSwitch.OperationMode -eq 1) {
$SetVmNetworkAdapterVlanArgs = @{}
$SetVmNetworkAdapterVlanArgs.VMNetworkAdapterName=$vmSwitch.Name
$SetVmNetworkAdapterVlanArgs.ManagementOS=$true
$SetVmNetworkAdapterVlanArgs.Access=$true
$SetVmNetworkAdapterVlanArgs.VlanID=$vmSwitch.VlanId

Set-VMNetworkAdapterVlan @SetVmNetworkAdapterVlanArgs
}

`))

func (c *ClientConfig) CreateVMSwitch(
Expand All @@ -108,6 +118,8 @@ func (c *ClientConfig) CreateVMSwitch(
defaultQueueVmmqEnabled bool,
defaultQueueVmmqQueuePairs int32,
defaultQueueVrssEnabled bool,
operationMode api.VMSwitchOperationMode,
vlanId int,
) (err error) {
vmSwitchJson, err := json.Marshal(api.VmSwitch{
Name: name,
Expand All @@ -124,6 +136,8 @@ func (c *ClientConfig) CreateVMSwitch(
DefaultQueueVmmqEnabled: defaultQueueVmmqEnabled,
DefaultQueueVmmqQueuePairs: defaultQueueVmmqQueuePairs,
DefaultQueueVrssEnabled: defaultQueueVrssEnabled,
OperationMode: operationMode,
VlanID: vlanId,
})

if err != nil {
Expand All @@ -143,6 +157,11 @@ type getVMSwitchArgs struct {

var getVMSwitchTemplate = template.Must(template.New("GetVMSwitch").Parse(`
$ErrorActionPreference = 'Stop'
$vmAdapterVlanObject = Get-VMNetworkAdapterVlan -ManagementOS -VMNetworkAdapterName '{{.Name}}*' | %{ @{
OperationMode=$_.OperationMode
AccessVlanId=$_.AccessVlanId
}}

$vmSwitchObject = Get-VMSwitch -Name '{{.Name}}*' | ?{$_.Name -eq '{{.Name}}' } | %{ @{
Name=$_.Name;
Notes=$_.Notes;
Expand All @@ -158,8 +177,11 @@ $vmSwitchObject = Get-VMSwitch -Name '{{.Name}}*' | ?{$_.Name -eq '{{.Name}}' }
DefaultQueueVmmqEnabled=$_.DefaultQueueVmmqEnabledRequested;
DefaultQueueVmmqQueuePairs=$_.DefaultQueueVmmqQueuePairsRequested;
DefaultQueueVrssEnabled=$_.DefaultQueueVrssEnabledRequested;
OperationMode=$vmAdapterVlanObject.OperationMode
VlanID=$vmAdapterVlanObject.AccessVlanId
}}


if ($vmSwitchObject){
$vmSwitch = ConvertTo-Json -InputObject $vmSwitchObject
$vmSwitch
Expand Down Expand Up @@ -207,7 +229,8 @@ $SetVmSwitchArgs.Name=$vmSwitch.Name
$SetVmSwitchArgs.Notes=$vmSwitch.Notes
if ($NetAdapterNames) {
$SetVmSwitchArgs.AllowManagementOS=$vmSwitch.AllowManagementOS
$SetVmSwitchArgs.NetAdapterName=$NetAdapterNames
# Converts the incoming Object[] to a String as expected by the command
$SetVmSwitchArgs.NetAdapterName=[system.String]::Join(",", $NetAdapterNames)
#Updates not supported on:
#-EnableEmbeddedTeaming $vmSwitch.EmbeddedTeamingEnabled
#-EnableIov $vmSwitch.IovEnabled
Expand Down Expand Up @@ -236,6 +259,16 @@ $SetVmSwitchArgs.DefaultQueueVmmqQueuePairs=$vmSwitch.DefaultQueueVmmqQueuePairs
$SetVmSwitchArgs.DefaultQueueVrssEnabled=$vmSwitch.DefaultQueueVrssEnabled

Set-VMSwitch @SetVmSwitchArgs

if ($vmSwitch.OperationMode -eq 1) {
$SetVmNetworkAdapterVlanArgs = @{}
$SetVmNetworkAdapterVlanArgs.VMNetworkAdapterName=$vmSwitch.Name
$SetVmNetworkAdapterVlanArgs.ManagementOS=$true
$SetVmNetworkAdapterVlanArgs.Access=$true
$SetVmNetworkAdapterVlanArgs.VlanID=$vmSwitch.VlanId

Set-VMNetworkAdapterVlan @SetVmNetworkAdapterVlanArgs
}
`))

func (c *ClientConfig) UpdateVMSwitch(
Expand All @@ -255,6 +288,8 @@ func (c *ClientConfig) UpdateVMSwitch(
defaultQueueVmmqEnabled bool,
defaultQueueVmmqQueuePairs int32,
defaultQueueVrssEnabled bool,
operationMode api.VMSwitchOperationMode,
vlanId int,
) (err error) {
vmSwitchJson, err := json.Marshal(api.VmSwitch{
Name: name,
Expand All @@ -271,6 +306,8 @@ func (c *ClientConfig) UpdateVMSwitch(
DefaultQueueVmmqEnabled: defaultQueueVmmqEnabled,
DefaultQueueVmmqQueuePairs: defaultQueueVmmqQueuePairs,
DefaultQueueVrssEnabled: defaultQueueVrssEnabled,
OperationMode: operationMode,
VlanID: vlanId,
})

if err != nil {
Expand Down
65 changes: 65 additions & 0 deletions api/vm_switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,65 @@ import (
"strings"
)

type VMSwitchOperationMode int

const (
VMSwitchOperationMode_Untagged VMSwitchOperationMode = 0
VMSwitchOperationMode_Isolated VMSwitchOperationMode = 1
VMSwitchOperationMode_Community VMSwitchOperationMode = 2
VMSwitchOperationMode_Promiscuous VMSwitchOperationMode = 3
)

var VMSwitchOperationMode_name = map[VMSwitchOperationMode]string{
VMSwitchOperationMode_Untagged: "Untagged",
VMSwitchOperationMode_Isolated: "Isolated",
VMSwitchOperationMode_Community: "Community",
VMSwitchOperationMode_Promiscuous: "Promiscuous",
}

var VMSwitchOperationMode_value = map[string]VMSwitchOperationMode{
"untagged": VMSwitchOperationMode_Untagged,
"isolated": VMSwitchOperationMode_Isolated,
"community": VMSwitchOperationMode_Community,
"promiscuous": VMSwitchOperationMode_Promiscuous,
}

func (x VMSwitchOperationMode) String() string {
return VMSwitchOperationMode_name[x]
}

func ToVMSwitchOperationMode(x string) VMSwitchOperationMode {
if integerValue, err := strconv.Atoi(x); err == nil {
return VMSwitchOperationMode(integerValue)
}

return VMSwitchOperationMode_value[strings.ToLower(x)]
}

func (d *VMSwitchOperationMode) MarshalJSON() ([]byte, error) {
buffer := bytes.NewBufferString(`"`)
buffer.WriteString(d.String())
buffer.WriteString(`"`)
return buffer.Bytes(), nil
}

func (d *VMSwitchOperationMode) UnmarshalJSON(b []byte) error {
var s string
err := json.Unmarshal(b, &s)
if err != nil {
var i int
err2 := json.Unmarshal(b, &i)
if err2 == nil {
*d = VMSwitchOperationMode(i)
return nil
}

return err
}
*d = ToVMSwitchOperationMode(s)
return nil
}

type VMSwitchBandwidthMode int

const (
Expand Down Expand Up @@ -142,6 +201,8 @@ type VmSwitch struct {
DefaultQueueVmmqEnabled bool
DefaultQueueVmmqQueuePairs int32
DefaultQueueVrssEnabled bool
OperationMode VMSwitchOperationMode
VlanID int
}

type HypervVmSwitchClient interface {
Expand All @@ -162,6 +223,8 @@ type HypervVmSwitchClient interface {
defaultQueueVmmqEnabled bool,
defaultQueueVmmqQueuePairs int32,
defaultQueueVrssEnabled bool,
vlanOperationMode VMSwitchOperationMode,
vlanId int,
) (err error)
GetVMSwitch(ctx context.Context, name string) (result VmSwitch, err error)
UpdateVMSwitch(
Expand All @@ -181,6 +244,8 @@ type HypervVmSwitchClient interface {
defaultQueueVmmqEnabled bool,
defaultQueueVmmqQueuePairs int32,
defaultQueueVrssEnabled bool,
vlanOperationMode VMSwitchOperationMode,
vlanId int,
) (err error)
DeleteVMSwitch(ctx context.Context, name string) (err error)
}
6 changes: 5 additions & 1 deletion api/vm_switch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ func TestSerializeVmSwitch(t *testing.T) {
NetAdapterNames: []string{"wan", "lan"},
DefaultQueueVrssEnabled: true,
DefaultQueueVmmqQueuePairs: 0,
OperationMode: VMSwitchOperationMode_Isolated,
VlanID: 42,
})

if err != nil {
Expand All @@ -44,7 +46,9 @@ func TestDeserializeVmSwitch(t *testing.T) {
"SwitchType": 2,
"IovEnabled": false,
"EmbeddedTeamingEnabled": false,
"PacketDirectEnabled": false
"PacketDirectEnabled": false,
"OperationMode": 1,
"VlanID": 42
}
`

Expand Down
2 changes: 2 additions & 0 deletions docs/resources/network_switch.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ resource "hyperv_network_switch" "default" {
- `notes` (String) Specifies a note to be associated with the switch to be created.
- `switch_type` (String) Specifies the type of the switch to be created. Valid values to use are `Internal`, `Private` and `External`.
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
- `vlan_access_id` (Number) The VLAN identifier used for all network communications through this network adapter. This setting does not affect virtual machine networking
- `vlan_operation_mode` (String) Operation Mode for the management operating system. Valid values are [Untagged, Isolated, Community, Promiscuous]. Only Untagged and Isolated are currently supported

### Read-Only

Expand Down
31 changes: 29 additions & 2 deletions internal/provider/resource_hyperv_network_switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,21 @@ func resourceHyperVNetworkSwitch() *schema.Resource {
Default: false,
Description: "Should Virtual Receive Side Scaling be enabled. This configuration allows the load from a virtual network adapter to be distributed across multiple virtual processors in a virtual machine (VM), allowing the VM to process more network traffic more rapidly than it can with a single logical processor.",
},

"vlan_operation_mode": {
Type: schema.TypeString,
Optional: true,
Default: api.VMSwitchOperationMode_name[api.VMSwitchOperationMode_Untagged],
ValidateDiagFunc: StringKeyInMap(api.VMSwitchOperationMode_value, true),
Description: "Operation Mode for the management operating system. Valid values are [Untagged, Isolated, Community, Promiscuous]. Only Untagged and Isolated are currently supported",
},

"vlan_access_id": {
Type: schema.TypeInt,
Optional: true,
Default: 0,
Description: "The VLAN identifier used for all network communications through this network adapter. This setting does not affect virtual machine networking",
},
},
}
}
Expand Down Expand Up @@ -236,7 +251,10 @@ func resourceHyperVNetworkSwitchCreate(ctx context.Context, d *schema.ResourceDa
return diag.Errorf("[ERROR][hyperv][create] defaultQueueVmmqQueuePairs must be greater then 0")
}

err := c.CreateVMSwitch(ctx, switchName, notes, allowManagementOS, embeddedTeamingEnabled, iovEnabled, packetDirectEnabled, bandwidthReservationMode, switchType, netAdapterNames, defaultFlowMinimumBandwidthAbsolute, defaultFlowMinimumBandwidthWeight, defaultQueueVmmqEnabled, defaultQueueVmmqQueuePairs, defaultQueueVrssEnabled)
vlanOperationMode := api.ToVMSwitchOperationMode((d.Get("vlan_operation_mode")).(string))
vlanAccessId := int((d.Get("vlan_access_id")).(int))

err := c.CreateVMSwitch(ctx, switchName, notes, allowManagementOS, embeddedTeamingEnabled, iovEnabled, packetDirectEnabled, bandwidthReservationMode, switchType, netAdapterNames, defaultFlowMinimumBandwidthAbsolute, defaultFlowMinimumBandwidthWeight, defaultQueueVmmqEnabled, defaultQueueVmmqQueuePairs, defaultQueueVrssEnabled, vlanOperationMode, vlanAccessId)

if err != nil {
return diag.FromErr(err)
Expand Down Expand Up @@ -363,6 +381,12 @@ func resourceHyperVNetworkSwitchRead(ctx context.Context, d *schema.ResourceData
if err := d.Set("default_queue_vrss_enabled", s.DefaultQueueVrssEnabled); err != nil {
return diag.FromErr(err)
}
if err := d.Set("vlan_operation_mode", s.OperationMode.String()); err != nil {
return diag.FromErr(err)
}
if err := d.Set("vlan_access_id", s.VlanID); err != nil {
return diag.FromErr(err)
}

log.Printf("[INFO][hyperv][read] read hyperv switch: %#v", d)

Expand Down Expand Up @@ -446,7 +470,10 @@ func resourceHyperVNetworkSwitchUpdate(ctx context.Context, d *schema.ResourceDa
return diag.Errorf("[ERROR][hyperv][update] defaultQueueVmmqQueuePairs must be greater then 0")
}

err := c.UpdateVMSwitch(ctx, id, newName, notes, allowManagementOS, switchType, netAdapterNames, defaultFlowMinimumBandwidthAbsolute, defaultFlowMinimumBandwidthWeight, defaultQueueVmmqEnabled, defaultQueueVmmqQueuePairs, defaultQueueVrssEnabled)
vlanOperationMode := api.ToVMSwitchOperationMode((d.Get("vlan_operation_mode")).(string))
vlanAccessId := int((d.Get("vlan_access_id")).(int))

err := c.UpdateVMSwitch(ctx, id, newName, notes, allowManagementOS, switchType, netAdapterNames, defaultFlowMinimumBandwidthAbsolute, defaultFlowMinimumBandwidthWeight, defaultQueueVmmqEnabled, defaultQueueVmmqQueuePairs, defaultQueueVrssEnabled, vlanOperationMode, vlanAccessId)

if err != nil {
return diag.FromErr(err)
Expand Down