From bc3bd96226331fcfa8c14bd4e068034ce8506dfd Mon Sep 17 00:00:00 2001 From: Xie Zheng Date: Mon, 23 Dec 2024 17:57:14 +0800 Subject: [PATCH] Add StoragePolicy, ContentLibrary, VmServiceSpec when creating VC Namespace --- test/e2e/framework.go | 23 +++++++++++++ test/e2e/vclient.go | 76 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 96 insertions(+), 3 deletions(-) diff --git a/test/e2e/framework.go b/test/e2e/framework.go index 477a14de6..9534b070a 100644 --- a/test/e2e/framework.go +++ b/test/e2e/framework.go @@ -307,17 +307,40 @@ func (data *TestData) createVCNamespace(namespace string) error { }() svID, _ := data.vcClient.getSupervisorID() + storagePolicyID, _ := data.vcClient.getStoragePolicyID() + log.V(1).Info("Get storage policy", "storagePolicyID", storagePolicyID) + contentLibraryID, _ := data.vcClient.getContentLibraryID() + log.V(1).Info("Get content library", "contentLibraryID", contentLibraryID) vcNamespace := &VCNamespaceCreateSpec{ Supervisor: svID, Namespace: namespace, + StorageSpecs: []InstancesStorageSpec{ + { + Policy: storagePolicyID, + }, + }, + ContentLibraries: []InstancesContentLibrarySpec{ + { + ContentLibrary: contentLibraryID, + }, + }, NetworkSpec: InstancesNetworkConfigInfo{ NetworkProvider: "NSX_VPC", VpcNetwork: InstancesVpcNetworkInfo{ DefaultSubnetSize: 16, }, }, + VmServiceSpec: &InstancesVMServiceSpec{ + ContentLibraries: map[string]bool{ + contentLibraryID: true, + }, + VmClasses: map[string]bool{ + "best-effort-xsmall": true, + }, + }, } dataJson, err := json.Marshal(vcNamespace) + log.V(1).Info("Data json", "dataJson", string(dataJson)) if err != nil { log.Error(err, "Unable convert vcNamespace object to json bytes", "namespace", namespace) return fmt.Errorf("unable convert vcNamespace object to json bytes: %v", err) diff --git a/test/e2e/vclient.go b/test/e2e/vclient.go index 0f47194bd..3d068da81 100644 --- a/test/e2e/vclient.go +++ b/test/e2e/vclient.go @@ -8,6 +8,7 @@ import ( "io" "net/http" "net/url" + "strings" "sync" "time" @@ -27,6 +28,12 @@ type supervisorInfo struct { K8sStatus string `json:"kubernetes_status"` } +type storagePolicyInfo struct { + Name string `json:"name"` + Description string `json:"description"` + Policy string `json:"policy"` +} + type supervisorSummary struct { ID string `json:"supervisor"` Info supervisorInfo `json:"info"` @@ -52,10 +59,29 @@ type InstancesNetworkConfigInfo struct { VpcNetwork InstancesVpcNetworkInfo `json:"vpc_network"` } +type InstancesStorageSpec struct { + Policy string `json:"policy"` + Limit *int64 `json:"limit"` +} + +type InstancesContentLibrarySpec struct { + ContentLibrary string `json:"content_library"` + Writable *bool `json:"writable"` + AllowImport *bool `json:"allow_import"` +} + +type InstancesVMServiceSpec struct { + ContentLibraries map[string]bool `json:"content_libraries"` + VmClasses map[string]bool `json:"vm_classes"` +} + type VCNamespaceCreateSpec struct { - Supervisor string `json:"supervisor"` - Namespace string `json:"namespace"` - NetworkSpec InstancesNetworkConfigInfo `json:"network_spec"` + Supervisor string `json:"supervisor"` + Namespace string `json:"namespace"` + NetworkSpec InstancesNetworkConfigInfo `json:"network_spec"` + StorageSpecs []InstancesStorageSpec `json:"storage_specs"` + ContentLibraries []InstancesContentLibrarySpec `json:"content_libraries"` + VmServiceSpec *InstancesVMServiceSpec `json:"vm_service_specs"` } type VCNamespaceGetInfo struct { @@ -143,6 +169,7 @@ func (c *vcClient) getSupervisorID() (string, error) { } for _, sv := range response.Items { + log.Info("Checking supervisor", "supervisor", sv.Info.Name, "status", sv.Info.ConfigStatus) if sv.Info.ConfigStatus == "RUNNING" { return sv.ID, nil } @@ -150,6 +177,48 @@ func (c *vcClient) getSupervisorID() (string, error) { return "", fmt.Errorf("no valid supervisor found on vCenter") } +func (c *vcClient) getStoragePolicyID() (string, error) { + urlPath := "/api/vcenter/storage/policies" + request, err := c.prepareRequest(http.MethodGet, urlPath, nil) + if err != nil { + return "", err + } + // response is a list of storage policy info + var response []storagePolicyInfo + if _, err = c.handleRequest(request, &response); err != nil { + return "", err + } + + for _, po := range response { + log.Info("Checking storage policy", "policy", po.Name, "description", po.Description) + if strings.Contains(po.Name, "global") || strings.Contains(po.Name, "local") { + return po.Name, nil + } + } + return "", fmt.Errorf("no valid storage policy found on vCenter") +} + +// Get the first content library ID by default +func (c *vcClient) getContentLibraryID() (string, error) { + urlPath := "/api/content/library" + request, err := c.prepareRequest(http.MethodGet, urlPath, nil) + if err != nil { + return "", err + } + var response []string + if _, err = c.handleRequest(request, &response); err != nil { + return "", err + } + + for _, cl := range response { + log.Info("Checking content library", "content library", cl) + if cl != "" { + return cl, nil + } + } + return "", fmt.Errorf("no valid content library found on vCenter") +} + func (c *vcClient) createNamespaceWithPreCreatedVPC(namespace string, vpcPath string, supervisorID string) error { vcNamespace := createVCNamespaceSpec(namespace, supervisorID, vpcPath) data, err := json.Marshal(vcNamespace) @@ -208,6 +277,7 @@ func createVCNamespaceSpec(namespace string, svID string, vpcPath string) *VCNam func (c *vcClient) prepareRequest(method string, urlPath string, data []byte) (*http.Request, error) { url := fmt.Sprintf("%s://%s%s", c.url.Scheme, c.url.Host, urlPath) + log.Info("Requesting", "url", url) req, err := http.NewRequest(method, url, bytes.NewBuffer(data)) if err != nil { return nil, err