From 5abdb3ce9032f1a1de93f216199f4206b8255400 Mon Sep 17 00:00:00 2001 From: Itzik Brown Date: Sun, 1 Dec 2024 13:45:48 +0000 Subject: [PATCH] [OCPBUGS-45069] Add a check for manila share type If the share type extra spec of driver_handles_share_servers is true we skip the test. --- test/extended/openstack/utils.go | 23 ++ test/extended/openstack/volumes.go | 13 +- .../v2/sharetypes/requests.go | 221 ++++++++++++++++++ .../v2/sharetypes/results.go | 143 ++++++++++++ .../sharedfilesystems/v2/sharetypes/urls.go | 43 ++++ vendor/modules.txt | 1 + 6 files changed, 441 insertions(+), 3 deletions(-) create mode 100644 vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/requests.go create mode 100644 vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/results.go create mode 100644 vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/urls.go diff --git a/test/extended/openstack/utils.go b/test/extended/openstack/utils.go index 3b0907771..5d2149f6e 100644 --- a/test/extended/openstack/utils.go +++ b/test/extended/openstack/utils.go @@ -18,6 +18,7 @@ import ( "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/networks" "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/subnets" "github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/shares" + "github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes" configv1 "github.com/openshift/api/config/v1" machinev1 "github.com/openshift/api/machine/v1beta1" operatorv1 "github.com/openshift/api/operator/v1" @@ -197,6 +198,28 @@ func GetSharesFromName(ctx context.Context, client *gophercloud.ServiceClient, s return shares, nil } +// return sharetype from openstack with specific name +func GetShareTypesFromName(ctx context.Context, client *gophercloud.ServiceClient, shareTypeName string) ([]sharetypes.ShareType, error) { + var emptyShareTypes []sharetypes.ShareType + var allShareTypes []sharetypes.ShareType + var shareTypes []sharetypes.ShareType + + allPages, err := sharetypes.List(client, sharetypes.ListOpts{}).AllPages(ctx) + if err != nil { + return emptyShareTypes, err + } + allShareTypes, err = sharetypes.ExtractShareTypes(allPages) + if err != nil { + return emptyShareTypes, err + } + for _, shareType := range allShareTypes { + if shareType.Name == shareTypeName { + shareTypes = append(shareTypes, shareType) + } + } + return shareTypes, nil +} + // return storageClass with specific provisioner. If seek_default is true, it will look also for the default annotation. func FindStorageClassByProvider(oc *exutil.CLI, provisioner string, seek_default bool) *storagev1.StorageClass { scList, err := oc.AdminKubeClient().StorageV1().StorageClasses().List(context.Background(), metav1.ListOptions{}) diff --git a/test/extended/openstack/volumes.go b/test/extended/openstack/volumes.go index 413f82e8f..210d81043 100644 --- a/test/extended/openstack/volumes.go +++ b/test/extended/openstack/volumes.go @@ -186,15 +186,22 @@ var _ = g.Describe("[sig-installer][Suite:openshift/openstack] The OpenStack pla g.It("should create a manila share when using manila storage class", func(ctx g.SpecContext) { var err error manilaSc := FindStorageClassByProvider(oc, "manila.csi.openstack.org", false) + shareClient, err := client.GetServiceClient(ctx, openstack.NewSharedFileSystemV2) + o.Expect(err).NotTo(o.HaveOccurred()) // Skip if Manila Storage class is not defined + // Skip if driver_handles_share_servers = true, Ref:https://issues.redhat.com/browse/OCPBUGS-45320 if manilaSc == nil { e2eskipper.Skipf("No StorageClass with manila.csi.openstack.org provisioner") + } else { + manilaShareTypes, err := GetShareTypesFromName(ctx, shareClient, "default") + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(len(manilaShareTypes)).To(o.Equal(1)) + if manilaShareTypes[0].ExtraSpecs["driver_handles_share_servers"] == "True" { + e2eskipper.Skipf("driver_handles_share_servers should be set to False in order for the test to run") + } } - shareClient, err := client.GetServiceClient(ctx, openstack.NewSharedFileSystemV2) - o.Expect(err).NotTo(o.HaveOccurred()) - ns := oc.Namespace() pvc := CreatePVC(ctx, clientSet, "manila-pvc", ns, manilaSc.Name, "1Gi") fileContent := "hello" diff --git a/vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/requests.go b/vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/requests.go new file mode 100644 index 000000000..66428ad0c --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/requests.go @@ -0,0 +1,221 @@ +package sharetypes + +import ( + "context" + + "github.com/gophercloud/gophercloud/v2" + "github.com/gophercloud/gophercloud/v2/pagination" +) + +// CreateOptsBuilder allows extensions to add additional parameters to the +// Create request. +type CreateOptsBuilder interface { + ToShareTypeCreateMap() (map[string]any, error) +} + +// CreateOpts contains options for creating a ShareType. This object is +// passed to the sharetypes.Create function. For more information about +// these parameters, see the ShareType object. +type CreateOpts struct { + // The share type name + Name string `json:"name" required:"true"` + // Indicates whether a share type is publicly accessible + IsPublic bool `json:"os-share-type-access:is_public"` + // The extra specifications for the share type + ExtraSpecs ExtraSpecsOpts `json:"extra_specs" required:"true"` +} + +// ExtraSpecsOpts represent the extra specifications that can be selected for a share type +type ExtraSpecsOpts struct { + // An extra specification that defines the driver mode for share server, or storage, life cycle management + DriverHandlesShareServers bool `json:"driver_handles_share_servers" required:"true"` + // An extra specification that filters back ends by whether they do or do not support share snapshots + SnapshotSupport *bool `json:"snapshot_support,omitempty"` +} + +// ToShareTypeCreateMap assembles a request body based on the contents of a +// CreateOpts. +func (opts CreateOpts) ToShareTypeCreateMap() (map[string]any, error) { + return gophercloud.BuildRequestBody(opts, "share_type") +} + +// Create will create a new ShareType based on the values in CreateOpts. To +// extract the ShareType object from the response, call the Extract method +// on the CreateResult. +func Create(ctx context.Context, client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { + b, err := opts.ToShareTypeCreateMap() + if err != nil { + r.Err = err + return + } + resp, err := client.Post(ctx, createURL(client), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// Delete will delete the existing ShareType with the provided ID. +func Delete(ctx context.Context, client *gophercloud.ServiceClient, id string) (r DeleteResult) { + resp, err := client.Delete(ctx, deleteURL(client, id), nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// ListOptsBuilder allows extensions to add additional parameters to the List +// request. +type ListOptsBuilder interface { + ToShareTypeListQuery() (string, error) +} + +// ListOpts holds options for listing ShareTypes. It is passed to the +// sharetypes.List function. +type ListOpts struct { + // Select if public types, private types, or both should be listed + IsPublic string `q:"is_public"` +} + +// ToShareTypeListQuery formats a ListOpts into a query string. +func (opts ListOpts) ToShareTypeListQuery() (string, error) { + q, err := gophercloud.BuildQueryString(opts) + return q.String(), err +} + +// List returns ShareTypes optionally limited by the conditions provided in ListOpts. +func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { + url := listURL(client) + if opts != nil { + query, err := opts.ToShareTypeListQuery() + if err != nil { + return pagination.Pager{Err: err} + } + url += query + } + + return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { + return ShareTypePage{pagination.SinglePageBase(r)} + }) +} + +// GetDefault will retrieve the default ShareType. +func GetDefault(ctx context.Context, client *gophercloud.ServiceClient) (r GetDefaultResult) { + resp, err := client.Get(ctx, getDefaultURL(client), &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// GetExtraSpecs will retrieve the extra specifications for a given ShareType. +func GetExtraSpecs(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetExtraSpecsResult) { + resp, err := client.Get(ctx, getExtraSpecsURL(client, id), &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// SetExtraSpecsOptsBuilder allows extensions to add additional parameters to the +// SetExtraSpecs request. +type SetExtraSpecsOptsBuilder interface { + ToShareTypeSetExtraSpecsMap() (map[string]any, error) +} + +type SetExtraSpecsOpts struct { + // A list of all extra specifications to be added to a ShareType + ExtraSpecs map[string]any `json:"extra_specs" required:"true"` +} + +// ToShareTypeSetExtraSpecsMap assembles a request body based on the contents of a +// SetExtraSpecsOpts. +func (opts SetExtraSpecsOpts) ToShareTypeSetExtraSpecsMap() (map[string]any, error) { + return gophercloud.BuildRequestBody(opts, "") +} + +// SetExtraSpecs will set new specifications for a ShareType based on the values +// in SetExtraSpecsOpts. To extract the extra specifications object from the response, +// call the Extract method on the SetExtraSpecsResult. +func SetExtraSpecs(ctx context.Context, client *gophercloud.ServiceClient, id string, opts SetExtraSpecsOptsBuilder) (r SetExtraSpecsResult) { + b, err := opts.ToShareTypeSetExtraSpecsMap() + if err != nil { + r.Err = err + return + } + + resp, err := client.Post(ctx, setExtraSpecsURL(client, id), b, &r.Body, &gophercloud.RequestOpts{ + OkCodes: []int{200, 202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// UnsetExtraSpecs will unset an extra specification for an existing ShareType. +func UnsetExtraSpecs(ctx context.Context, client *gophercloud.ServiceClient, id string, key string) (r UnsetExtraSpecsResult) { + resp, err := client.Delete(ctx, unsetExtraSpecsURL(client, id, key), nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// ShowAccess will show access details for an existing ShareType. +func ShowAccess(ctx context.Context, client *gophercloud.ServiceClient, id string) (r ShowAccessResult) { + resp, err := client.Get(ctx, showAccessURL(client, id), &r.Body, nil) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// AddAccessOptsBuilder allows extensions to add additional parameters to the +// AddAccess +type AddAccessOptsBuilder interface { + ToAddAccessMap() (map[string]any, error) +} + +type AccessOpts struct { + // The UUID of the project to which access to the share type is granted. + Project string `json:"project"` +} + +// ToAddAccessMap assembles a request body based on the contents of a +// AccessOpts. +func (opts AccessOpts) ToAddAccessMap() (map[string]any, error) { + return gophercloud.BuildRequestBody(opts, "addProjectAccess") +} + +// AddAccess will add access to a ShareType based on the values +// in AccessOpts. +func AddAccess(ctx context.Context, client *gophercloud.ServiceClient, id string, opts AddAccessOptsBuilder) (r AddAccessResult) { + b, err := opts.ToAddAccessMap() + if err != nil { + r.Err = err + return + } + + resp, err := client.Post(ctx, addAccessURL(client, id), b, nil, &gophercloud.RequestOpts{ + OkCodes: []int{200, 202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} + +// RemoveAccessOptsBuilder allows extensions to add additional parameters to the +// RemoveAccess +type RemoveAccessOptsBuilder interface { + ToRemoveAccessMap() (map[string]any, error) +} + +// ToRemoveAccessMap assembles a request body based on the contents of a +// AccessOpts. +func (opts AccessOpts) ToRemoveAccessMap() (map[string]any, error) { + return gophercloud.BuildRequestBody(opts, "removeProjectAccess") +} + +// RemoveAccess will remove access to a ShareType based on the values +// in AccessOpts. +func RemoveAccess(ctx context.Context, client *gophercloud.ServiceClient, id string, opts RemoveAccessOptsBuilder) (r RemoveAccessResult) { + b, err := opts.ToRemoveAccessMap() + if err != nil { + r.Err = err + return + } + + resp, err := client.Post(ctx, removeAccessURL(client, id), b, nil, &gophercloud.RequestOpts{ + OkCodes: []int{200, 202}, + }) + _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) + return +} diff --git a/vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/results.go b/vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/results.go new file mode 100644 index 000000000..9fb54fa8d --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/results.go @@ -0,0 +1,143 @@ +package sharetypes + +import ( + "github.com/gophercloud/gophercloud/v2" + "github.com/gophercloud/gophercloud/v2/pagination" +) + +// ShareType contains all the information associated with an OpenStack +// ShareType. +type ShareType struct { + // The Share Type ID + ID string `json:"id"` + // The Share Type name + Name string `json:"name"` + // Indicates whether a share type is publicly accessible + IsPublic bool `json:"os-share-type-access:is_public"` + // The required extra specifications for the share type + RequiredExtraSpecs map[string]any `json:"required_extra_specs"` + // The extra specifications for the share type + ExtraSpecs map[string]any `json:"extra_specs"` +} + +type commonResult struct { + gophercloud.Result +} + +// Extract will get the ShareType object out of the commonResult object. +func (r commonResult) Extract() (*ShareType, error) { + var s struct { + ShareType *ShareType `json:"share_type"` + } + err := r.ExtractInto(&s) + return s.ShareType, err +} + +// CreateResult contains the response body and error from a Create request. +type CreateResult struct { + commonResult +} + +// DeleteResult contains the response body and error from a Delete request. +type DeleteResult struct { + gophercloud.ErrResult +} + +// ShareTypePage is a pagination.pager that is returned from a call to the List function. +type ShareTypePage struct { + pagination.SinglePageBase +} + +// IsEmpty returns true if a ListResult contains no ShareTypes. +func (r ShareTypePage) IsEmpty() (bool, error) { + if r.StatusCode == 204 { + return true, nil + } + + shareTypes, err := ExtractShareTypes(r) + return len(shareTypes) == 0, err +} + +// ExtractShareTypes extracts and returns ShareTypes. It is used while +// iterating over a sharetypes.List call. +func ExtractShareTypes(r pagination.Page) ([]ShareType, error) { + var s struct { + ShareTypes []ShareType `json:"share_types"` + } + err := (r.(ShareTypePage)).ExtractInto(&s) + return s.ShareTypes, err +} + +// GetDefaultResult contains the response body and error from a Get Default request. +type GetDefaultResult struct { + commonResult +} + +// ExtraSpecs contains all the information associated with extra specifications +// for an Openstack ShareType. +type ExtraSpecs map[string]any + +type extraSpecsResult struct { + gophercloud.Result +} + +// Extract will get the ExtraSpecs object out of the commonResult object. +func (r extraSpecsResult) Extract() (ExtraSpecs, error) { + var s struct { + Specs ExtraSpecs `json:"extra_specs"` + } + err := r.ExtractInto(&s) + return s.Specs, err +} + +// GetExtraSpecsResult contains the response body and error from a Get Extra Specs request. +type GetExtraSpecsResult struct { + extraSpecsResult +} + +// SetExtraSpecsResult contains the response body and error from a Set Extra Specs request. +type SetExtraSpecsResult struct { + extraSpecsResult +} + +// UnsetExtraSpecsResult contains the response body and error from a Unset Extra Specs request. +type UnsetExtraSpecsResult struct { + gophercloud.ErrResult +} + +// ShareTypeAccess contains all the information associated with an OpenStack +// ShareTypeAccess. +type ShareTypeAccess struct { + // The share type ID of the member. + ShareTypeID string `json:"share_type_id"` + // The UUID of the project for which access to the share type is granted. + ProjectID string `json:"project_id"` +} + +type shareTypeAccessResult struct { + gophercloud.Result +} + +// ShowAccessResult contains the response body and error from a Show access request. +type ShowAccessResult struct { + shareTypeAccessResult +} + +// Extract will get the ShareTypeAccess objects out of the shareTypeAccessResult object. +func (r ShowAccessResult) Extract() ([]ShareTypeAccess, error) { + var s struct { + ShareTypeAccess []ShareTypeAccess `json:"share_type_access"` + } + err := r.ExtractInto(&s) + return s.ShareTypeAccess, err +} + +// AddAccessResult contains the response body and error from a Add Access request. +type AddAccessResult struct { + gophercloud.ErrResult +} + +// RemoveAccessResult contains the response body and error from a Remove Access request. +type RemoveAccessResult struct { + gophercloud.ErrResult +} diff --git a/vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/urls.go b/vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/urls.go new file mode 100644 index 000000000..35afec8f5 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes/urls.go @@ -0,0 +1,43 @@ +package sharetypes + +import "github.com/gophercloud/gophercloud/v2" + +func createURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("types") +} + +func deleteURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("types", id) +} + +func listURL(c *gophercloud.ServiceClient) string { + return createURL(c) +} + +func getDefaultURL(c *gophercloud.ServiceClient) string { + return c.ServiceURL("types", "default") +} + +func getExtraSpecsURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("types", id, "extra_specs") +} + +func setExtraSpecsURL(c *gophercloud.ServiceClient, id string) string { + return getExtraSpecsURL(c, id) +} + +func unsetExtraSpecsURL(c *gophercloud.ServiceClient, id string, key string) string { + return c.ServiceURL("types", id, "extra_specs", key) +} + +func showAccessURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("types", id, "share_type_access") +} + +func addAccessURL(c *gophercloud.ServiceClient, id string) string { + return c.ServiceURL("types", id, "action") +} + +func removeAccessURL(c *gophercloud.ServiceClient, id string) string { + return addAccessURL(c, id) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 76c2b2389..2461532be 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -576,6 +576,7 @@ github.com/gophercloud/gophercloud/v2/openstack/networking/v2/networks github.com/gophercloud/gophercloud/v2/openstack/networking/v2/ports github.com/gophercloud/gophercloud/v2/openstack/networking/v2/subnets github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/shares +github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/sharetypes github.com/gophercloud/gophercloud/v2/openstack/utils github.com/gophercloud/gophercloud/v2/pagination # github.com/gorilla/websocket v1.5.0