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

Add Vdc Vm compute policies functionality #334

Merged
merged 28 commits into from
Oct 1, 2020
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* Add OVF file upload support in UploadOvf function besides OVA. The input should be OVF file path inside the OVF folder. It will check if input file is XML content type, if yes, skip some OVA steps (like unpacking), if not, keep the old logic. [#323](https://github.com/vmware/go-vcloud-director/pull/323)
* Dropped support for VMware Cloud Director 9.5 [#330](https://github.com/vmware/go-vcloud-director/pull/330)
* Deprecated Vdc.UploadMediaImage because it no longer works with API V32.0+ [#330](https://github.com/vmware/go-vcloud-director/pull/330)
* Add methods `vapp.AddNewVMWithComputePolicy`, `org.GetVdcComputePolicyById`, `adminOrg.GetVdcComputePolicyById`, `org.GetAllVdcComputePolicies`, `adminOrg.GetAllVdcComputePolicies`, `adminOrg.CreateVdcComputePolicy`, `vdcComputePolicy.Update`, `vdcComputePolicy.Delete`, `adminVdc.GetAllAssignedVdcComputePolicies` and `adminVdc.SetAssignedComputePolicies` [#334] (https://github.com/vmware/go-vcloud-director/pull/334)

## 2.8.0 (June 30, 2020)

Expand Down
2 changes: 1 addition & 1 deletion govcd/adminvdc.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ var vdcVersionedFuncsByVcdVersion = map[string]vdcVersionedFuncs{
}

// getVdcVersionedFuncsByVdcVersion is a wrapper function that retrieves the requested versioned VDC function
// When the wanted version does not exist in the map, it returns the highest available one.
// When the wanted version does not exist in the map, it returns the highest available one.
func getVdcVersionedFuncsByVdcVersion(version string) vdcVersionedFuncs {
f, ok := vdcVersionedFuncsByVcdVersion[version]
if ok {
Expand Down
5 changes: 5 additions & 0 deletions govcd/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -642,3 +642,8 @@ func takeIntAddress(x int) *int {
func takeStringPointer(x string) *string {
return &x
}

// takeFloatAddress is a helper that returns the address of an `float64`
func takeFloatAddress(x float64) *float64 {
return &x
}
22 changes: 22 additions & 0 deletions govcd/api_vcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1303,6 +1303,28 @@ func (vcd *TestVCD) removeLeftoverEntities(entity CleanupEntity) {
}
vcd.infoCleanup(removedMsg, entity.EntityType, entity.Name, entity.CreatedBy)
return
case "vcdComputePolicy":
if entity.Parent == "" {
vcd.infoCleanup("removeLeftoverEntries: [ERROR] No ORG provided for vcdComputePolicy '%s'\n", entity.Name)
return
}
org, err := vcd.client.GetAdminOrgByName(entity.Parent)
if err != nil {
vcd.infoCleanup(notFoundMsg, "org", entity.Parent)
return
}
policy, err := org.GetVdcComputePolicyById(entity.Name)
if policy == nil || err != nil {
vcd.infoCleanup(notFoundMsg, "vcdComputePolicy", entity.Name)
return
}
err = policy.Delete()
if err == nil {
vcd.infoCleanup(removedMsg, entity.EntityType, entity.Name, entity.CreatedBy)
} else {
vcd.infoCleanup(notDeletedMsg, entity.EntityType, entity.Name, err)
}
return

default:
// If we reach this point, we are trying to clean up an entity that
Expand Down
4 changes: 3 additions & 1 deletion govcd/openapi_endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (

// endpointMinApiVersions holds mapping of OpenAPI endpoints and API versions they were introduced in.
var endpointMinApiVersions = map[string]string{
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRoles: "31.0",
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointRoles: "31.0",
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcComputePolicies: "32.0",
types.OpenApiPathVersion1_0_0 + types.OpenApiEndpointVdcAssignedComputePolicies: "33.0",
}

// checkOpenApiEndpointCompatibility checks if VCD version (to which the client is connected) is sufficient to work with
Expand Down
52 changes: 31 additions & 21 deletions govcd/vapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,22 @@ func (vapp *VApp) AddNewVM(name string, vappTemplate VAppTemplate, network *type
func (vapp *VApp) AddNewVMWithStorageProfile(name string, vappTemplate VAppTemplate,
network *types.NetworkConnectionSection,
storageProfileRef *types.Reference, acceptAllEulas bool) (Task, error) {
return addNewVMW(vapp, name, vappTemplate, network, storageProfileRef, nil, acceptAllEulas)
}

// AddNewVMWithComputePolicy adds VM from vApp template with custom NetworkConnectionSection and optional storage profile
// and compute policy
func (vapp *VApp) AddNewVMWithComputePolicy(name string, vappTemplate VAppTemplate,
network *types.NetworkConnectionSection,
storageProfileRef *types.Reference, computePolicy *types.VdcComputePolicy, acceptAllEulas bool) (Task, error) {
return addNewVMW(vapp, name, vappTemplate, network, storageProfileRef, computePolicy, acceptAllEulas)
}

// addNewVMW adds VM from vApp template with custom NetworkConnectionSection and optional storage profile
// and optional compute policy
func addNewVMW(vapp *VApp, name string, vappTemplate VAppTemplate,
network *types.NetworkConnectionSection,
storageProfileRef *types.Reference, computePolicy *types.VdcComputePolicy, acceptAllEulas bool) (Task, error) {

if vappTemplate == (VAppTemplate{}) || vappTemplate.VAppTemplate == nil {
return Task{}, fmt.Errorf("vApp Template can not be empty")
Expand Down Expand Up @@ -207,15 +223,28 @@ func (vapp *VApp) AddNewVMWithStorageProfile(name string, vappTemplate VAppTempl
vAppComposition.SourcedItem.StorageProfile = storageProfileRef
}

if computePolicy != nil && vapp.client.APIVCDMaxVersionIs("< 33.0") {
util.Logger.Printf("[Warning] compute policy is ignored because VCD version doesn't support it")
}
// Add compute policy
if computePolicy != nil && computePolicy.ID != "" && vapp.client.APIVCDMaxVersionIs("> 32.0") {
vcdComputePolicyHref, err := vapp.client.OpenApiBuildEndpoint(types.OpenApiPathVersion1_0_0, types.OpenApiEndpointVdcComputePolicies, computePolicy.ID)
if err != nil {
return Task{}, fmt.Errorf("error constructing HREF for compute policy")
}
vAppComposition.SourcedItem.ComputePolicy = &types.ComputePolicy{VmSizingPolicy: &types.Reference{HREF: vcdComputePolicyHref.String()}}
}

// Inject network config
vAppComposition.SourcedItem.InstantiationParams.NetworkConnectionSection = network

apiEndpoint, _ := url.ParseRequestURI(vapp.VApp.HREF)
apiEndpoint.Path += "/action/recomposeVApp"

// Return the task
return vapp.client.ExecuteTaskRequest(apiEndpoint.String(), http.MethodPost,
types.MimeRecomposeVappParams, "error instantiating a new VM: %s", vAppComposition)
return vapp.client.ExecuteTaskRequestWithApiVersion(apiEndpoint.String(), http.MethodPost,
types.MimeRecomposeVappParams, "error instantiating a new VM: %s", vAppComposition,
vapp.client.GetSpecificApiVersionOnCondition(">= 33.0", "33.0"))

}

Expand Down Expand Up @@ -1247,25 +1276,6 @@ func (vapp *VApp) GetProductSectionList() (*types.ProductSectionList, error) {
return getProductSectionList(vapp.client, vapp.VApp.HREF)
}

// GetVMByHref returns a VM reference by running a vCD API call
// If no valid VM is found, it returns a nil VM reference and an error
// Note that the pointer receiver here is a Client instead of a VApp, because
// there are cases where we know the VM HREF but not which VApp it belongs to.
func (client *Client) GetVMByHref(vmHref string) (*VM, error) {

newVm := NewVM(client)

_, err := client.ExecuteRequest(vmHref, http.MethodGet,
"", "error retrieving vm: %s", nil, newVm.VM)

if err != nil {

return nil, err
}

return newVm, nil
}

// GetVMByName returns a VM reference if the VM name matches an existing one.
// If no valid VM is found, it returns a nil VM reference and an error
func (vapp *VApp) GetVMByName(vmName string, refresh bool) (*VM, error) {
Expand Down
119 changes: 119 additions & 0 deletions govcd/vapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1441,3 +1441,122 @@ func (vcd *TestVCD) Test_AddNewVMFromMultiVmTemplate(check *C) {
check.Assert(err, IsNil)
check.Assert(task.Task.Status, Equals, "success")
}

// Test_AddNewVMWithComputeCapacity creates a new VM in vApp with VM using compute capacity
func (vcd *TestVCD) Test_AddNewVMWitComputeCapacity(check *C) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func (vcd *TestVCD) Test_AddNewVMWitComputeCapacity(check *C) {
func (vcd *TestVCD) Test_AddNewVMWithComputeCapacity(check *C) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how this happened, but it is not fixed. Only comment was fixed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:)) ty, pushed one more time.


if vcd.client.Client.APIVCDMaxVersionIs("< 33.0") {
check.Skip(fmt.Sprintf("Test %s requires vCD 10.0 (API version 33) or higher", check.TestName()))
}

if vcd.skipVappTests {
check.Skip("Skipping test because vApp was not successfully created at setup")
}

// Find VApp
if vcd.vapp.VApp == nil {
check.Skip("skipping test because no vApp is found")
}

// Populate Catalog
cat, err := vcd.org.GetCatalogByName(vcd.config.VCD.Catalog.Name, true)
check.Assert(err, IsNil)
check.Assert(cat, NotNil)

// Populate Catalog Item
catitem, err := cat.GetCatalogItemByName(vcd.config.VCD.Catalog.CatalogItem, false)
check.Assert(err, IsNil)
check.Assert(catitem, NotNil)

// Get VAppTemplate
vapptemplate, err := catitem.GetVAppTemplate()
check.Assert(err, IsNil)

vapp, err := createVappForTest(vcd, "Test_AddNewVMWitComputeCapacity")
check.Assert(err, IsNil)
check.Assert(vapp, NotNil)

// Create and assign compute policy
newComputePolicy := &VdcComputePolicy{
client: vcd.org.client,
VdcComputePolicy: &types.VdcComputePolicy{
Name: check.TestName() + "_empty",
Description: "Empty policy created by test",
},
}

adminOrg, err := vcd.client.GetAdminOrgByName(vcd.org.Org.Name)
check.Assert(err, IsNil)
check.Assert(adminOrg, NotNil)

adminVdc, err := adminOrg.GetAdminVDCByName(vcd.vdc.Vdc.Name, false)
if adminVdc == nil || err != nil {
vcd.infoCleanup(notFoundMsg, "vdc", vcd.vdc.Vdc.Name)
}

createdPolicy, err := adminOrg.CreateVdcComputePolicy(newComputePolicy.VdcComputePolicy)
check.Assert(err, IsNil)

AddToCleanupList(createdPolicy.VdcComputePolicy.ID, "vcdComputePolicy", vcd.org.Org.Name, "Test_AddNewEmptyVMWithVmComputePolicy")

vcdComputePolicyHref, err := adminOrg.client.OpenApiBuildEndpoint(types.OpenApiPathVersion1_0_0, types.OpenApiEndpointVdcComputePolicies)
check.Assert(err, IsNil)

// Get policy to existing ones (can be only default one)
allAssignedComputePolicies, err := adminVdc.GetAllAssignedVdcComputePolicies(nil)
check.Assert(err, IsNil)
var policyReferences []*types.Reference
for _, assignedPolicy := range allAssignedComputePolicies {
policyReferences = append(policyReferences, &types.Reference{HREF: vcdComputePolicyHref.String() + assignedPolicy.VdcComputePolicy.ID})
}
policyReferences = append(policyReferences, &types.Reference{HREF: vcdComputePolicyHref.String() + createdPolicy.VdcComputePolicy.ID})

assignedVdcComputePolicies, err := adminVdc.SetAssignedComputePolicies(types.VdcComputePolicyReferences{VdcComputePolicyReference: policyReferences})
check.Assert(err, IsNil)
check.Assert(len(allAssignedComputePolicies)+1, Equals, len(assignedVdcComputePolicies.VdcComputePolicyReference))
// end

var task Task

if testVerbose {
fmt.Printf("Custom storage profile not found. Using AddNewVM\n")
}
task, err = vapp.AddNewVMWithComputePolicy(check.TestName(), vapptemplate, nil, nil, createdPolicy.VdcComputePolicy, true)

check.Assert(err, IsNil)

err = task.WaitTaskCompletion()
check.Assert(err, IsNil)
check.Assert(task.Task.Status, Equals, "success")

createdVm, err := vapp.GetVMByName(check.TestName(), true)
check.Assert(err, IsNil)

check.Assert(createdVm.VM.ComputePolicy, NotNil)
check.Assert(createdVm.VM.ComputePolicy.VmSizingPolicy, NotNil)
check.Assert(createdVm.VM.ComputePolicy.VmSizingPolicy.ID, Equals, createdPolicy.VdcComputePolicy.ID)

// Cleanup
err = vapp.RemoveVM(*createdVm)
check.Assert(err, IsNil)

// Ensure network is detached from vApp to avoid conflicts in other tests
task, err = vapp.RemoveAllNetworks()
check.Assert(err, IsNil)
err = task.WaitTaskCompletion()
check.Assert(err, IsNil)
task, err = vapp.Delete()
check.Assert(err, IsNil)
err = task.WaitTaskCompletion()
check.Assert(err, IsNil)
check.Assert(task.Task.Status, Equals, "success")

// cleanup assigned compute policy
var beforeTestPolicyReferences []*types.Reference
for _, assignedPolicy := range allAssignedComputePolicies {
beforeTestPolicyReferences = append(beforeTestPolicyReferences, &types.Reference{HREF: vcdComputePolicyHref.String() + assignedPolicy.VdcComputePolicy.ID})
}

_, err = adminVdc.SetAssignedComputePolicies(types.VdcComputePolicyReferences{VdcComputePolicyReference: beforeTestPolicyReferences})
check.Assert(err, IsNil)
}
Loading