Skip to content

Commit

Permalink
Affinity rules (#313)
Browse files Browse the repository at this point in the history
* update staticcheck
* Implement VM affinity rules
* Update CHANGELOG
  • Loading branch information
dataclouder authored Jun 23, 2020
1 parent 0b9c970 commit 17e533a
Show file tree
Hide file tree
Showing 14 changed files with 1,045 additions and 35 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
Active Directory Federations Services (ADFS) as IdP using WS-TRUST auth endpoint
"/adfs/services/trust/13/usernamemixed"
[#304](https://github.com/vmware/go-vcloud-director/pull/304)
* Implemented VM affinity rules CRUD: `vdc.CreateVmAffinityRuleAsync`, `vdc. CreateVmAffinityRule`, `vdc.GetAllVmAffinityRuleList`, `vdc.GetVmAffinityRuleList`, `vdc.GetVmAntiAffinityRuleList`
`vdc.GetVmAffinityRuleByHref`, `vdc.GetVmAffinityRulesByName`, `vdc.GetVmAffinityRuleById`, `vdc.GetVmAffinityRuleByNameOrId`, `VmAffinityRule.Delete`, `VmAffinityRule.Update`,
`VmAffinityRule.SetMandatory`, `VmAffinityRule.SetEnabled`, `VmAffinityRule.Refresh` [#313](https://github.com/vmware/go-vcloud-director/pull/313)
* Add method `client.QueryVmList` [#313](https://github.com/vmware/go-vcloud-director/pull/313)
* Add support for group management using `CreateGroup`, `GetGroupByHref`, `GetGroupById`,
`GetGroupByName`, `GetGroupByNameOrId`, `Delete`, `Update`, `NewGroup` functions [#314](https://github.com/vmware/go-vcloud-director/pull/314)
* Add LDAP administration functions for Org `LdapConfigure`, `GetLdapConfiguration`, and `LdapDisable` [#314](https://github.com/vmware/go-vcloud-director/pull/314)
Expand Down
24 changes: 23 additions & 1 deletion govcd/api_vcd_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build api functional catalog vapp gateway network org query extnetwork task vm vdc system disk lb lbAppRule lbAppProfile lbServerPool lbServiceMonitor lbVirtualServer user search nsxv auth ALL
// +build api functional catalog vapp gateway network org query extnetwork task vm vdc system disk lb lbAppRule lbAppProfile lbServerPool lbServiceMonitor lbVirtualServer user search nsxv auth affinity ALL

/*
* Copyright 2019 VMware, Inc. All rights reserved. Licensed under the Apache v2 License.
Expand Down Expand Up @@ -770,6 +770,28 @@ func (vcd *TestVCD) removeLeftoverEntities(entity CleanupEntity) {
vcd.infoCleanup(notDeletedMsg, entity.EntityType, entity.Name, err)
}
return
case "affinity_rule":
_, vdc, err := vcd.getAdminOrgAndVdcFromCleanupEntity(entity)
if err != nil {
vcd.infoCleanup("adminOrg + VDC: %s", err)
return
}
affinityRule, err := vdc.GetVmAffinityRuleById(entity.Name)
if err != nil {
if ContainsNotFound(err) {
vcd.infoCleanup(notFoundMsg, entity.EntityType, entity.Name)
return
} else {
vcd.infoCleanup("retrieving affinity rule %s", err)
return
}
}
err = affinityRule.Delete()
if err != nil {
vcd.infoCleanup("affinity rule deletion: %s", err)
}
return

case "externalNetwork":
externalNetwork, err := vcd.client.GetExternalNetworkByName(entity.Name)
if err != nil {
Expand Down
20 changes: 13 additions & 7 deletions govcd/entity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ func (vm *VM) id() string { return vm.VM.ID }
func (media *Media) name() string { return media.Media.Name }
func (media *Media) id() string { return media.Media.ID }

func (vmar *VmAffinityRule) name() string { return vmar.VmAffinityRule.Name }
func (vmar *VmAffinityRule) id() string { return vmar.VmAffinityRule.ID }

// Semi-generic tests that check the complete set of Get methods for an entity
// GetEntityByName
// GetEntityById
Expand Down Expand Up @@ -134,11 +137,11 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
fmt.Printf("#Testing %s.Get%sByName\n", def.parentType, def.getterPrefix)
}
ge, err := def.getByName(entityName, false)
entity1 := ge.(genericEntity)
if err != nil {
check.Skip(fmt.Sprintf("testFinderGetGenericEntity: %s %s not found.", def.entityType, def.entityName))
return
}
entity1 := ge.(genericEntity)

wantedType := fmt.Sprintf("*govcd.%s", def.entityType)
if testVerbose {
Expand All @@ -156,8 +159,9 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
fmt.Printf("#Testing %s.Get%sById\n", def.parentType, def.getterPrefix)
}
ge, err = def.getById(entityId, false)
entity2 := ge.(genericEntity)
check.Assert(err, IsNil)
check.Assert(ge, NotNil)
entity2 := ge.(genericEntity)
check.Assert(entity2, NotNil)
check.Assert(entity2.name(), Equals, entityName)
check.Assert(entity2.id(), Equals, entityId)
Expand All @@ -168,8 +172,9 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
fmt.Printf("#Testing %s.Get%sByNameOrId\n", def.parentType, def.getterPrefix)
}
ge, err = def.getByNameOrId(entityId, false)
entity3 := ge.(genericEntity)
check.Assert(err, IsNil)
check.Assert(ge, NotNil)
entity3 := ge.(genericEntity)
check.Assert(entity3, NotNil)
check.Assert(entity3.name(), Equals, entityName)
check.Assert(entity3.id(), Equals, entityId)
Expand All @@ -180,6 +185,7 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
fmt.Printf("#Testing %s.Get%sByNameOrId\n", def.parentType, def.getterPrefix)
}
ge, err = def.getByNameOrId(entityName, false)
check.Assert(ge, NotNil)
entity4 := ge.(genericEntity)
check.Assert(err, IsNil)
check.Assert(entity4, NotNil)
Expand All @@ -192,8 +198,8 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
fmt.Printf("#Testing %s.Get%sByName (invalid name)\n", def.parentType, def.getterPrefix)
}
ge, err = def.getByName(INVALID_NAME, false)
entity5 := ge.(genericEntity)
check.Assert(err, NotNil)
entity5 := ge // this is expected to be nil
check.Assert(IsNotFound(err), Equals, true)
check.Assert(entity5, IsNil)

Expand All @@ -202,8 +208,8 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
fmt.Printf("#Testing %s.Get%sByNameOrId (invalid name)\n", def.parentType, def.getterPrefix)
}
ge, err = def.getByNameOrId(INVALID_NAME, false)
entity6 := ge.(genericEntity)
check.Assert(err, NotNil)
entity6 := ge // this is expected to be nil
check.Assert(IsNotFound(err), Equals, true)
check.Assert(entity6, IsNil)

Expand All @@ -212,8 +218,8 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
fmt.Printf("#Testing %s.Get%sById (invalid ID)\n", def.parentType, def.getterPrefix)
}
ge, err = def.getById(invalidEntityId, false)
entity7 := ge.(genericEntity)
check.Assert(err, NotNil)
entity7 := ge // this is expected to be nil
check.Assert(IsNotFound(err), Equals, true)
check.Assert(entity7, IsNil)

Expand All @@ -222,8 +228,8 @@ func (vcd *TestVCD) testFinderGetGenericEntity(def getterTestDefinition, check *
fmt.Printf("#Testing %s.Get%sByNameOrId (invalid ID)\n", def.parentType, def.getterPrefix)
}
ge, err = def.getByNameOrId(invalidEntityId, false)
entity8 := ge.(genericEntity)
check.Assert(err, NotNil)
entity8 := ge // this is expected to be nil
check.Assert(IsNotFound(err), Equals, true)
check.Assert(entity8, IsNil)
}
2 changes: 1 addition & 1 deletion govcd/lb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (vcd *TestVCD) Test_LB(check *C) {
vm2, err := spawnVM("SecondNode", 512, *vdc, *vapp, desiredNetConfig, vappTemplate, check, vm2CustomizationScript)
check.Assert(err, IsNil)

// Get IPs alocated to the VMs
// Get IPs allocated to the VMs
ip1 := vm1.VM.NetworkConnectionSection.NetworkConnection[0].IPAddress
ip2 := vm2.VM.NetworkConnectionSection.NetworkConnection[0].IPAddress

Expand Down
40 changes: 40 additions & 0 deletions govcd/query_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ func queryFieldsOnDemand(queryType string) ([]string, error) {
"isIso", "isVdcEnabled", "taskStatus", "taskDetails"}
catalogItemFields = []string{"entity", "entityName", "entityType", "catalog", "catalogName", "ownerName",
"owner", "isPublished", "vdc", "vdcName", "isVdcEnabled", "creationDate", "isExpired", "status"}
vmFields = []string{"catalogName", "container", "containerName", "datastoreName", "description",
"gcStatus", "guestOs", "hardwareVersion", "hostName", "isAutoNature", "isDeleted", "isDeployed", "isPublished",
"isVAppTemplate", "isVdcEnabled", "memoryMB", "moref", "name", "numberOfCpus", "org", "status",
"storageProfileName", "vc", "vdc", "vmToolsVersion", "containerStatus", "pvdcHighestSupportedHardwareVersion",
}
fieldsOnDemand = map[string][]string{
types.QtVappTemplate: vappTemplatefields,
types.QtAdminVappTemplate: vappTemplatefields,
Expand All @@ -70,6 +75,8 @@ func queryFieldsOnDemand(queryType string) ([]string, error) {
types.QtAdminMedia: mediaFields,
types.QtCatalogItem: catalogItemFields,
types.QtAdminCatalogItem: catalogItemFields,
types.QtVm: vmFields,
types.QtAdminVm: vmFields,
}
)

Expand Down Expand Up @@ -115,6 +122,12 @@ func addResults(queryType string, cumulativeResults, newResults Results) (Result
case types.QtEdgeGateway:
cumulativeResults.Results.EdgeGatewayRecord = append(cumulativeResults.Results.EdgeGatewayRecord, newResults.Results.EdgeGatewayRecord...)
size = len(newResults.Results.EdgeGatewayRecord)
case types.QtVm:
cumulativeResults.Results.VMRecord = append(cumulativeResults.Results.VMRecord, newResults.Results.VMRecord...)
size = len(newResults.Results.VMRecord)
case types.QtAdminVm:
cumulativeResults.Results.AdminVMRecord = append(cumulativeResults.Results.AdminVMRecord, newResults.Results.AdminVMRecord...)
size = len(newResults.Results.AdminVMRecord)

default:
return Results{}, 0, fmt.Errorf("query type %s not supported", queryType)
Expand All @@ -125,6 +138,33 @@ func addResults(queryType string, cumulativeResults, newResults Results) (Result

// cumulativeQuery runs a paginated query and collects all elements until the total number of records is retrieved
func (client *Client) cumulativeQuery(queryType string, params, notEncodedParams map[string]string) (Results, error) {
var supportedQueryTypes = []string{
types.QtVappTemplate,
types.QtAdminVappTemplate,
types.QtEdgeGateway,
types.QtOrgVdcNetwork,
types.QtCatalog,
types.QtAdminCatalog,
types.QtMedia,
types.QtAdminMedia,
types.QtCatalogItem,
types.QtAdminCatalogItem,
types.QtVm,
types.QtAdminVm,
}
// Make sure the query type is supported
// We need to check early, as queries that would return less than 25 items (default page size) would succeed,
// but the check on query type will happen once that threshold is crossed.
isSupported := false
for _, qt := range supportedQueryTypes {
if qt == queryType {
isSupported = true
break
}
}
if !isSupported {
return Results{}, fmt.Errorf("[cumulativeQuery] query type %s not supported", queryType)
}

result, err := client.QueryWithNotEncodedParams(params, notEncodedParams)
if err != nil {
Expand Down
10 changes: 10 additions & 0 deletions govcd/vdc.go
Original file line number Diff line number Diff line change
Expand Up @@ -877,3 +877,13 @@ func (vdc *Vdc) QueryVappVmTemplate(catalogName, vappTemplateName, vmNameInTempl

return vmResults[0], nil
}

// getLinkHref returns a link HREF for a wanted combination of rel and type
func (vdc *Vdc) getLinkHref(rel, linkType string) string {
for _, link := range vdc.Vdc.Link {
if link.Rel == rel && link.Type == linkType {
return link.HREF
}
}
return ""
}
3 changes: 2 additions & 1 deletion govcd/vdc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ package govcd
import (
"fmt"

"github.com/vmware/go-vcloud-director/v2/types/v56"
. "gopkg.in/check.v1"

"github.com/vmware/go-vcloud-director/v2/types/v56"
)

func (vcd *TestVCD) Test_FindVDCNetwork(check *C) {
Expand Down
25 changes: 25 additions & 0 deletions govcd/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1476,3 +1476,28 @@ func (vm *VM) UpdateVmSpecSectionAsync(vmSettingsToUpdate *types.VmSpecSection,
// API version requirements changes through vCD version to access VmSpecSection
}, vm.client.GetSpecificApiVersionOnCondition(">= 32.0", "32.0"))
}

// QueryVmList returns a list of all VMs in all the organizations available to the caller
func (client *Client) QueryVmList(filter types.VmQueryFilter) ([]*types.QueryResultVMRecordType, error) {
var vmList []*types.QueryResultVMRecordType
queryType := types.QtVm
if client.IsSysAdmin {
queryType = types.QtAdminVm
}
params := map[string]string{
"type": queryType,
"filterEncoded": "true",
}
if filter.String() != "" {
params["filter"] = filter.String()
}
vmResult, err := client.cumulativeQuery(queryType, nil, params)
if err != nil {
return nil, fmt.Errorf("error getting VM list : %s", err)
}
vmList = vmResult.Results.VMRecord
if client.IsSysAdmin {
vmList = vmResult.Results.AdminVMRecord
}
return vmList, nil
}
Loading

0 comments on commit 17e533a

Please sign in to comment.