From 60cc7314f0f611c5f9411cc7ec8e37f869e6c367 Mon Sep 17 00:00:00 2001 From: GraysonWu Date: Tue, 22 Aug 2023 14:26:31 -0700 Subject: [PATCH] UplinkHostSwitchProfile support (#939) Signed-off-by: graysonwu --- ..._source_nsxt_uplink_host_switch_profile.go | 42 ++ nsxt/policy_common.go | 8 + nsxt/provider.go | 2 + ...esource_nsxt_uplink_host_switch_profile.go | 483 ++++++++++++++++++ ...ce_nsxt_uplink_host_switch_profile_test.go | 326 ++++++++++++ .../d/uplink_host_switch_profile.markdown | 31 ++ website/docs/r/policy_vni_pool.html.markdown | 2 +- .../uplink_host_switch_profile.html.markdown | 129 +++++ 8 files changed, 1022 insertions(+), 1 deletion(-) create mode 100644 nsxt/data_source_nsxt_uplink_host_switch_profile.go create mode 100644 nsxt/resource_nsxt_uplink_host_switch_profile.go create mode 100644 nsxt/resource_nsxt_uplink_host_switch_profile_test.go create mode 100644 website/docs/d/uplink_host_switch_profile.markdown create mode 100644 website/docs/r/uplink_host_switch_profile.html.markdown diff --git a/nsxt/data_source_nsxt_uplink_host_switch_profile.go b/nsxt/data_source_nsxt_uplink_host_switch_profile.go new file mode 100644 index 000000000..3bd1ec207 --- /dev/null +++ b/nsxt/data_source_nsxt_uplink_host_switch_profile.go @@ -0,0 +1,42 @@ +/* Copyright © 2023 VMware, Inc. All Rights Reserved. + SPDX-License-Identifier: MPL-2.0 */ + +package nsxt + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra" +) + +func dataSourceNsxtUplinkHostSwitchProfile() *schema.Resource { + return &schema.Resource{ + Read: dataSourceNsxtUplinkHostSwitchProfileRead, + + Schema: map[string]*schema.Schema{ + "id": getDataSourceIDSchema(), + "gateway_path": getPolicyPathSchema(false, false, "Gateway path"), + "path": getPathSchema(), + "display_name": getDisplayNameSchema(), + "description": getDescriptionSchema(), + }, + } +} + +func dataSourceNsxtUplinkHostSwitchProfileRead(d *schema.ResourceData, m interface{}) error { + connector := getPolicyConnector(m) + + gwPath := d.Get("gateway_path").(string) + query := make(map[string]string) + if len(gwPath) > 0 { + query["parent_path"] = fmt.Sprintf("%s*", gwPath) + } + + _, err := policyDataSourceResourceReadWithValidation(d, connector, getSessionContext(d, m), infra.HostSwitchProfiles_LIST_HOSTSWITCH_PROFILE_TYPE_POLICYUPLINKHOSTSWITCHPROFILE, query, false) + if err == nil { + return nil + } + + return fmt.Errorf("UplinkHostSwitchProfile with name '%s' was not found", d.Get("display_name").(string)) +} diff --git a/nsxt/policy_common.go b/nsxt/policy_common.go index b12abe18a..cae89697b 100644 --- a/nsxt/policy_common.go +++ b/nsxt/policy_common.go @@ -111,6 +111,14 @@ func getDataSourceStringSchema(description string) *schema.Schema { } } +func getRequiredStringSchema(description string) *schema.Schema { + return &schema.Schema{ + Type: schema.TypeString, + Description: description, + Required: true, + } +} + func getDomainNameSchema() *schema.Schema { return &schema.Schema{ Type: schema.TypeString, diff --git a/nsxt/provider.go b/nsxt/provider.go index f068c4ac1..379a7da32 100644 --- a/nsxt/provider.go +++ b/nsxt/provider.go @@ -275,6 +275,7 @@ func Provider() *schema.Provider { "nsxt_policy_project": dataSourceNsxtPolicyProject(), "nsxt_policy_gateway_prefix_list": dataSourceNsxtPolicyGatewayPrefixList(), "nsxt_policy_gateway_route_map": dataSourceNsxtPolicyGatewayRouteMap(), + "nsxt_uplink_host_switch_profile": dataSourceNsxtUplinkHostSwitchProfile(), }, ResourcesMap: map[string]*schema.Resource{ @@ -403,6 +404,7 @@ func Provider() *schema.Provider { "nsxt_edge_cluster": resourceNsxtEdgeCluster(), "nsxt_compute_manager": resourceNsxtComputeManager(), "nsxt_manager_cluster": resourceNsxtManagerCluster(), + "nsxt_uplink_host_switch_profile": resourceNsxtUplinkHostSwitchProfile(), }, ConfigureFunc: providerConfigure, diff --git a/nsxt/resource_nsxt_uplink_host_switch_profile.go b/nsxt/resource_nsxt_uplink_host_switch_profile.go new file mode 100644 index 000000000..6ded7cc72 --- /dev/null +++ b/nsxt/resource_nsxt_uplink_host_switch_profile.go @@ -0,0 +1,483 @@ +/* Copyright © 2023 VMware, Inc. All Rights Reserved. + SPDX-License-Identifier: MPL-2.0 */ + +package nsxt + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/vmware/vsphere-automation-sdk-go/runtime/bindings" + "github.com/vmware/vsphere-automation-sdk-go/runtime/data" + "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" + "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra" + "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" +) + +var lacpLoadBalanceAlgorithms = []string{ + model.Lag_LOAD_BALANCE_ALGORITHM_SRCMAC, + model.Lag_LOAD_BALANCE_ALGORITHM_DESTMAC, + model.Lag_LOAD_BALANCE_ALGORITHM_SRCDESTMAC, + model.Lag_LOAD_BALANCE_ALGORITHM_SRCDESTIPVLAN, + model.Lag_LOAD_BALANCE_ALGORITHM_SRCDESTMACIPPORT, +} + +var lacpGroupModes = []string{ + model.Lag_MODE_ACTIVE, + model.Lag_MODE_PASSIVE, +} + +var lacpTimeoutTypes = []string{ + model.Lag_TIMEOUT_TYPE_SLOW, + model.Lag_TIMEOUT_TYPE_FAST, +} + +var uplinkTypes = []string{ + model.Uplink_UPLINK_TYPE_PNIC, + model.Uplink_UPLINK_TYPE_LAG, +} + +var teamingPolicies = []string{ + model.TeamingPolicy_POLICY_FAILOVER_ORDER, + model.TeamingPolicy_POLICY_LOADBALANCE_SRCID, + model.TeamingPolicy_POLICY_LOADBALANCE_SRC_MAC, +} + +var overlayEncapModes = []string{ + model.PolicyUplinkHostSwitchProfile_OVERLAY_ENCAP_VXLAN, + model.PolicyUplinkHostSwitchProfile_OVERLAY_ENCAP_GENEVE, +} + +func resourceNsxtUplinkHostSwitchProfile() *schema.Resource { + return &schema.Resource{ + Create: resourceNsxtUplinkHostSwitchProfileCreate, + Read: resourceNsxtUplinkHostSwitchProfileRead, + Update: resourceNsxtUplinkHostSwitchProfileUpdate, + Delete: resourceNsxtUplinkHostSwitchProfileDelete, + Importer: &schema.ResourceImporter{ + State: nsxtPolicyPathResourceImporter, + }, + + Schema: map[string]*schema.Schema{ + "nsx_id": getNsxIDSchema(), + "path": getPathSchema(), + "display_name": getDisplayNameSchema(), + "description": getDescriptionSchema(), + "revision": getRevisionSchema(), + "tag": getTagsSchema(), + "lag": { + Type: schema.TypeList, + Description: "List of LACP group", + Optional: true, + MaxItems: 64, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Description: "unique id", + Required: false, + Optional: false, + Computed: true, + }, + "load_balance_algorithm": { + Type: schema.TypeString, + Description: "LACP load balance Algorithm", + Required: true, + ValidateFunc: validation.StringInSlice(lacpLoadBalanceAlgorithms, false), + }, + "mode": { + Type: schema.TypeString, + Description: "LACP group mode", + Required: true, + ValidateFunc: validation.StringInSlice(lacpGroupModes, false), + }, + "name": getRequiredStringSchema("Lag name"), + "number_of_uplinks": { + Type: schema.TypeInt, + Description: "Number of uplinks", + Required: true, + ValidateFunc: validation.IntBetween(2, 32), + }, + "timeout_type": { + Type: schema.TypeString, + Description: "LACP timeout type", + Optional: true, + Default: model.Lag_TIMEOUT_TYPE_SLOW, + ValidateFunc: validation.StringInSlice(lacpTimeoutTypes, false), + }, + "uplink": { + Type: schema.TypeList, + Description: "uplink names", + Required: false, + Optional: false, + Computed: true, + Elem: getUplinkSchemaResource(), + }, + }, + }, + }, + "teaming": { + Type: schema.TypeList, + Description: "Default TeamingPolicy associated with this UplinkProfile", + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "active": { + Type: schema.TypeList, + Description: "List of Uplinks used in active list", + Required: true, + Elem: getUplinkSchemaResource(), + }, + "policy": { + Type: schema.TypeString, + Description: "Teaming policy", + Required: true, + ValidateFunc: validation.StringInSlice(teamingPolicies, false), + }, + "standby": { + Type: schema.TypeList, + Description: "List of Uplinks used in standby list", + Optional: true, + Elem: getUplinkSchemaResource(), + }, + }, + }, + }, + "named_teaming": { + Type: schema.TypeList, + Description: "List of named uplink teaming policies that can be used by logical switches", + Optional: true, + MaxItems: 32, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": getRequiredStringSchema("The name of the uplink teaming policy"), + "active": { + Type: schema.TypeList, + Description: "List of Uplinks used in active list", + Required: true, + Elem: getUplinkSchemaResource(), + }, + "policy": { + Type: schema.TypeString, + Description: "Teaming policy", + Required: true, + ValidateFunc: validation.StringInSlice(teamingPolicies, false), + }, + "standby": { + Type: schema.TypeList, + Description: "List of Uplinks used in standby list", + Optional: true, + Elem: getUplinkSchemaResource(), + }, + }, + }, + }, + "overlay_encap": { + Type: schema.TypeString, + Description: "The protocol used to encapsulate overlay traffic", + Optional: true, + Default: model.PolicyUplinkHostSwitchProfile_OVERLAY_ENCAP_GENEVE, + ValidateFunc: validation.StringInSlice(overlayEncapModes, false), + }, + "transport_vlan": { + Type: schema.TypeInt, + Description: "VLAN used for tagging Overlay traffic of associated HostSwitch", + Optional: true, + Default: 0, + ValidateFunc: validation.IntBetween(0, 4094), + }, + "mtu": { + Type: schema.TypeInt, + Description: "Maximum Transmission Unit used for uplinks", + Optional: true, + Default: 1700, + ValidateFunc: validation.IntAtLeast(1280), + }, + }, + } +} + +func getUplinkSchemaResource() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "uplink_name": getRequiredStringSchema("Name of this uplink"), + "uplink_type": { + Type: schema.TypeString, + Description: "Type of the uplink", + Required: true, + ValidateFunc: validation.StringInSlice(uplinkTypes, false), + }, + }, + } +} + +func setUplinkHostSwitchProfileSchema(d *schema.ResourceData, profile model.PolicyUplinkHostSwitchProfile) { + uplinksToMap := func(uplinks []model.Uplink) []map[string]interface{} { + var uplinksMap []map[string]interface{} + for _, uplink := range uplinks { + uplinkMap := make(map[string]interface{}) + uplinkMap["uplink_name"] = uplink.UplinkName + uplinkMap["uplink_type"] = uplink.UplinkType + uplinksMap = append(uplinksMap, uplinkMap) + } + return uplinksMap + } + + var lagsSchema []map[string]interface{} + for _, lag := range profile.Lags { + lagMap := make(map[string]interface{}) + lagMap["id"] = lag.Id + lagMap["load_balance_algorithm"] = lag.LoadBalanceAlgorithm + lagMap["mode"] = lag.Mode + lagMap["name"] = lag.Name + lagMap["number_of_uplinks"] = lag.NumberOfUplinks + lagMap["timeout_type"] = lag.TimeoutType + lagMap["uplink"] = uplinksToMap(lag.Uplinks) + lagsSchema = append(lagsSchema, lagMap) + } + d.Set("lag", lagsSchema) + + teamingSchema := make(map[string]interface{}) + teamingSchema["policy"] = profile.Teaming.Policy + teamingSchema["active"] = uplinksToMap(profile.Teaming.ActiveList) + teamingSchema["standby"] = uplinksToMap(profile.Teaming.StandbyList) + d.Set("teaming", []map[string]interface{}{teamingSchema}) + + var namedTeamingsSchema []map[string]interface{} + for _, namedTeaming := range profile.NamedTeamings { + namedTeamingMap := make(map[string]interface{}) + namedTeamingMap["name"] = namedTeaming.Name + namedTeamingMap["policy"] = namedTeaming.Policy + namedTeamingMap["active"] = uplinksToMap(namedTeaming.ActiveList) + namedTeamingMap["standby"] = uplinksToMap(namedTeaming.StandbyList) + namedTeamingsSchema = append(namedTeamingsSchema, namedTeamingMap) + } + d.Set("named_teaming", namedTeamingsSchema) + + d.Set("overlay_encap", profile.OverlayEncap) + d.Set("transport_vlan", profile.TransportVlan) + d.Set("mtu", profile.Mtu) +} + +func resourceNsxtUplinkHostSwitchProfileExists(id string, connector client.Connector, isGlobalManager bool) (bool, error) { + var err error + client := infra.NewHostSwitchProfilesClient(connector) + structValue, err := client.Get(id) + if err == nil { + converter := bindings.NewTypeConverter() + baseInterface, errs := converter.ConvertToGolang(structValue, model.PolicyBaseHostSwitchProfileBindingType()) + if errs != nil { + return false, errs[0] + } + base := baseInterface.(model.PolicyBaseHostSwitchProfile) + + resourceType := base.ResourceType + if resourceType != infra.HostSwitchProfiles_LIST_HOSTSWITCH_PROFILE_TYPE_POLICYUPLINKHOSTSWITCHPROFILE { + return false, nil + } + return true, nil + } + + if isNotFoundError(err) { + return false, nil + } + + return false, logAPIError("Error retrieving resource", err) +} + +func resourceNsxtUplinkHostSwitchProfileRead(d *schema.ResourceData, m interface{}) error { + connector := getPolicyConnector(m) + + id := d.Id() + if id == "" { + return fmt.Errorf("Error obtaining UplinkHostSwitchProfile ID") + } + client := infra.NewHostSwitchProfilesClient(connector) + structValue, err := client.Get(id) + if err != nil { + return handleReadError(d, "UplinkHostSwitchProfile", id, err) + } + + converter := bindings.NewTypeConverter() + baseInterface, errs := converter.ConvertToGolang(structValue, model.PolicyBaseHostSwitchProfileBindingType()) + if errs != nil { + return errs[0] + } + base := baseInterface.(model.PolicyBaseHostSwitchProfile) + + resourceType := base.ResourceType + if resourceType != infra.HostSwitchProfiles_LIST_HOSTSWITCH_PROFILE_TYPE_POLICYUPLINKHOSTSWITCHPROFILE { + return handleReadError(d, "UplinkHostSwitchProfile", id, err) + } + + uplinkInterface, errs := converter.ConvertToGolang(structValue, model.PolicyUplinkHostSwitchProfileBindingType()) + if errs != nil { + return errs[0] + } + uplinkHostSwitchProfile := uplinkInterface.(model.PolicyUplinkHostSwitchProfile) + d.Set("display_name", uplinkHostSwitchProfile.DisplayName) + d.Set("description", uplinkHostSwitchProfile.Description) + setPolicyTagsInSchema(d, uplinkHostSwitchProfile.Tags) + d.Set("nsx_id", id) + d.Set("path", uplinkHostSwitchProfile.Path) + d.Set("revision", uplinkHostSwitchProfile.Revision) + setUplinkHostSwitchProfileSchema(d, uplinkHostSwitchProfile) + return nil +} + +func uplinkSchemaToModelList(schema interface{}) []model.Uplink { + uplinkSchemaList := schema.([]interface{}) + var uplinkList []model.Uplink + for _, item := range uplinkSchemaList { + data := item.(map[string]interface{}) + uplinkName := data["uplink_name"].(string) + uplinkType := data["uplink_type"].(string) + obj := model.Uplink{ + UplinkName: &uplinkName, + UplinkType: &uplinkType, + } + uplinkList = append(uplinkList, obj) + } + return uplinkList +} + +func uplinkHostSwitchProfileSchemaToModel(d *schema.ResourceData) model.PolicyUplinkHostSwitchProfile { + displayName := d.Get("display_name").(string) + description := d.Get("description").(string) + tags := getPolicyTagsFromSchema(d) + + var lags []model.Lag + lagsList := d.Get("lag").([]interface{}) + for _, lagSchema := range lagsList { + lagData := lagSchema.(map[string]interface{}) + loadBalanceAlgorithm := lagData["load_balance_algorithm"].(string) + mode := lagData["mode"].(string) + name := lagData["name"].(string) + numberOfUplinks := int64(lagData["number_of_uplinks"].(int)) + timeoutType := lagData["timeout_type"].(string) + lag := model.Lag{ + LoadBalanceAlgorithm: &loadBalanceAlgorithm, + Mode: &mode, + Name: &name, + NumberOfUplinks: &numberOfUplinks, + TimeoutType: &timeoutType, + } + lags = append(lags, lag) + } + + var namedTeamings []model.NamedTeamingPolicy + namedTeamingsList := d.Get("named_teaming").([]interface{}) + for _, namedTeamingsSchema := range namedTeamingsList { + namedTeamingsSchemaData := namedTeamingsSchema.(map[string]interface{}) + activeList := uplinkSchemaToModelList(namedTeamingsSchemaData["active"]) + standbyList := uplinkSchemaToModelList(namedTeamingsSchemaData["standby"]) + policy := namedTeamingsSchemaData["policy"].(string) + name := namedTeamingsSchemaData["name"].(string) + namedTeaming := model.NamedTeamingPolicy{ + ActiveList: activeList, + Policy: &policy, + StandbyList: standbyList, + Name: &name, + } + namedTeamings = append(namedTeamings, namedTeaming) + } + + teamingSchema := d.Get("teaming").([]interface{})[0] + teamingSchemaData := teamingSchema.(map[string]interface{}) + activeList := uplinkSchemaToModelList(teamingSchemaData["active"]) + standbyList := uplinkSchemaToModelList(teamingSchemaData["standby"]) + policy := teamingSchemaData["policy"].(string) + teaming := model.TeamingPolicy{ + ActiveList: activeList, + Policy: &policy, + StandbyList: standbyList, + } + + overlayEncap := d.Get("overlay_encap").(string) + mtu := int64(d.Get("mtu").(int)) + transportVlan := int64(d.Get("transport_vlan").(int)) + + uplinkHostSwitchProfile := model.PolicyUplinkHostSwitchProfile{ + DisplayName: &displayName, + Description: &description, + Tags: tags, + ResourceType: model.PolicyBaseHostSwitchProfile_RESOURCE_TYPE_POLICYUPLINKHOSTSWITCHPROFILE, + Mtu: &mtu, + OverlayEncap: &overlayEncap, + TransportVlan: &transportVlan, + Lags: lags, + NamedTeamings: namedTeamings, + Teaming: &teaming, + } + return uplinkHostSwitchProfile +} + +func resourceNsxtUplinkHostSwitchProfileCreate(d *schema.ResourceData, m interface{}) error { + // Initialize resource Id and verify this ID is not yet used + id, err := getOrGenerateID(d, m, resourceNsxtUplinkHostSwitchProfileExists) + if err != nil { + return err + } + + connector := getPolicyConnector(m) + client := infra.NewHostSwitchProfilesClient(connector) + converter := bindings.NewTypeConverter() + + uplinkHostSwitchProfile := uplinkHostSwitchProfileSchemaToModel(d) + profileValue, errs := converter.ConvertToVapi(uplinkHostSwitchProfile, model.PolicyUplinkHostSwitchProfileBindingType()) + if errs != nil { + return errs[0] + } + profileStruct := profileValue.(*data.StructValue) + _, err = client.Patch(id, profileStruct) + if err != nil { + return handleCreateError("UplinkHostSwitchProfile", id, err) + } + + d.SetId(id) + d.Set("nsx_id", id) + + return resourceNsxtUplinkHostSwitchProfileRead(d, m) +} + +func resourceNsxtUplinkHostSwitchProfileUpdate(d *schema.ResourceData, m interface{}) error { + id := d.Id() + if id == "" { + return fmt.Errorf("Error obtaining UplinkHostSwitchProfile ID") + } + + connector := getPolicyConnector(m) + client := infra.NewHostSwitchProfilesClient(connector) + converter := bindings.NewTypeConverter() + + uplinkHostSwitchProfile := uplinkHostSwitchProfileSchemaToModel(d) + revision := int64(d.Get("revision").(int)) + uplinkHostSwitchProfile.Revision = &revision + profileValue, errs := converter.ConvertToVapi(uplinkHostSwitchProfile, model.PolicyUplinkHostSwitchProfileBindingType()) + if errs != nil { + return errs[0] + } + profileStruct := profileValue.(*data.StructValue) + _, err := client.Update(id, profileStruct) + if err != nil { + return handleUpdateError("UplinkHostSwitchProfile", id, err) + } + + return resourceNsxtUplinkHostSwitchProfileRead(d, m) +} + +func resourceNsxtUplinkHostSwitchProfileDelete(d *schema.ResourceData, m interface{}) error { + id := d.Id() + if id == "" { + return fmt.Errorf("error obtaining UplinkHostSwitchProfile ID") + } + connector := getPolicyConnector(m) + client := infra.NewHostSwitchProfilesClient(connector) + err := client.Delete(id) + if err != nil { + return handleDeleteError("UplinkHostSwitchProfile", id, err) + } + return nil +} diff --git a/nsxt/resource_nsxt_uplink_host_switch_profile_test.go b/nsxt/resource_nsxt_uplink_host_switch_profile_test.go new file mode 100644 index 000000000..01358308f --- /dev/null +++ b/nsxt/resource_nsxt_uplink_host_switch_profile_test.go @@ -0,0 +1,326 @@ +/* Copyright © 2023 VMware, Inc. All Rights Reserved. + SPDX-License-Identifier: MPL-2.0 */ + +package nsxt + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +var accTestUplinkHostSwitchProfileCreateAttributes = map[string]string{ + "display_name": getAccTestResourceName(), + "description": "terraform created", + "mtu": "1400", + "overlay_encap": "GENEVE", + "transport_vlan": "1", + "lag_load_balance_algorithm": "SRCDESTIPVLAN", + "lag_mode": "ACTIVE", + "lag_name": "lag-name", + "lag_number_of_uplinks": "2", + "lag_timeout_type": "SLOW", + "teaming_al_uplink_name": "t-uplink-name1", + "teaming_al_uplink_type": "PNIC", + "teaming_sl_uplink_name": "t-uplink-name2", + "teaming_sl_uplink_type": "PNIC", + "teaming_policy": "FAILOVER_ORDER", + "named_teaming_name": "nt-name", + "named_teaming_al_uplink_name": "nt-uplink-name1", + "named_teaming_al_uplink_type": "PNIC", + "named_teaming_sl_uplink_name": "nt-uplink-name2", + "named_teaming_sl_uplink_type": "PNIC", + "named_teaming_policy": "FAILOVER_ORDER", +} + +var accTestUplinkHostSwitchProfileUpdateAttributes = map[string]string{ + "display_name": getAccTestResourceName(), + "description": "terraform created", + "mtu": "1500", + "overlay_encap": "VXLAN", + "transport_vlan": "1", + "lag_load_balance_algorithm": "SRCMAC", + "lag_mode": "PASSIVE", + "lag_name": "lag-name", + "lag_number_of_uplinks": "2", + "lag_timeout_type": "FAST", + "teaming_al_uplink_name": "t-uplink-name3", + "teaming_al_uplink_type": "PNIC", + "teaming_sl_uplink_name": "t-uplink-name4", + "teaming_sl_uplink_type": "PNIC", + "teaming_policy": "FAILOVER_ORDER", + "named_teaming_name": "nt-name", + "named_teaming_al_uplink_name": "nt-uplink-name3", + "named_teaming_al_uplink_type": "PNIC", + "named_teaming_sl_uplink_name": "nt-uplink-name4", + "named_teaming_sl_uplink_type": "PNIC", + "named_teaming_policy": "FAILOVER_ORDER", +} + +func TestAccResourceNsxtUplinkHostSwitchProfile_basic(t *testing.T) { + testResourceName := "nsxt_uplink_host_switch_profile.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccOnlyLocalManager(t) + testAccPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: func(state *terraform.State) error { + return testAccNsxtUplinkHostSwitchProfileCheckDestroy(state, accTestUplinkHostSwitchProfileUpdateAttributes["display_name"]) + }, + Steps: []resource.TestStep{ + { + Config: testAccNsxtUplinkHostSwitchProfileTemplate(true), + Check: resource.ComposeTestCheckFunc( + testAccNsxtUplinkHostSwitchProfileExists(accTestUplinkHostSwitchProfileCreateAttributes["display_name"], testResourceName), + resource.TestCheckResourceAttr(testResourceName, "display_name", accTestUplinkHostSwitchProfileCreateAttributes["display_name"]), + resource.TestCheckResourceAttr(testResourceName, "description", accTestUplinkHostSwitchProfileCreateAttributes["description"]), + + resource.TestCheckResourceAttr(testResourceName, "mtu", accTestUplinkHostSwitchProfileCreateAttributes["mtu"]), + resource.TestCheckResourceAttr(testResourceName, "overlay_encap", accTestUplinkHostSwitchProfileCreateAttributes["overlay_encap"]), + resource.TestCheckResourceAttr(testResourceName, "transport_vlan", accTestUplinkHostSwitchProfileCreateAttributes["transport_vlan"]), + + resource.TestCheckResourceAttr(testResourceName, "lag.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "lag.0.load_balance_algorithm", accTestUplinkHostSwitchProfileCreateAttributes["lag_load_balance_algorithm"]), + resource.TestCheckResourceAttr(testResourceName, "lag.0.mode", accTestUplinkHostSwitchProfileCreateAttributes["lag_mode"]), + resource.TestCheckResourceAttr(testResourceName, "lag.0.name", accTestUplinkHostSwitchProfileCreateAttributes["lag_name"]), + resource.TestCheckResourceAttr(testResourceName, "lag.0.number_of_uplinks", accTestUplinkHostSwitchProfileCreateAttributes["lag_number_of_uplinks"]), + resource.TestCheckResourceAttr(testResourceName, "lag.0.timeout_type", accTestUplinkHostSwitchProfileCreateAttributes["lag_timeout_type"]), + + resource.TestCheckResourceAttr(testResourceName, "teaming.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.active.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.active.0.uplink_name", accTestUplinkHostSwitchProfileCreateAttributes["teaming_al_uplink_name"]), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.active.0.uplink_type", accTestUplinkHostSwitchProfileCreateAttributes["teaming_al_uplink_type"]), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.standby.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.standby.0.uplink_name", accTestUplinkHostSwitchProfileCreateAttributes["teaming_sl_uplink_name"]), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.standby.0.uplink_type", accTestUplinkHostSwitchProfileCreateAttributes["teaming_sl_uplink_type"]), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.policy", accTestUplinkHostSwitchProfileCreateAttributes["teaming_policy"]), + + resource.TestCheckResourceAttr(testResourceName, "named_teaming.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.active.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.active.0.uplink_name", accTestUplinkHostSwitchProfileCreateAttributes["named_teaming_al_uplink_name"]), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.active.0.uplink_type", accTestUplinkHostSwitchProfileCreateAttributes["named_teaming_al_uplink_type"]), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.standby.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.standby.0.uplink_name", accTestUplinkHostSwitchProfileCreateAttributes["named_teaming_sl_uplink_name"]), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.standby.0.uplink_type", accTestUplinkHostSwitchProfileCreateAttributes["named_teaming_sl_uplink_type"]), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.policy", accTestUplinkHostSwitchProfileCreateAttributes["named_teaming_policy"]), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.name", accTestUplinkHostSwitchProfileCreateAttributes["named_teaming_name"]), + + resource.TestCheckResourceAttrSet(testResourceName, "nsx_id"), + resource.TestCheckResourceAttrSet(testResourceName, "path"), + resource.TestCheckResourceAttrSet(testResourceName, "revision"), + resource.TestCheckResourceAttr(testResourceName, "tag.#", "1"), + ), + }, + { + Config: testAccNsxtUplinkHostSwitchProfileTemplate(false), + Check: resource.ComposeTestCheckFunc( + testAccNsxtUplinkHostSwitchProfileExists(accTestUplinkHostSwitchProfileUpdateAttributes["display_name"], testResourceName), + resource.TestCheckResourceAttr(testResourceName, "display_name", accTestUplinkHostSwitchProfileUpdateAttributes["display_name"]), + resource.TestCheckResourceAttr(testResourceName, "description", accTestUplinkHostSwitchProfileUpdateAttributes["description"]), + + resource.TestCheckResourceAttr(testResourceName, "mtu", accTestUplinkHostSwitchProfileUpdateAttributes["mtu"]), + resource.TestCheckResourceAttr(testResourceName, "overlay_encap", accTestUplinkHostSwitchProfileUpdateAttributes["overlay_encap"]), + resource.TestCheckResourceAttr(testResourceName, "transport_vlan", accTestUplinkHostSwitchProfileUpdateAttributes["transport_vlan"]), + + resource.TestCheckResourceAttr(testResourceName, "lag.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "lag.0.load_balance_algorithm", accTestUplinkHostSwitchProfileUpdateAttributes["lag_load_balance_algorithm"]), + resource.TestCheckResourceAttr(testResourceName, "lag.0.mode", accTestUplinkHostSwitchProfileUpdateAttributes["lag_mode"]), + resource.TestCheckResourceAttr(testResourceName, "lag.0.name", accTestUplinkHostSwitchProfileUpdateAttributes["lag_name"]), + resource.TestCheckResourceAttr(testResourceName, "lag.0.number_of_uplinks", accTestUplinkHostSwitchProfileUpdateAttributes["lag_number_of_uplinks"]), + resource.TestCheckResourceAttr(testResourceName, "lag.0.timeout_type", accTestUplinkHostSwitchProfileUpdateAttributes["lag_timeout_type"]), + + resource.TestCheckResourceAttr(testResourceName, "teaming.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.active.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.active.0.uplink_name", accTestUplinkHostSwitchProfileUpdateAttributes["teaming_al_uplink_name"]), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.active.0.uplink_type", accTestUplinkHostSwitchProfileUpdateAttributes["teaming_al_uplink_type"]), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.standby.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.standby.0.uplink_name", accTestUplinkHostSwitchProfileUpdateAttributes["teaming_sl_uplink_name"]), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.standby.0.uplink_type", accTestUplinkHostSwitchProfileUpdateAttributes["teaming_sl_uplink_type"]), + resource.TestCheckResourceAttr(testResourceName, "teaming.0.policy", accTestUplinkHostSwitchProfileUpdateAttributes["teaming_policy"]), + + resource.TestCheckResourceAttr(testResourceName, "named_teaming.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.active.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.active.0.uplink_name", accTestUplinkHostSwitchProfileUpdateAttributes["named_teaming_al_uplink_name"]), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.active.0.uplink_type", accTestUplinkHostSwitchProfileUpdateAttributes["named_teaming_al_uplink_type"]), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.standby.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.standby.0.uplink_name", accTestUplinkHostSwitchProfileUpdateAttributes["named_teaming_sl_uplink_name"]), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.standby.0.uplink_type", accTestUplinkHostSwitchProfileUpdateAttributes["named_teaming_sl_uplink_type"]), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.policy", accTestUplinkHostSwitchProfileUpdateAttributes["named_teaming_policy"]), + resource.TestCheckResourceAttr(testResourceName, "named_teaming.0.name", accTestUplinkHostSwitchProfileUpdateAttributes["named_teaming_name"]), + + resource.TestCheckResourceAttrSet(testResourceName, "nsx_id"), + resource.TestCheckResourceAttrSet(testResourceName, "path"), + resource.TestCheckResourceAttrSet(testResourceName, "revision"), + resource.TestCheckResourceAttr(testResourceName, "tag.#", "1"), + ), + }, + { + Config: testAccNsxtUplinkHostSwitchProfileMinimalistic(), + Check: resource.ComposeTestCheckFunc( + testAccNsxtUplinkHostSwitchProfileExists(accTestUplinkHostSwitchProfileCreateAttributes["display_name"], testResourceName), + resource.TestCheckResourceAttr(testResourceName, "description", ""), + resource.TestCheckResourceAttrSet(testResourceName, "nsx_id"), + resource.TestCheckResourceAttrSet(testResourceName, "path"), + resource.TestCheckResourceAttrSet(testResourceName, "revision"), + resource.TestCheckResourceAttr(testResourceName, "tag.#", "0"), + + resource.TestCheckNoResourceAttr(testResourceName, "lag.#"), + resource.TestCheckNoResourceAttr(testResourceName, "named_teaming.#"), + resource.TestCheckNoResourceAttr(testResourceName, "teaming.0.standby.#"), + resource.TestCheckResourceAttr(testResourceName, "mtu", "1700"), + resource.TestCheckResourceAttr(testResourceName, "overlay_encap", "GENEVE"), + resource.TestCheckResourceAttr(testResourceName, "transport_vlan", "0"), + ), + }, + }, + }) +} + +func TestAccResourceNsxtUplinkHostSwitchProfile_importBasic(t *testing.T) { + testResourceName := "nsxt_uplink_host_switch_profile.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccOnlyLocalManager(t) + testAccPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: func(state *terraform.State) error { + return testAccNsxtUplinkHostSwitchProfileCheckDestroy(state, accTestUplinkHostSwitchProfileUpdateAttributes["display_name"]) + }, + Steps: []resource.TestStep{ + { + Config: testAccNsxtUplinkHostSwitchProfileMinimalistic(), + }, + { + ResourceName: testResourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccNsxtUplinkHostSwitchProfileExists(displayName string, resourceName string) resource.TestCheckFunc { + return func(state *terraform.State) error { + + connector := getPolicyConnector(testAccProvider.Meta().(nsxtClients)) + + rs, ok := state.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("UplinkHostSwitchProfile resource %s not found in resources", resourceName) + } + + resourceID := rs.Primary.ID + if resourceID == "" { + return fmt.Errorf("UplinkHostSwitchProfile resource ID not set in resources") + } + + exists, err := resourceNsxtUplinkHostSwitchProfileExists(resourceID, connector, testAccIsGlobalManager()) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("UplinkHostSwitchProfile %s does not exist", resourceID) + } + + return nil + } +} + +func testAccNsxtUplinkHostSwitchProfileCheckDestroy(state *terraform.State, displayName string) error { + connector := getPolicyConnector(testAccProvider.Meta().(nsxtClients)) + for _, rs := range state.RootModule().Resources { + + if rs.Type != "nsxt_policy_uplink_host_switch_profile" { + continue + } + + resourceID := rs.Primary.Attributes["id"] + exists, err := resourceNsxtUplinkHostSwitchProfileExists(resourceID, connector, testAccIsGlobalManager()) + if err == nil { + return err + } + + if exists { + return fmt.Errorf("UplinkHostSwitchProfile %s still exists", displayName) + } + } + return nil +} + +func testAccNsxtUplinkHostSwitchProfileTemplate(createFlow bool) string { + var attrMap map[string]string + if createFlow { + attrMap = accTestUplinkHostSwitchProfileCreateAttributes + } else { + attrMap = accTestUplinkHostSwitchProfileUpdateAttributes + } + return fmt.Sprintf(` +resource "nsxt_uplink_host_switch_profile" "test" { + display_name = "%s" + description = "%s" + + mtu = %s + transport_vlan = %s + overlay_encap = "%s" + lag { + name = "%s" + load_balance_algorithm = "%s" + mode = "%s" + number_of_uplinks = %s + timeout_type = "%s" + } + teaming { + active { + uplink_name = "%s" + uplink_type = "%s" + } + standby { + uplink_name = "%s" + uplink_type = "%s" + } + policy = "%s" + } + named_teaming { + active { + uplink_name = "%s" + uplink_type = "%s" + } + standby { + uplink_name = "%s" + uplink_type = "%s" + } + policy = "%s" + name = "%s" + } + + tag { + scope = "scope1" + tag = "tag1" + } +} + +data "nsxt_uplink_host_switch_profile" "test" { + display_name = "%s" + depends_on = [nsxt_uplink_host_switch_profile.test] +}`, attrMap["display_name"], attrMap["description"], attrMap["mtu"], attrMap["transport_vlan"], attrMap["overlay_encap"], attrMap["lag_name"], attrMap["lag_load_balance_algorithm"], attrMap["lag_mode"], attrMap["lag_number_of_uplinks"], attrMap["lag_timeout_type"], attrMap["teaming_al_uplink_name"], attrMap["teaming_al_uplink_type"], attrMap["teaming_sl_uplink_name"], attrMap["teaming_sl_uplink_type"], attrMap["teaming_policy"], attrMap["named_teaming_al_uplink_name"], attrMap["named_teaming_al_uplink_type"], attrMap["named_teaming_sl_uplink_name"], attrMap["named_teaming_sl_uplink_type"], attrMap["named_teaming_policy"], attrMap["named_teaming_name"], attrMap["display_name"]) +} + +func testAccNsxtUplinkHostSwitchProfileMinimalistic() string { + return fmt.Sprintf(` +resource "nsxt_uplink_host_switch_profile" "test" { + display_name = "%s" + teaming { + active { + uplink_name = "%s" + uplink_type = "%s" + } + policy = "%s" + } +}`, accTestUplinkHostSwitchProfileUpdateAttributes["display_name"], accTestUplinkHostSwitchProfileUpdateAttributes["teaming_al_uplink_name"], accTestUplinkHostSwitchProfileUpdateAttributes["teaming_al_uplink_type"], accTestUplinkHostSwitchProfileUpdateAttributes["teaming_policy"]) +} diff --git a/website/docs/d/uplink_host_switch_profile.markdown b/website/docs/d/uplink_host_switch_profile.markdown new file mode 100644 index 000000000..9ee74d5eb --- /dev/null +++ b/website/docs/d/uplink_host_switch_profile.markdown @@ -0,0 +1,31 @@ +--- +subcategory: "Fabric" +layout: "nsxt" +page_title: "NSXT: nsxt_uplink_host_switch_profile" +description: A host switch profile data source. +--- + +# nsxt_uplink_host_switch_profile + +This data source provides information about uplink host switch profile configured on NSX. +This data source is applicable to NSX Policy Manager. + +## Example Usage + +```hcl +data "nsxt_uplink_host_switch_profile" "uplink_host_switch_profile" { + display_name = "uplink_host_switch_profile1" +} +``` + +## Argument Reference + +* `id` - (Optional) The ID of uplink host switch profile to retrieve. +* `display_name` - (Optional) The Display Name prefix of the uplink host switch profile to retrieve. + +## Attributes Reference + +In addition to arguments listed above, the following attributes are exported: + +* `description` - The description of the resource. +* `path` - The NSX path of the policy resource. diff --git a/website/docs/r/policy_vni_pool.html.markdown b/website/docs/r/policy_vni_pool.html.markdown index fc50b95e0..85d9f61fb 100644 --- a/website/docs/r/policy_vni_pool.html.markdown +++ b/website/docs/r/policy_vni_pool.html.markdown @@ -64,4 +64,4 @@ The above command imports the VNI Pool named `vnipool1` with the NSX Policy ID ` terraform import nsxt_policy_vni_pool.vnipool1 POLICY_PATH ``` The above command imports the VNI pool named `vnipool1` with the policy path `POLICY_PATH`. -Note: for multitenancy projects only the later form is usable. \ No newline at end of file +Note: for multitenancy projects only the later form is usable. diff --git a/website/docs/r/uplink_host_switch_profile.html.markdown b/website/docs/r/uplink_host_switch_profile.html.markdown new file mode 100644 index 000000000..1f30f5aec --- /dev/null +++ b/website/docs/r/uplink_host_switch_profile.html.markdown @@ -0,0 +1,129 @@ +--- +subcategory: "Fabric" +layout: "nsxt" +page_title: "NSXT: nsxt_uplink_host_switch_profile" +description: A resource to configure a uplink host switch profile in NSX Policy. +--- + +# nsxt_uplink_host_switch_profile + +This resource provides a method for the management of a uplink host switch profile which can be used within NSX Policy. + +This resource is applicable to NSX Policy Manager. + +## Example Usage + +```hcl +resource "nsxt_uplink_host_switch_profile" "uplink_host_switch_profile" { + description = "Uplink host switch profile provisioned by Terraform" + display_name = "uplink_host_switch_profile" + + mtu = 1500 + transport_vlan = 0 + overlay_encap = "GENEVE" + lag { + name = "t_created_lag" + load_balance_algorithm = "SRCDESTIPVLAN" + mode = "ACTIVE" + number_of_uplinks = 2 + timeout_type = "SLOW" + } + teaming { + active { + uplink_name = "t1" + uplink_type = "PNIC" + } + standby { + uplink_name = "t2" + uplink_type = "LAG" + } + policy = "FAILOVER_ORDER" + } + named_teaming { + active { + uplink_name = "nt1" + uplink_type = "PNIC" + } + standby { + uplink_name = "nt2" + uplink_type = "PNIC" + } + policy = "FAILOVER_ORDER" + name = "named_teaming1" + } + named_teaming { + active { + uplink_name = "nt3" + uplink_type = "PNIC" + } + policy = "LOADBALANCE_SRCID" + name = "named_teaming2" + } + + tag { + scope = "color" + tag = "blue" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `display_name` - (Required) Display name of the resource. +* `description` - (Optional) Description of the resource. +* `tag` - (Optional) A list of scope + tag pairs to associate with this resource. +* `nsx_id` - (Optional) The NSX ID of this resource. If set, this ID will be used to create the resource. +* `mtu` - (Optional) Maximum Transmission Unit used for uplinks. Minimum: 1280. +* `transport_vlan` - (Optional) VLAN used for tagging Overlay traffic of associated HostSwitch. Default: 0. +* `overlay_encap` - (Optional) The protocol used to encapsulate overlay traffic. Possible values are: `VXLAN`, `GENEVE`. Default: `GENEVE`. +* `lag` - (Optional) List of LACP group. + * `load_balance_algorithm` - (Required) LACP load balance Algorithm. Possible values are: `SRCMAC`, `DESTMAC`, `SRCDESTMAC`, `SRCDESTIPVLAN`, `SRCDESTMACIPPORT`. + * `mode` - (Required) LACP group mode. Possible values are: `ACTIVE`, `PASSIVE`. + * `name` - (Required) Lag name. + * `number_of_uplinks` - (Required) Number of uplinks. Minimum: 2, maximum: 32. + * `timeout_type` - (Optional) LACP timeout type. Possible values are: `SLOW`, `FAST`. Default: `SLOW`. +* `teaming` - (Required) Default TeamingPolicy associated with this UplinkProfile. + * `active` - (Required) List of Uplinks used in active list. + * `uplink_name` - (Required) Name of this uplink. + * `uplink_type` - (Required) Type of the uplink. Possible values are: `PNIC`, `LAG`. + * `policy` - (Required) Teaming policy. Possible values are: `FAILOVER_ORDER`, `LOADBALANCE_SRCID`, `LOADBALANCE_SRC_MAC`. + * `standby` - (Optional) List of Uplinks used in standby list. + * `uplink_name` - (Required) Name of this uplink. + * `uplink_type` - (Required) Type of the uplink. Possible values are: `PNIC`, `LAG`. +* `named_teaming` - (Optional) List of named uplink teaming policies that can be used by logical switches. + * `active` - (Required) List of Uplinks used in active list. + * `uplink_name` - (Required) Name of this uplink. + * `uplink_type` - (Required) Type of the uplink. Possible values are: `PNIC`, `LAG`. + * `policy` - (Required) Teaming policy. Possible values are: `FAILOVER_ORDER`, `LOADBALANCE_SRCID`, `LOADBALANCE_SRC_MAC`. + * `standby` - (Optional) List of Uplinks used in standby list. + * `uplink_name` - (Required) Name of this uplink. + * `uplink_type` - (Required) Type of the uplink. Possible values are: `PNIC`, `LAG`. + * `name` - (Optional) An uplink teaming policy of a given name defined in UplinkHostSwitchProfile. The names of all NamedTeamingPolicies in an UplinkHostSwitchProfile must be different, but a name can be shared by different UplinkHostSwitchProfiles. Different TransportNodes can use different NamedTeamingPolicies having the same name in different UplinkHostSwitchProfiles to realize an uplink teaming policy on a logical switch. An uplink teaming policy on a logical switch can be any policy defined by a user; it does not have to be a single type of FAILOVER or LOADBALANCE. It can be a combination of types, for instance, a user can define a policy with name `MyHybridTeamingPolicy` as `FAILOVER on all ESX TransportNodes and LOADBALANCE on all KVM TransportNodes`. + +## Attributes Reference + +In addition to arguments listed above, the following attributes are exported: + +* `id` - ID of the resource. +* `revision` - Indicates current revision number of the object as seen by NSX-T API server. This attribute can be useful for debugging. +* `path` - The NSX path of the policy resource. + +## Importing + +An existing object can be [imported][docs-import] into this resource, via the following command: + +[docs-import]: https://www.terraform.io/cli/import + +``` +terraform import nsxt_uplink_host_switch_profile.uplink_host_switch_profile UUID +``` + +The above command imports UplinkHostSwitchProfile named `uplink_host_switch_profile` with the NSX ID `UUID`. + + +``` +terraform import nsxt_uplink_host_switch_profile.uplink_host_switch_profile POLICY_PATH +``` +The above command imports the uplink host switch profile named `uplink_host_switch_profile` with policy path `POLICY_PATH`.