Skip to content

Commit

Permalink
Use search API for pulling VM on latest nsx
Browse files Browse the repository at this point in the history
Since 4.1.2, search API works for inventory objects, this change
uses it instead of listing all VMs, dependant of NSX version.
For older versions, previous codepath is used.
Signed-off-by: Anna Khmelnitsky <akhmelnitsky@vmware.com>
  • Loading branch information
annakhm committed Apr 24, 2024
1 parent 0841c98 commit 1a18756
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 31 deletions.
1 change: 0 additions & 1 deletion nsxt/data_source_nsxt_policy_vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ func dataSourceNsxtPolicyVMIDRead(d *schema.ResourceData, m interface{}) error {
var vmModel model.VirtualMachine
connector := getPolicyConnector(m)

// TODO: test with KVM based VM
objID := getNsxtPolicyVMIDFromSchema(d)
context := getSessionContext(d, m)
if objID != "" {
Expand Down
44 changes: 19 additions & 25 deletions nsxt/policy_search.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ func listPolicyResourcesByNameAndType(connector client.Connector, context utl.Se
return nil, errors.New("invalid ClientType %d")
}

func listInventoryResourcesByNameAndType(connector client.Connector, context utl.SessionContext, displayName string, resourceType string, additionalQuery *string) ([]*data.StructValue, error) {
query := fmt.Sprintf("resource_type:%s AND display_name:%s*", resourceType, escapeSpecialCharacters(displayName))
return searchLM(connector, *buildPolicyResourcesQuery(&query, additionalQuery))
}

func listInventoryResourcesByAnyFieldAndType(connector client.Connector, context utl.SessionContext, anyField string, resourceType string, additionalQuery *string) ([]*data.StructValue, error) {
query := fmt.Sprintf("resource_type:%s AND %s", resourceType, escapeSpecialCharacters(anyField))
return searchLM(connector, *buildPolicyResourcesQuery(&query, additionalQuery))
}

func escapeSpecialCharacters(str string) string {
// we replace special characters that can be encountered in object IDs
specials := "()[]+-=&|><!{}^~*?:/"
Expand Down Expand Up @@ -201,15 +211,12 @@ func searchGMPolicyResources(connector client.Connector, query string) ([]*data.
}
}

func searchLMPolicyResources(connector client.Connector, query string) ([]*data.StructValue, error) {
func searchLM(connector client.Connector, query string) ([]*data.StructValue, error) {
client := lm_search.NewQueryClient(connector)
var results []*data.StructValue
var cursor *string
total := 0

// Make sure global objects are not found (path needs to start with infra)
query = query + " AND path:\\/infra*"

for {
searchResponse, err := client.List(query, cursor, nil, nil, nil, nil)
if err != nil {
Expand All @@ -227,27 +234,14 @@ func searchLMPolicyResources(connector client.Connector, query string) ([]*data.
}
}

func searchMultitenancyPolicyResources(connector client.Connector, org string, project string, query string) ([]*data.StructValue, error) {
client := lm_search.NewQueryClient(connector)
var results []*data.StructValue
var cursor *string
total := 0
func searchLMPolicyResources(connector client.Connector, query string) ([]*data.StructValue, error) {
// Make sure global objects are not found (path needs to start with infra)
query = query + " AND path:\\/infra*"

query = query + fmt.Sprintf(" AND path:\\/orgs\\/%s\\/projects\\/%s*", org, project)
return searchLM(connector, query)
}

for {
searchResponse, err := client.List(query, cursor, nil, nil, nil, nil)
if err != nil {
return results, err
}
results = append(results, searchResponse.Results...)
if total == 0 {
// first response
total = int(*searchResponse.ResultCount)
}
cursor = searchResponse.Cursor
if len(results) >= total {
return results, nil
}
}
func searchMultitenancyPolicyResources(connector client.Connector, org string, project string, query string) ([]*data.StructValue, error) {
query = query + fmt.Sprintf(" AND path:\\/orgs\\/%s\\/projects\\/%s*", org, project)
return searchLM(connector, query)
}
54 changes: 49 additions & 5 deletions nsxt/resource_nsxt_policy_vm_tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/vmware/terraform-provider-nsxt/api/infra/segments"
t1_segments "github.com/vmware/terraform-provider-nsxt/api/infra/tier_1s/segments"
utl "github.com/vmware/terraform-provider-nsxt/api/utl"
"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/realized_state/enforcement_points"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/realized_state/virtual_machines"
Expand Down Expand Up @@ -162,11 +164,24 @@ func listAllPolicyVifs(m interface{}) ([]model.VirtualNetworkInterface, error) {
}

func findNsxtPolicyVMByNamePrefix(context utl.SessionContext, connector client.Connector, namePrefix string, m interface{}) ([]model.VirtualMachine, []model.VirtualMachine, error) {
var perfectMatch, prefixMatch []model.VirtualMachine
var perfectMatch, prefixMatch, allVMs []model.VirtualMachine
var err error

if nsxVersionHigherOrEqual("4.1.2") {
// Search API works for inventory objects for 4.1.2 and above
resourceType := "VirtualMachine"
resultValues, err1 := listInventoryResourcesByNameAndType(connector, context, namePrefix, resourceType, nil)
if err1 != nil {
log.Printf("[INFO] Error searching for Virtual Machine with name: %s", namePrefix)
return perfectMatch, prefixMatch, err1
}
allVMs, err = convertSearchResultToVMList(resultValues)

allVMs, err := listAllPolicyVirtualMachines(context, connector, m)
} else {
allVMs, err = listAllPolicyVirtualMachines(context, connector, m)
}
if err != nil {
log.Printf("[INFO] Error reading Virtual Machines when looking for name: %s", namePrefix)
log.Printf("[INFO] Error reading Virtual Machine with name: %s", namePrefix)
return perfectMatch, prefixMatch, err
}

Expand All @@ -180,16 +195,45 @@ func findNsxtPolicyVMByNamePrefix(context utl.SessionContext, connector client.C
return perfectMatch, prefixMatch, nil
}

func convertSearchResultToVMList(searchResults []*data.StructValue) ([]model.VirtualMachine, error) {
var vms []model.VirtualMachine
converter := bindings.NewTypeConverter()

for _, item := range searchResults {
dataValue, errors := converter.ConvertToGolang(item, model.VirtualMachineBindingType())
if len(errors) > 0 {
return vms, errors[0]
}
vm := dataValue.(model.VirtualMachine)
vms = append(vms, vm)
}
return vms, nil
}

func findNsxtPolicyVMByID(context utl.SessionContext, connector client.Connector, vmID string, m interface{}) (model.VirtualMachine, error) {
var virtualMachineStruct model.VirtualMachine
var vms []model.VirtualMachine
var err error

allVMs, err := listAllPolicyVirtualMachines(context, connector, m)
if nsxVersionHigherOrEqual("4.1.2") {
// Search API works for inventory objects for 4.1.2 and above
resourceType := "VirtualMachine"
resultValues, err1 := listInventoryResourcesByAnyFieldAndType(connector, context, vmID, resourceType, nil)
if err1 != nil {
log.Printf("[INFO] Error searching for Virtual Machine with id: %s", vmID)
return virtualMachineStruct, err1
}

vms, err = convertSearchResultToVMList(resultValues)
} else {
vms, err = listAllPolicyVirtualMachines(context, connector, m)
}
if err != nil {
log.Printf("[INFO] Error reading Virtual Machines when looking for ID: %s", vmID)
return virtualMachineStruct, err
}

for _, vmResult := range allVMs {
for _, vmResult := range vms {
if (vmResult.ExternalId != nil) && *vmResult.ExternalId == vmID {
return vmResult, nil
}
Expand Down

0 comments on commit 1a18756

Please sign in to comment.