diff --git a/README.md b/README.md index 4cc1345..8e25835 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Example: * Invoke `/registercluster` API on CNS manager by uploading the kubeconfig file. You may also modify other input parameters for the API based on your cluster configuration. The API can also be invoked from command line. Here is an example: ``` -curl -X 'POST' "http://CNS-MANAGER-ENDPOINT/1.0.0/registercluster?csiDriverSecretName=vsphere-config-secret&csiDriverSecretNamespace=vmware-system-csi" -H 'accept: application/json' -H 'Content-Type: multipart/form-data' -F 'clusterKubeConfigFile=@output_file_name' -u "Admistrator:Admin123@" +curl -X 'POST' "http://CNS-MANAGER-ENDPOINT/1.0.0/registercluster?csiDriverSecretName=vsphere-config-secret&csiDriverNamespace=vmware-system-csi" -H 'accept: application/json' -H 'Content-Type: multipart/form-data' -F 'clusterKubeConfigFile=@output_file_name' -u "Admistrator:Admin123@" ``` * Once the cluster is registered, you may delete this file from the machine. @@ -66,3 +66,6 @@ This feature allows migrating volumes from one datastore to another. Read [here] * **Orphan volumes detection & deletion** This feature allows detecting/deleting orphan volumes that are not being used in any of the registered Kubernetes clusters on the vCenter. Read [here](docs/book/features/orphan_volumes.md) for more details about this feature. + +* **Orphan snapshots detection & deletion** +This feature allows detecting/deleting orphan snapshots that are not being used in any of the registered Kubernetes clusters on the vCenter. Read [here](docs/book/features/orphan_snapshots.md) for more details about this feature. \ No newline at end of file diff --git a/client-sdk/go/client/api_cluster_record_keeping.go b/client-sdk/go/client/api_cluster_record_keeping.go index 651ea83..4d619d6 100644 --- a/client-sdk/go/client/api_cluster_record_keeping.go +++ b/client-sdk/go/client/api_cluster_record_keeping.go @@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -20,9 +20,8 @@ import ( "io/ioutil" "net/http" "net/url" - "os" "strings" - + "os" "github.com/antihax/optional" ) @@ -32,7 +31,6 @@ var ( ) type ClusterRecordKeepingApiService service - /* ClusterRecordKeepingApiService Deregister a cluster with the CNS Manager. The API takes unique clusterID as input and de-registers the cluster from CNS Manager. @@ -42,10 +40,10 @@ The API takes unique clusterID as input and de-registers the cluster from CNS Ma */ func (a *ClusterRecordKeepingApiService) Deregistercluster(ctx context.Context, clusterId string) (DeregisterClusterResult, *http.Response, error) { var ( - localVarHttpMethod = strings.ToUpper("Post") - localVarPostBody interface{} - localVarFileName string - localVarFileBytes []byte + localVarHttpMethod = strings.ToUpper("Post") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte localVarReturnValue DeregisterClusterResult ) @@ -92,43 +90,42 @@ func (a *ClusterRecordKeepingApiService) Deregistercluster(ctx context.Context, if localVarHttpResponse.StatusCode < 300 { // If we succeed, return the data, otherwise pass on to decode error. - err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err == nil { + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err == nil { return localVarReturnValue, localVarHttpResponse, err } } if localVarHttpResponse.StatusCode >= 300 { newErr := GenericSwaggerError{ - body: localVarBody, + body: localVarBody, error: localVarHttpResponse.Status, } if localVarHttpResponse.StatusCode == 200 { var v DeregisterClusterResult - err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v return localVarReturnValue, localVarHttpResponse, newErr - } - newErr.model = v - return localVarReturnValue, localVarHttpResponse, newErr } if localVarHttpResponse.StatusCode == 0 { var v ModelError - err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v return localVarReturnValue, localVarHttpResponse, newErr - } - newErr.model = v - return localVarReturnValue, localVarHttpResponse, newErr } return localVarReturnValue, localVarHttpResponse, newErr } return localVarReturnValue, localVarHttpResponse, nil } - /* ClusterRecordKeepingApiService Get the list of registered k8s clusters from CNS manager inventory. CNS manager does a record keeping of all the clusters in a vCenter. The registered cluster config is stored in the CNS manager inventory by using ClusterId as the key. The listregisteredclusters API will return the list of all the registered clusterIds as an array. @@ -137,10 +134,10 @@ CNS manager does a record keeping of all the clusters in a vCenter. The register */ func (a *ClusterRecordKeepingApiService) Listregisteredclusters(ctx context.Context) ([]string, *http.Response, error) { var ( - localVarHttpMethod = strings.ToUpper("Get") - localVarPostBody interface{} - localVarFileName string - localVarFileBytes []byte + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte localVarReturnValue []string ) @@ -186,66 +183,67 @@ func (a *ClusterRecordKeepingApiService) Listregisteredclusters(ctx context.Cont if localVarHttpResponse.StatusCode < 300 { // If we succeed, return the data, otherwise pass on to decode error. - err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err == nil { + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err == nil { return localVarReturnValue, localVarHttpResponse, err } } if localVarHttpResponse.StatusCode >= 300 { newErr := GenericSwaggerError{ - body: localVarBody, + body: localVarBody, error: localVarHttpResponse.Status, } if localVarHttpResponse.StatusCode == 200 { var v []string - err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v return localVarReturnValue, localVarHttpResponse, newErr - } - newErr.model = v - return localVarReturnValue, localVarHttpResponse, newErr } if localVarHttpResponse.StatusCode == 0 { var v ModelError - err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v return localVarReturnValue, localVarHttpResponse, newErr - } - newErr.model = v - return localVarReturnValue, localVarHttpResponse, newErr } return localVarReturnValue, localVarHttpResponse, newErr } return localVarReturnValue, localVarHttpResponse, nil } - /* -ClusterRecordKeepingApiService Register a cluster with the CNS Manager. -The API takes kubeconfig of a given cluster as an input. Make sure to copy the contents of the Cluster KubeConfig to a file. The kubeconfig is stored securely inside a k8s secret on the cluster where CNS manager is deployed. The API additionally takes optional params to read cluster-id set for CSI driver from the CSI secret. +ClusterRecordKeepingApiService Register a Kubernetes cluster with CNS Manager. +The API takes kubeconfig of a given cluster as an input. Make sure to copy the contents of the Cluster KubeConfig to a file. The kubeconfig is stored securely inside a k8s secret on the cluster where CNS manager is deployed. The API additionally takes optional params like CSI driver clusterId or CSI driver namespace and config secret name to read cluster-id from the CSI secret. * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param optional nil or *ClusterRecordKeepingApiRegisterclusterOpts - Optional Parameters: - * @param "ClusterKubeConfigFile" (optional.*os.File) - A file with cluster kubeconfig content. + * @param "ClusterKubeConfigFile" (optional.*os.File) - * @param "CsiDriverSecretName" (optional.String) - (Optional) Refers to the name of the config secret of vsphere-csi-driver. - * @param "CsiDriverSecretNamespace" (optional.String) - (Optional) Refers to the namespace of the config secret of vsphere-csi-driver. + * @param "CsiDriverNamespace" (optional.String) - (Optional) Refers to the namespace of vsphere-csi-driver. + * @param "ClusterId" (optional.String) - (Optional) Cluster Id of the cluster to be registered with the CNS Manager. This cluster Id needs to be the same that's used in the vSphere CSI driver config of the Kubernetes cluster. For vanilla Kubernetes distributions deployed using [VMware's recommended way](https://docs.vmware.com/en/VMware-vSphere-Container-Storage-Plug-in/2.0/vmware-vsphere-csp-getting-started/GUID-BFF39F1D-F70A-4360-ABC9-85BDAFBE8864.html), it will be present in the CSI secret and will be auto-computed from the provided kubeConfig. For other Kubernetes distributions, please check their docs to determine how they're configuring clusterId for the vSphere CSI driver in the Kubernetes cluster. @return RegisterClusterResult */ type ClusterRecordKeepingApiRegisterclusterOpts struct { - ClusterKubeConfigFile optional.Interface - CsiDriverSecretName optional.String - CsiDriverSecretNamespace optional.String + ClusterKubeConfigFile optional.Interface + CsiDriverSecretName optional.String + CsiDriverNamespace optional.String + ClusterId optional.String } func (a *ClusterRecordKeepingApiService) Registercluster(ctx context.Context, localVarOptionals *ClusterRecordKeepingApiRegisterclusterOpts) (RegisterClusterResult, *http.Response, error) { var ( - localVarHttpMethod = strings.ToUpper("Post") - localVarPostBody interface{} - localVarFileName string - localVarFileBytes []byte + localVarHttpMethod = strings.ToUpper("Post") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte localVarReturnValue RegisterClusterResult ) @@ -259,8 +257,11 @@ func (a *ClusterRecordKeepingApiService) Registercluster(ctx context.Context, lo if localVarOptionals != nil && localVarOptionals.CsiDriverSecretName.IsSet() { localVarQueryParams.Add("csiDriverSecretName", parameterToString(localVarOptionals.CsiDriverSecretName.Value(), "")) } - if localVarOptionals != nil && localVarOptionals.CsiDriverSecretNamespace.IsSet() { - localVarQueryParams.Add("csiDriverSecretNamespace", parameterToString(localVarOptionals.CsiDriverSecretNamespace.Value(), "")) + if localVarOptionals != nil && localVarOptionals.CsiDriverNamespace.IsSet() { + localVarQueryParams.Add("csiDriverNamespace", parameterToString(localVarOptionals.CsiDriverNamespace.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.ClusterId.IsSet() { + localVarQueryParams.Add("clusterId", parameterToString(localVarOptionals.ClusterId.Value(), "")) } // to determine the Content-Type header localVarHttpContentTypes := []string{"multipart/form-data"} @@ -279,12 +280,12 @@ func (a *ClusterRecordKeepingApiService) Registercluster(ctx context.Context, lo if localVarHttpHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHttpHeaderAccept } - var localVarFile *os.File + var localVarFile *os.File if localVarOptionals != nil && localVarOptionals.ClusterKubeConfigFile.IsSet() { localVarFileOk := false localVarFile, localVarFileOk = localVarOptionals.ClusterKubeConfigFile.Value().(*os.File) if !localVarFileOk { - return localVarReturnValue, nil, reportError("clusterKubeConfigFile should be *os.File") + return localVarReturnValue, nil, reportError("clusterKubeConfigFile should be *os.File") } } if localVarFile != nil { @@ -311,36 +312,36 @@ func (a *ClusterRecordKeepingApiService) Registercluster(ctx context.Context, lo if localVarHttpResponse.StatusCode < 300 { // If we succeed, return the data, otherwise pass on to decode error. - err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err == nil { + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err == nil { return localVarReturnValue, localVarHttpResponse, err } } if localVarHttpResponse.StatusCode >= 300 { newErr := GenericSwaggerError{ - body: localVarBody, + body: localVarBody, error: localVarHttpResponse.Status, } if localVarHttpResponse.StatusCode == 200 { var v RegisterClusterResult - err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v return localVarReturnValue, localVarHttpResponse, newErr - } - newErr.model = v - return localVarReturnValue, localVarHttpResponse, newErr } if localVarHttpResponse.StatusCode == 0 { var v ModelError - err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v return localVarReturnValue, localVarHttpResponse, newErr - } - newErr.model = v - return localVarReturnValue, localVarHttpResponse, newErr } return localVarReturnValue, localVarHttpResponse, newErr } diff --git a/client-sdk/go/client/api_orphan_snapshot.go b/client-sdk/go/client/api_orphan_snapshot.go new file mode 100644 index 0000000..d58994a --- /dev/null +++ b/client-sdk/go/client/api_orphan_snapshot.go @@ -0,0 +1,268 @@ +/* +Copyright 2024 VMware, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package swagger + +import ( + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" + "github.com/antihax/optional" +) + +// Linger please +var ( + _ context.Context +) + +type OrphanSnapshotApiService service +/* +OrphanSnapshotApiService Delete orphan snapshots. +Use this API to identify and delete orphan snapshots. From vSphere CSI plugin's perspective, orphan snapshots are FCD snapshots that were initiated through the vSphere CSI driver but do not have a corresponding VolumeSnapshotContent object in the Kubernetes cluster. snapshotPrefix is the prefix used in the snapshot description. Its default value is “snapshot”, which is also the default value used by snapshot sidecar in CSI and it can be configured based on prefix used in the snapshot sidecar. Use the `snapshotPrefix` parameter to specify alternate prefix. From Velero vSphere plugin's perspective, orphan snapshots are snapshots whose upload is failing with multiple attempts or snapshots whose local deletion is failing after successful upload. For Velero vSphere plugin, user has to specify “AstrolabeSnapshot” as the snapshotPrefix. Orphan snapshot deletion operation is performed asynchronously. It returns a job id, the status of which can be retrieved using `jobStatus` API. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param optional nil or *OrphanSnapshotApiOrphanSnapshotsDeleteOpts - Optional Parameters: + * @param "Datacenter" (optional.String) - (Optional) Datacenter name to narrow down the orphan snapshots search. + * @param "Datastores" (optional.String) - (Optional) List of comma-separated datastores. Specify only if the `datacenter` param is specified. + * @param "SnapshotPrefix" (optional.String) - (Optional) The snapshot prefix indicates the prefix used in snapshot description. +@return SnapshotDeleteResult +*/ + +type OrphanSnapshotApiOrphanSnapshotsDeleteOpts struct { + Datacenter optional.String + Datastores optional.String + SnapshotPrefix optional.String +} + +func (a *OrphanSnapshotApiService) OrphanSnapshotsDelete(ctx context.Context, localVarOptionals *OrphanSnapshotApiOrphanSnapshotsDeleteOpts) (SnapshotDeleteResult, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Delete") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue SnapshotDeleteResult + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/orphansnapshots" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if localVarOptionals != nil && localVarOptionals.Datacenter.IsSet() { + localVarQueryParams.Add("datacenter", parameterToString(localVarOptionals.Datacenter.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.Datastores.IsSet() { + localVarQueryParams.Add("datastores", parameterToString(localVarOptionals.Datastores.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.SnapshotPrefix.IsSet() { + localVarQueryParams.Add("snapshotPrefix", parameterToString(localVarOptionals.SnapshotPrefix.Value(), "")) + } + // to determine the Content-Type header + localVarHttpContentTypes := []string{} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 202 { + var v SnapshotDeleteResult + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 0 { + var v ModelError + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} +/* +OrphanSnapshotApiService List all the orphan snapshots. +Use this API to identify orphan snapshots. From vSphere CSI plugin's perspective, orphan snapshots are FCD snapshots that were initiated through the vSphere CSI driver but do not have a corresponding VolumeSnapshotContent object in the Kubernetes cluster. snapshotPrefix is the prefix used in the snapshot description. Its default value is “snapshot”, which is also the default value used by snapshot sidecar in CSI and it can be configured based on prefix used in the snapshot sidecar. Use the `snapshotPrefix` parameter to specify alternate prefix. From Velero vSphere plugin's perspective, orphan snapshots are snapshots whose upload is failing with multiple attempts or snapshots whose local deletion is failing after successful upload. For Velero vSphere plugin, user has to specify “AstrolabeSnapshot” as the snapshotPrefix. GET API for orphan snapshots support pagination. The response body contains totalOrphanSnapshots, limit and offset values. Also, response header contains X-Limit and X-Next-Offset values. Based on these values user can decide if there are more results to be fetched. Since the detection of orphan snapshots is an expensive operation, the operation is performed asynchronously at regular intervals. This API returns the list of orphan snapshots found in the last run of the operation. `retryAfterMinutes` in response body indicates the time in minutes after which the next retry should be attempted to get the updated orphan snapshot list. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param optional nil or *OrphanSnapshotApiOrphanSnapshotsListOpts - Optional Parameters: + * @param "Datacenter" (optional.String) - (Optional) Datacenter name to narrow down the orphan snapshots search. + * @param "Datastores" (optional.String) - (Optional) List of comma-separated datastores. Specify only if the `datacenter` param is specified. + * @param "SnapshotPrefix" (optional.String) - (Optional) The snapshot prefix indicates the prefix used in snapshot description. + * @param "Limit" (optional.Int64) - (Optional) Limit specifies the maximum entries that should be displayed in single request. + * @param "Offset" (optional.Int64) - (Optional) Offset specifies the starting point of the result set. +@return OrphanSnapshotResult +*/ + +type OrphanSnapshotApiOrphanSnapshotsListOpts struct { + Datacenter optional.String + Datastores optional.String + SnapshotPrefix optional.String + Limit optional.Int64 + Offset optional.Int64 +} + +func (a *OrphanSnapshotApiService) OrphanSnapshotsList(ctx context.Context, localVarOptionals *OrphanSnapshotApiOrphanSnapshotsListOpts) (OrphanSnapshotResult, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue OrphanSnapshotResult + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/orphansnapshots" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + if localVarOptionals != nil && localVarOptionals.Datacenter.IsSet() { + localVarQueryParams.Add("datacenter", parameterToString(localVarOptionals.Datacenter.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.Datastores.IsSet() { + localVarQueryParams.Add("datastores", parameterToString(localVarOptionals.Datastores.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.SnapshotPrefix.IsSet() { + localVarQueryParams.Add("snapshotPrefix", parameterToString(localVarOptionals.SnapshotPrefix.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.Limit.IsSet() { + localVarQueryParams.Add("limit", parameterToString(localVarOptionals.Limit.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.Offset.IsSet() { + localVarQueryParams.Add("offset", parameterToString(localVarOptionals.Offset.Value(), "")) + } + // to determine the Content-Type header + localVarHttpContentTypes := []string{} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 200 { + var v OrphanSnapshotResult + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 0 { + var v ModelError + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} diff --git a/client-sdk/go/client/api_orphan_volume.go b/client-sdk/go/client/api_orphan_volume.go index 217a499..d1c4c83 100644 --- a/client-sdk/go/client/api_orphan_volume.go +++ b/client-sdk/go/client/api_orphan_volume.go @@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ - package swagger import ( @@ -22,7 +21,6 @@ import ( "net/http" "net/url" "strings" - "github.com/antihax/optional" ) @@ -32,12 +30,11 @@ var ( ) type OrphanVolumeApiService service - /* OrphanVolumeApiService Delete orphan volumes. Delete the orphan volumes for the given criteria. * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - * @param deleteAttachedOrphans Set to `true` to delete attached orphans. When set to `true`, the API will detach the orphan volume from the VM before deleting it. + * @param deleteAttachedOrphans Set to `true` to delete attached orphans. When set to `true`, the API will detach the orphan volume from the VM before deleting it. * @param optional nil or *OrphanVolumeApiOrphanVolumeDeleteOpts - Optional Parameters: * @param "Datacenter" (optional.String) - (Optional) Datacenter name to narrow down the deletion of orphan volumes to. * @param "Datastores" (optional.String) - (Optional) List of comma-separated datastores to narrow down the deletion of orphan volumes to. Specify only if the `datacenter` param is specified. @@ -45,16 +42,16 @@ Delete the orphan volumes for the given criteria. */ type OrphanVolumeApiOrphanVolumeDeleteOpts struct { - Datacenter optional.String - Datastores optional.String + Datacenter optional.String + Datastores optional.String } func (a *OrphanVolumeApiService) OrphanVolumeDelete(ctx context.Context, deleteAttachedOrphans bool, localVarOptionals *OrphanVolumeApiOrphanVolumeDeleteOpts) (OrphanVolumeDeleteResult, *http.Response, error) { var ( - localVarHttpMethod = strings.ToUpper("Delete") - localVarPostBody interface{} - localVarFileName string - localVarFileBytes []byte + localVarHttpMethod = strings.ToUpper("Delete") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte localVarReturnValue OrphanVolumeDeleteResult ) @@ -107,65 +104,68 @@ func (a *OrphanVolumeApiService) OrphanVolumeDelete(ctx context.Context, deleteA if localVarHttpResponse.StatusCode < 300 { // If we succeed, return the data, otherwise pass on to decode error. - err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err == nil { + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err == nil { return localVarReturnValue, localVarHttpResponse, err } } if localVarHttpResponse.StatusCode >= 300 { newErr := GenericSwaggerError{ - body: localVarBody, + body: localVarBody, error: localVarHttpResponse.Status, } if localVarHttpResponse.StatusCode == 200 { var v OrphanVolumeDeleteResult - err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v return localVarReturnValue, localVarHttpResponse, newErr - } - newErr.model = v - return localVarReturnValue, localVarHttpResponse, newErr } if localVarHttpResponse.StatusCode == 0 { var v ModelError - err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v return localVarReturnValue, localVarHttpResponse, newErr - } - newErr.model = v - return localVarReturnValue, localVarHttpResponse, newErr } return localVarReturnValue, localVarHttpResponse, newErr } return localVarReturnValue, localVarHttpResponse, nil } - /* OrphanVolumeApiService List all the orphan volumes. -Returns a list of orphan volumes for the given input parameters, which could be attached or detached. Since the detection of orphan volumes is an expensive operation, the operation is performed asynchronously at regular intervals. This API returns the list of orphan volumes found in the last run of the operation. The response body contains the following fields: 1. `TotalOrphans` - The total number of orphan volumes found. 2. `OrphanVolumes` - The list of orphan volumes found. 3. `RetryAfterMinutes` - The time in minutes after which the next retry should be attempted to get the updated orphan volume list. 4. `TotalOrphansAttached` - The total number of orphan volumes found that are attached to a VM. 5. `TotalOrphansDetached` - The total number of orphan volumes found that are detached. Orphan volumes are safe to delete since there is no PersistentVolume in the Kubernetes cluster referring to them. +Returns a list of orphan volumes for the given input parameters, which could be attached or detached. Since the detection of orphan volumes is an expensive operation, the operation is performed asynchronously at regular intervals. This API returns the list of orphan volumes found in the last run of the operation. If the request is successful, the response will contain the following: 1. `TotalOrphans` - The total number of orphan volumes found. 2. `OrphanVolumes` - The list of orphan volumes found. 3. `RetryAfterMinutes` - The time in minutes after which the next retry should be attempted to get the updated orphan volume list. 4. `TotalOrphansAttached` - The total number of orphan volumes found that are attached to a VM. 5. `TotalOrphansDetached` - The total number of orphan volumes found that are detached. 6. `Limit` - The maximum number of orphan volumes to be returned. 7. `NextOffset` - The offset of the next page if there are more orphan volumes to query. Orphan volumes are safe to delete since there is no PersistentVolume in the Kubernetes cluster referring to them. * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). * @param includeDetails Set to \"true\" to get a detailed dump of the orphan volume. * @param optional nil or *OrphanVolumeApiOrphanVolumeListOpts - Optional Parameters: * @param "Datacenter" (optional.String) - (Optional) Datacenter name to narrow down the orphan volume search. * @param "Datastores" (optional.String) - (Optional) List of comma-separated datastores. Specify only if the `datacenter` param is specified. + * @param "Offset" (optional.Int32) - (Optional) The offset indicates the starting point of the result set. + * @param "Limit" (optional.Int32) - (Optional) The limit indicates the maximum number of orphan volumes to be returned. @return OrphanVolumeResult */ type OrphanVolumeApiOrphanVolumeListOpts struct { - Datacenter optional.String - Datastores optional.String + Datacenter optional.String + Datastores optional.String + Offset optional.Int32 + Limit optional.Int32 } func (a *OrphanVolumeApiService) OrphanVolumeList(ctx context.Context, includeDetails bool, localVarOptionals *OrphanVolumeApiOrphanVolumeListOpts) (OrphanVolumeResult, *http.Response, error) { var ( - localVarHttpMethod = strings.ToUpper("Get") - localVarPostBody interface{} - localVarFileName string - localVarFileBytes []byte + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte localVarReturnValue OrphanVolumeResult ) @@ -183,6 +183,12 @@ func (a *OrphanVolumeApiService) OrphanVolumeList(ctx context.Context, includeDe if localVarOptionals != nil && localVarOptionals.Datastores.IsSet() { localVarQueryParams.Add("datastores", parameterToString(localVarOptionals.Datastores.Value(), "")) } + if localVarOptionals != nil && localVarOptionals.Offset.IsSet() { + localVarQueryParams.Add("offset", parameterToString(localVarOptionals.Offset.Value(), "")) + } + if localVarOptionals != nil && localVarOptionals.Limit.IsSet() { + localVarQueryParams.Add("limit", parameterToString(localVarOptionals.Limit.Value(), "")) + } // to determine the Content-Type header localVarHttpContentTypes := []string{} @@ -218,36 +224,36 @@ func (a *OrphanVolumeApiService) OrphanVolumeList(ctx context.Context, includeDe if localVarHttpResponse.StatusCode < 300 { // If we succeed, return the data, otherwise pass on to decode error. - err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err == nil { + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err == nil { return localVarReturnValue, localVarHttpResponse, err } } if localVarHttpResponse.StatusCode >= 300 { newErr := GenericSwaggerError{ - body: localVarBody, + body: localVarBody, error: localVarHttpResponse.Status, } if localVarHttpResponse.StatusCode == 200 { var v OrphanVolumeResult - err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v return localVarReturnValue, localVarHttpResponse, newErr - } - newErr.model = v - return localVarReturnValue, localVarHttpResponse, newErr } if localVarHttpResponse.StatusCode == 0 { var v ModelError - err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v return localVarReturnValue, localVarHttpResponse, newErr - } - newErr.model = v - return localVarReturnValue, localVarHttpResponse, newErr } return localVarReturnValue, localVarHttpResponse, newErr } diff --git a/client-sdk/go/client/api_snapshot_for_volume.go b/client-sdk/go/client/api_snapshot_for_volume.go new file mode 100644 index 0000000..80c6b86 --- /dev/null +++ b/client-sdk/go/client/api_snapshot_for_volume.go @@ -0,0 +1,352 @@ +/* +Copyright 2024 VMware, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package swagger + +import ( + "context" + "io/ioutil" + "net/http" + "net/url" + "strings" + "fmt" + "github.com/antihax/optional" +) + +// Linger please +var ( + _ context.Context +) + +type SnapshotForVolumeApiService service +/* +SnapshotForVolumeApiService Delete all the snapshots for a specific volume +Use this API to delete all the snapshots for a specific volume. Snapshot deletion operation is performed asynchronously. It returns a job id, the status of which can be retrieved using `jobStatus` API. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param volumeId Unique Id of the volume. + * @param datacenter Datacenter name to which volume and snapshots belong to. + * @param datastore Datastore name to which volume and snapshots belong to. + * @param optional nil or *SnapshotForVolumeApiDeleteAllSnapshotsForVolumeOpts - Optional Parameters: + * @param "SnapshotPrefix" (optional.String) - (Optional) The snapshot prefix indicates the prefix used in snapshot description. If snapshot prefix is not specified, then it will delete all snapshots of a volume. +@return SnapshotDeleteResult +*/ + +type SnapshotForVolumeApiDeleteAllSnapshotsForVolumeOpts struct { + SnapshotPrefix optional.String +} + +func (a *SnapshotForVolumeApiService) DeleteAllSnapshotsForVolume(ctx context.Context, volumeId string, datacenter string, datastore string, localVarOptionals *SnapshotForVolumeApiDeleteAllSnapshotsForVolumeOpts) (SnapshotDeleteResult, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Delete") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue SnapshotDeleteResult + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/volumes/{volumeId}/snapshots" + localVarPath = strings.Replace(localVarPath, "{"+"volumeId"+"}", fmt.Sprintf("%v", volumeId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + localVarQueryParams.Add("datacenter", parameterToString(datacenter, "")) + localVarQueryParams.Add("datastore", parameterToString(datastore, "")) + if localVarOptionals != nil && localVarOptionals.SnapshotPrefix.IsSet() { + localVarQueryParams.Add("snapshotPrefix", parameterToString(localVarOptionals.SnapshotPrefix.Value(), "")) + } + // to determine the Content-Type header + localVarHttpContentTypes := []string{} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 202 { + var v SnapshotDeleteResult + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 0 { + var v ModelError + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} +/* +SnapshotForVolumeApiService Delete one specific snapshot for volume +Use this API to delete the specific snapshot of a volume. Snapshot deletion operation is performed asynchronously. It returns a job id, the status of which can be retrieved using `jobStatus` API. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param volumeId Unique Id of the volume. + * @param snapshotId Unique Id of the snapshot. + * @param datacenter Datacenter name to which volume and snapshot belongs to. + * @param datastore Datastore name to which volume and snapshot belongs to. +@return SnapshotDeleteResult +*/ +func (a *SnapshotForVolumeApiService) DeleteSnapshotForVolume(ctx context.Context, volumeId string, snapshotId string, datacenter string, datastore string) (SnapshotDeleteResult, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Delete") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue SnapshotDeleteResult + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/volumes/{volumeId}/snapshots/{snapshotId}" + localVarPath = strings.Replace(localVarPath, "{"+"volumeId"+"}", fmt.Sprintf("%v", volumeId), -1) + localVarPath = strings.Replace(localVarPath, "{"+"snapshotId"+"}", fmt.Sprintf("%v", snapshotId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + localVarQueryParams.Add("datacenter", parameterToString(datacenter, "")) + localVarQueryParams.Add("datastore", parameterToString(datastore, "")) + // to determine the Content-Type header + localVarHttpContentTypes := []string{} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 202 { + var v SnapshotDeleteResult + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 0 { + var v ModelError + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} +/* +SnapshotForVolumeApiService List all the snapshots for a specific volume +Use this API to retrieve all the snapshots for a specific volume. + * @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param volumeId Unique Id of the volume. + * @param datacenter Datacenter name to which volume and snapshots belong to. + * @param datastore Datastore name to which volume and snapshots belong to. + * @param optional nil or *SnapshotForVolumeApiListAllSnapshotsForVolumeOpts - Optional Parameters: + * @param "SnapshotPrefix" (optional.String) - (Optional) The snapshot prefix indicates the prefix used in snapshot description. If snapshot prefix is not specified, then it will list all snapshots of a volume. +@return SnapshotsForVolumeResult +*/ + +type SnapshotForVolumeApiListAllSnapshotsForVolumeOpts struct { + SnapshotPrefix optional.String +} + +func (a *SnapshotForVolumeApiService) ListAllSnapshotsForVolume(ctx context.Context, volumeId string, datacenter string, datastore string, localVarOptionals *SnapshotForVolumeApiListAllSnapshotsForVolumeOpts) (SnapshotsForVolumeResult, *http.Response, error) { + var ( + localVarHttpMethod = strings.ToUpper("Get") + localVarPostBody interface{} + localVarFileName string + localVarFileBytes []byte + localVarReturnValue SnapshotsForVolumeResult + ) + + // create path and map variables + localVarPath := a.client.cfg.BasePath + "/volumes/{volumeId}/snapshots" + localVarPath = strings.Replace(localVarPath, "{"+"volumeId"+"}", fmt.Sprintf("%v", volumeId), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + localVarQueryParams.Add("datacenter", parameterToString(datacenter, "")) + localVarQueryParams.Add("datastore", parameterToString(datastore, "")) + if localVarOptionals != nil && localVarOptionals.SnapshotPrefix.IsSet() { + localVarQueryParams.Add("snapshotPrefix", parameterToString(localVarOptionals.SnapshotPrefix.Value(), "")) + } + // to determine the Content-Type header + localVarHttpContentTypes := []string{} + + // set Content-Type header + localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes) + if localVarHttpContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHttpContentType + } + + // to determine the Accept header + localVarHttpHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts) + if localVarHttpHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHttpHeaderAccept + } + r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHttpResponse, err := a.client.callAPI(r) + if err != nil || localVarHttpResponse == nil { + return localVarReturnValue, localVarHttpResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) + localVarHttpResponse.Body.Close() + if err != nil { + return localVarReturnValue, localVarHttpResponse, err + } + + if localVarHttpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err == nil { + return localVarReturnValue, localVarHttpResponse, err + } + } + + if localVarHttpResponse.StatusCode >= 300 { + newErr := GenericSwaggerError{ + body: localVarBody, + error: localVarHttpResponse.Status, + } + if localVarHttpResponse.StatusCode == 200 { + var v SnapshotsForVolumeResult + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + if localVarHttpResponse.StatusCode == 0 { + var v ModelError + err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type")); + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHttpResponse, newErr + } + newErr.model = v + return localVarReturnValue, localVarHttpResponse, newErr + } + return localVarReturnValue, localVarHttpResponse, newErr + } + + return localVarReturnValue, localVarHttpResponse, nil +} diff --git a/client-sdk/go/client/client.go b/client-sdk/go/client/client.go index bdc4027..9bfbae9 100644 --- a/client-sdk/go/client/client.go +++ b/client-sdk/go/client/client.go @@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -51,11 +51,17 @@ type APIClient struct { // API Services + ClusterRecordKeepingApi *ClusterRecordKeepingApiService + DatastoreOperationsApi *DatastoreOperationsApiService JobDetailsApi *JobDetailsApiService + OrphanSnapshotApi *OrphanSnapshotApiService + OrphanVolumeApi *OrphanVolumeApiService + + SnapshotForVolumeApi *SnapshotForVolumeApiService } type service struct { @@ -74,9 +80,12 @@ func NewAPIClient(cfg *Configuration) *APIClient { c.common.client = c // API Services + c.ClusterRecordKeepingApi = (*ClusterRecordKeepingApiService)(&c.common) c.DatastoreOperationsApi = (*DatastoreOperationsApiService)(&c.common) c.JobDetailsApi = (*JobDetailsApiService)(&c.common) + c.OrphanSnapshotApi = (*OrphanSnapshotApiService)(&c.common) c.OrphanVolumeApi = (*OrphanVolumeApiService)(&c.common) + c.SnapshotForVolumeApi = (*SnapshotForVolumeApiService)(&c.common) return c } @@ -322,17 +331,17 @@ func (c *APIClient) prepareRequest( } func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) { - if strings.Contains(contentType, "application/xml") { - if err = xml.Unmarshal(b, v); err != nil { - return err - } - return nil - } else if strings.Contains(contentType, "application/json") { - if err = json.Unmarshal(b, v); err != nil { - return err + if strings.Contains(contentType, "application/xml") { + if err = xml.Unmarshal(b, v); err != nil { + return err + } + return nil + } else if strings.Contains(contentType, "application/json") { + if err = json.Unmarshal(b, v); err != nil { + return err + } + return nil } - return nil - } return errors.New("undefined response type") } diff --git a/client-sdk/go/client/model_job_result.go b/client-sdk/go/client/model_job_result.go index b801624..3ae412d 100644 --- a/client-sdk/go/client/model_job_result.go +++ b/client-sdk/go/client/model_job_result.go @@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/client-sdk/go/client/model_one_of_job_result_job_parameters.go b/client-sdk/go/client/model_one_of_job_result_job_parameters.go index b43bcda..d6aae78 100644 --- a/client-sdk/go/client/model_one_of_job_result_job_parameters.go +++ b/client-sdk/go/client/model_one_of_job_result_job_parameters.go @@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -17,4 +17,5 @@ package swagger type OneOfJobResultJobParameters struct { VolumeMigrationJobParameters + SnapshotDeletionJobParameters } diff --git a/client-sdk/go/client/model_one_of_job_result_job_status.go b/client-sdk/go/client/model_one_of_job_result_job_status.go index 0906244..f1b877d 100644 --- a/client-sdk/go/client/model_one_of_job_result_job_status.go +++ b/client-sdk/go/client/model_one_of_job_result_job_status.go @@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -17,4 +17,5 @@ package swagger type OneOfJobResultJobStatus struct { VolumeMigrationJobStatus + SnapshotDeletionJobStatus } diff --git a/client-sdk/go/client/model_orphan_snapshot.go b/client-sdk/go/client/model_orphan_snapshot.go new file mode 100644 index 0000000..27f3391 --- /dev/null +++ b/client-sdk/go/client/model_orphan_snapshot.go @@ -0,0 +1,31 @@ +/* +Copyright 2024 VMware, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package swagger + +type OrphanSnapshot struct { + // FCD Id of the orphan snapshot. + VolumeId string `json:"volumeId,omitempty"` + // Snapshot Id of the orphan snapshot. + VolumeSnapshotId string `json:"volumeSnapshotId,omitempty"` + // Datacenter where the orphan snapshot is located. + Datacenter string `json:"datacenter,omitempty"` + // Datastore where the orphan snapshot is located. + Datastore string `json:"datastore,omitempty"` + // Create time of the orphan snapshot. + CreateTime string `json:"createTime,omitempty"` + // Description of orphan snapshot + SnapshotDescription string `json:"snapshotDescription,omitempty"` +} diff --git a/client-sdk/go/client/model_orphan_snapshot_result.go b/client-sdk/go/client/model_orphan_snapshot_result.go new file mode 100644 index 0000000..3676b98 --- /dev/null +++ b/client-sdk/go/client/model_orphan_snapshot_result.go @@ -0,0 +1,29 @@ +/* +Copyright 2024 VMware, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package swagger + +type OrphanSnapshotResult struct { + // The total orphan snapshots returned. + TotalOrphanSnapshots int64 `json:"totalOrphanSnapshots,omitempty"` + // Limit specifies the maximum number of entries that are displayed in single request. + Limit int64 `json:"limit,omitempty"` + // Offset specifies the starting point of the result set. + Offset int64 `json:"offset,omitempty"` + // Array of orphan snapshots + OrphanSnapshots []OrphanSnapshot `json:"orphanSnapshots,omitempty"` + // Since the detection of orphan snapshots is an expensive operation, the operation is performed asynchronously at regular intervals. This API returns the list of orphan snapshots found in the last run of the operation. `retryAfterMinutes` indicates the time in minutes after which the next retry should be attempted to get the updated orphan snapshot list. + RetryAfterMinutes int64 `json:"retryAfterMinutes,omitempty"` +} diff --git a/client-sdk/go/client/model_orphan_volume.go b/client-sdk/go/client/model_orphan_volume.go index b373cdd..fd32980 100644 --- a/client-sdk/go/client/model_orphan_volume.go +++ b/client-sdk/go/client/model_orphan_volume.go @@ -16,16 +16,20 @@ limitations under the License. package swagger +// Orphan volumes are volumes that are present in the vSphere datastore but have no corresponding PersistentVolume in the Kubernetes cluster. Primarily, Orphan volumes are created when the CNS solution creates more than one volume for a Persistent Volume in the Kubernetes cluster. This can occur when the vCenter components are slow, storage is slow, vCenter service restarts, or there are connectivity issues between vCenter and ESXi hosts type OrphanVolume struct { // ID of the orphan volume. VolumeId string `json:"volumeId,omitempty"` // Name of the orphan volume. VolumeName string `json:"volumeName,omitempty"` + // Datacenter where the orphan volume is located. + Datacenter string `json:"datacenter,omitempty"` // Datastore where the orphan volume is located. Datastore string `json:"datastore,omitempty"` // Create time of the orphan volume. CreateTime string `json:"createTime,omitempty"` // Capacity of the orphan volume. - CapacityInMb int64 `json:"capacityInMb,omitempty"` - Details *OrphanVolumeDetails `json:"details,omitempty"` + CapacityInMb int64 `json:"capacityInMb,omitempty"` + + Details *OrphanVolumeDetails `json:"details,omitempty"` } diff --git a/client-sdk/go/client/model_orphan_volume_details.go b/client-sdk/go/client/model_orphan_volume_details.go index 3026df5..64feb2c 100644 --- a/client-sdk/go/client/model_orphan_volume_details.go +++ b/client-sdk/go/client/model_orphan_volume_details.go @@ -16,9 +16,10 @@ limitations under the License. package swagger +// OrphanVolumeDetails represents if the orphan volume is attached to a VM or not. type OrphanVolumeDetails struct { // Indicates whether the orphan volume is attached to a VM or not. - Attached bool `json:"attached,omitempty"` + Attached bool `json:"attached"` // The name of VM to which the orphan volume is attached. Vm string `json:"vm,omitempty"` } diff --git a/client-sdk/go/client/model_orphan_volume_result.go b/client-sdk/go/client/model_orphan_volume_result.go index cf6ca5c..0bfbec5 100644 --- a/client-sdk/go/client/model_orphan_volume_result.go +++ b/client-sdk/go/client/model_orphan_volume_result.go @@ -17,14 +17,18 @@ limitations under the License. package swagger type OrphanVolumeResult struct { - // The total orphan volumes returned. - TotalOrphans int64 `json:"totalOrphans"` - // This field is set only if includeDetails is set to true. - TotalOrphansAttached int64 `json:"totalOrphansAttached,omitempty"` - // This field is set only if includeDetails is set to true. - TotalOrphansDetached int64 `json:"totalOrphansDetached,omitempty"` - // Array of orphan volumes + // The total number of orphan volumes returned. + TotalOrphans int32 `json:"totalOrphans"` + // The total number of orphan volumes that are attached to a VM. This field is returned only if includeDetails is set to true. + TotalOrphansAttached int32 `json:"totalOrphansAttached,omitempty"` + // The total number of orphan volumes that are not attached to a VM. This field is set only if includeDetails is set to true. + TotalOrphansDetached int32 `json:"totalOrphansDetached,omitempty"` + // Array of orphan volumes. OrphanVolumes []OrphanVolume `json:"orphanVolumes"` // The time in minutes after which the next retry should be attempted to get the updated orphan volume list. - RetryAfterMinutes int64 `json:"retryAfterMinutes"` + RetryAfterMinutes int32 `json:"retryAfterMinutes"` + // The maximum number of orphan volumes returned. + Limit int32 `json:"limit,omitempty"` + // The offset of the next page if there are more orphan volumes to query. + NextOffset int32 `json:"nextOffset,omitempty"` } diff --git a/client-sdk/go/client/model_snapshot_delete_result.go b/client-sdk/go/client/model_snapshot_delete_result.go new file mode 100644 index 0000000..d4cf282 --- /dev/null +++ b/client-sdk/go/client/model_snapshot_delete_result.go @@ -0,0 +1,21 @@ +/* +Copyright 2024 VMware, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package swagger + +type SnapshotDeleteResult struct { + // Identifier of the snapshot deletion job submitted + JobId string `json:"jobId,omitempty"` +} diff --git a/client-sdk/go/client/model_snapshot_deletion_job_parameters.go b/client-sdk/go/client/model_snapshot_deletion_job_parameters.go new file mode 100644 index 0000000..77b03d1 --- /dev/null +++ b/client-sdk/go/client/model_snapshot_deletion_job_parameters.go @@ -0,0 +1,29 @@ +/* +Copyright 2024 VMware, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package swagger + +type SnapshotDeletionJobParameters struct { + // fcdId is the identifier of FCD. + FcdId string `json:"fcdId,omitempty"` + // snapshotId is the identifier of snapshot. + SnapshotId string `json:"snapshotId,omitempty"` + // datacenter to which snapshots belong. + Datacenter string `json:"datacenter,omitempty"` + // datastores to which snapshots belong. + Datastores []string `json:"datastores,omitempty"` + // snapshotPrefix is the prefix used in the snapshot description. + SnapshotPrefix string `json:"snapshotPrefix,omitempty"` +} diff --git a/client-sdk/go/client/model_snapshot_deletion_job_status.go b/client-sdk/go/client/model_snapshot_deletion_job_status.go new file mode 100644 index 0000000..afca8cb --- /dev/null +++ b/client-sdk/go/client/model_snapshot_deletion_job_status.go @@ -0,0 +1,34 @@ +/* +Copyright 2024 VMware, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package swagger +import ( + "time" +) + +type SnapshotDeletionJobStatus struct { + // Total snapshots which will be deleted as part of this job. + TotalSnapshotsPlannedForDeletion int32 `json:"totalSnapshotsPlannedForDeletion,omitempty"` + // Total snapshots which got successfully deleted as part of this job. + TotalSnapshotsSuccessfullyDeleted int32 `json:"totalSnapshotsSuccessfullyDeleted,omitempty"` + // Total snapshots whose deletion failed as part of this job. + TotalSnapshotsWithFailedDeletion int32 `json:"totalSnapshotsWithFailedDeletion,omitempty"` + // Time at which the job started processing. + StartTime time.Time `json:"startTime,omitempty"` + // Time at which the job completed processing. + EndTime time.Time `json:"endTime,omitempty"` + // Array of status of individual snapshot deletion tasks in the job. + SnapshotDeletionTasks []SnapshotDeletionTaskStatus `json:"snapshotDeletionTasks,omitempty"` +} diff --git a/client-sdk/go/client/model_snapshot_deletion_task_status.go b/client-sdk/go/client/model_snapshot_deletion_task_status.go new file mode 100644 index 0000000..8b07f58 --- /dev/null +++ b/client-sdk/go/client/model_snapshot_deletion_task_status.go @@ -0,0 +1,39 @@ +/* +Copyright 2024 VMware, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package swagger +import ( + "time" +) + +type SnapshotDeletionTaskStatus struct { + // Id of the FCD to which snapshot belongs. + FcdId string `json:"fcdId,omitempty"` + // Id of the snapshot to be deleted. + SnapshotId string `json:"snapshotId,omitempty"` + // datacenter to which snapshot belongs. + Datacenter string `json:"datacenter,omitempty"` + // datastore to which snapshot belongs. + Datastore string `json:"datastore,omitempty"` + // description of the snapshot. + SnapshotDescription string `json:"snapshotDescription,omitempty"` + // Current phase of the snapshot deletion task. + Phase string `json:"phase,omitempty"` + // The timestamp at which the task was invoked. + TaskStartTime time.Time `json:"taskStartTime,omitempty"` + // The timestamp at which the task finished. + TaskEndTime time.Time `json:"taskEndTime,omitempty"` + Error_ *Fault `json:"error,omitempty"` +} diff --git a/client-sdk/go/client/model_snapshot_details.go b/client-sdk/go/client/model_snapshot_details.go new file mode 100644 index 0000000..5ed4bd4 --- /dev/null +++ b/client-sdk/go/client/model_snapshot_details.go @@ -0,0 +1,33 @@ +/* +Copyright 2024 VMware, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package swagger + +type SnapshotDetails struct { + // Id of the snapshot. + SnapshotId string `json:"snapshotId,omitempty"` + // Id of the volume. + VolumeId string `json:"volumeId,omitempty"` + // Time when snapshot is created. + CreateTime string `json:"createTime,omitempty"` + // Description of the snapshot. + SnapshotDescription string `json:"snapshotDescription,omitempty"` + // Phase of the sanpshot if it is created by Velero vSphere plugin. + VelerovSpherePluginSnapshotPhase string `json:"velerovSpherePluginSnapshotPhase,omitempty"` + // Associated VolumeSnapshotContent name if snapshot is created by CSI driver. + AssociatedVolumeSnapshotContent string `json:"associatedVolumeSnapshotContent,omitempty"` + // Owner who created this snapshot. e.g. vSphere CSI driver, Velero vSphere plugin etc. + Owner string `json:"owner,omitempty"` +} diff --git a/client-sdk/go/client/model_snapshots_for_volume_result.go b/client-sdk/go/client/model_snapshots_for_volume_result.go new file mode 100644 index 0000000..b65d27f --- /dev/null +++ b/client-sdk/go/client/model_snapshots_for_volume_result.go @@ -0,0 +1,20 @@ +/* +Copyright 2024 VMware, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package swagger + +type SnapshotsForVolumeResult struct { + Snapshots *SnapshotDetails `json:"Snapshots,omitempty"` +} diff --git a/client-sdk/go/examples/basicauth_client.go b/client-sdk/go/examples/basicauth_client.go index 3ff17b7..47a5c59 100644 --- a/client-sdk/go/examples/basicauth_client.go +++ b/client-sdk/go/examples/basicauth_client.go @@ -139,4 +139,48 @@ func main() { // logger.Info("Result", "result", res) //This gives the result in json format // logger.Info("HTTP status", "status", resp.Status) //======================================================= + + //======List orphan snapshots====== + // osopts := &apiclient.OrphanSnapshotApiOrphanSnapshotsListOpts{ + // Datacenter: optional.NewString("VSAN-DC"), + // Datastores: optional.NewString("vsanDatastore"), + // SnapshotPrefix: optional.NewString("snapshot"), + // Limit: optional.NewInt64(50), + // Offset: optional.NewInt64(0), + // } + + // osres, resp, err := client.OrphanSnapshotApi.OrphanSnapshotsList(ctx, osopts) + // if err != nil { + // logger.Error(err, "failed to list orphan snapshots") + // } + // logger.Info("Result", "result", osres) //This gives the result in json format + // logger.Info("HTTP status", "status", resp.Status) + //======================================================= + + //======Delete orphan snapshots====== + // osdopts := &apiclient.OrphanSnapshotApiOrphanSnapshotsDeleteOpts{ + // Datacenter: optional.NewString("VSAN-DC"), + // Datastores: optional.NewString("vsanDatastore"), + // SnapshotPrefix: optional.NewString("snapshot"), + // } + + // osdres, resp, err := client.OrphanSnapshotApi.OrphanSnapshotsDelete(ctx, osdopts) + // if err != nil { + // logger.Error(err, "failed to delete orphan snapshots") + // } + // logger.Info("Result", "result", osdres) //This gives the result in json format + // logger.Info("HTTP status", "status", resp.Status) + //======================================================= + + //====== Job status ======== + // jobId := "snapshotdeletionjob-94539b64-7cf4-11ec-94b8-165555b18754" + + // res, resp, err := client.JobDetailsApi.GetJobStatus(ctx, jobId) + // if err != nil { + // logger.Error(err, "failed to get job status snapshot deletion job") + // } + + // logger.Info("Result", "result", res) //This gives the result in json format + // logger.Info("HTTP status", "status", resp.Status) + //======================================================= } diff --git a/client-sdk/go/go.mod b/client-sdk/go/go.mod index 00c9e9f..7482706 100644 --- a/client-sdk/go/go.mod +++ b/client-sdk/go/go.mod @@ -1,22 +1,60 @@ module cns.vmware.com/cns-manager -go 1.18 +go 1.19 require ( github.com/antihax/optional v1.0.0 github.com/go-logr/zapr v1.2.3 - go.uber.org/zap v1.21.0 - golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c - sigs.k8s.io/controller-runtime v0.12.3 + go.uber.org/zap v1.24.0 + golang.org/x/oauth2 v0.5.0 + sigs.k8s.io/controller-runtime v0.13.0 ) require ( - github.com/go-logr/logr v1.2.2 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-logr/logr v1.2.3 // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/stretchr/testify v1.8.0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/onsi/gomega v1.27.0 // indirect + github.com/stretchr/testify v1.8.1 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.7.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect + k8s.io/apimachinery v0.25.2 // indirect +) + +replace ( + github.com/go-logr/logr => github.com/go-logr/logr v1.2.0 + github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.4.1 + github.com/kubernetes-csi/csi-lib-utils => github.com/kubernetes-csi/csi-lib-utils v0.11.0 + k8s.io/api => k8s.io/api v0.25.2 + k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.25.2 + k8s.io/apimachinery => k8s.io/apimachinery v0.25.2 + k8s.io/apiserver => k8s.io/apiserver v0.25.2 + k8s.io/cli-runtime => k8s.io/cli-runtime v0.25.2 + k8s.io/client-go => k8s.io/client-go v0.25.2 + k8s.io/cloud-provider => k8s.io/cloud-provider v0.25.2 + k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.25.2 + k8s.io/code-generator => k8s.io/code-generator v0.25.2 + k8s.io/component-base => k8s.io/component-base v0.25.2 + k8s.io/component-helpers => k8s.io/component-helpers v0.25.2 + k8s.io/controller-manager => k8s.io/controller-manager v0.25.2 + k8s.io/cri-api => k8s.io/cri-api v0.25.2 + k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.25.2 + k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.25.2 + k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.25.2 + k8s.io/kube-proxy => k8s.io/kube-proxy v0.25.2 + k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.25.2 + k8s.io/kubectl => k8s.io/kubectl v0.25.2 + k8s.io/kubelet => k8s.io/kubelet v0.25.2 + k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.25.2 + k8s.io/metrics => k8s.io/metrics v0.25.2 + k8s.io/mount-utils => k8s.io/mount-utils v0.24.6 + k8s.io/node-api => k8s.io/node-api v0.25.2 + k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.25.2 + k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.25.2 + k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.25.2 + k8s.io/sample-controller => k8s.io/sample-controller v0.25.2 ) diff --git a/client-sdk/go/go.sum b/client-sdk/go/go.sum index 9104009..3aacc4a 100644 --- a/client-sdk/go/go.sum +++ b/client-sdk/go/go.sum @@ -5,9 +5,10 @@ github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -15,13 +16,15 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.27.0 h1:QLidEla4bXUuZVFa4KX6JHCsuGgbi85LC/pCHrt/O08= +github.com/onsi/gomega v1.27.0/go.mod h1:i189pavgK95OSIipFBa74gC2V4qrQuvjuyGEr3GmbXA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -29,74 +32,60 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c h1:q3gFqPqH7NVofKo3c3yETAP//pPI+G5mvB7qqj1Y5kY= -golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/apimachinery v0.24.2 h1:5QlH9SL2C8KMcrNJPor+LbXVTaZRReml7svPEh4OKDM= -sigs.k8s.io/controller-runtime v0.12.3 h1:FCM8xeY/FI8hoAfh/V4XbbYMY20gElh9yh+A98usMio= -sigs.k8s.io/controller-runtime v0.12.3/go.mod h1:qKsk4WE6zW2Hfj0G4v10EnNB2jMG1C+NTb8h+DwCoU0= +k8s.io/apimachinery v0.25.2 h1:WbxfAjCx+AeN8Ilp9joWnyJ6xu9OMeS/fsfjK/5zaQs= +k8s.io/apimachinery v0.25.2/go.mod h1:hqqA1X0bsgsxI6dXsJ4HnNTBOmJNxyPp8dw3u2fSHwA= +sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= +sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= diff --git a/deploy/basic-auth/deploy-template.yaml b/deploy/basic-auth/deploy-template.yaml index f19fb85..ca77d8f 100644 --- a/deploy/basic-auth/deploy-template.yaml +++ b/deploy/basic-auth/deploy-template.yaml @@ -6,7 +6,7 @@ metadata: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: cns-manager + name: cns-manager-syspriv-rolebinding subjects: - kind: ServiceAccount name: cns-manager @@ -38,13 +38,13 @@ spec: properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object @@ -96,13 +96,13 @@ spec: properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object @@ -180,13 +180,13 @@ spec: properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object @@ -238,6 +238,185 @@ status: conditions: [] storedVersions: [] --- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: snapshotdeletionjobs.cnsmanager.cns.vmware.com +spec: + group: cnsmanager.cns.vmware.com + names: + kind: SnapshotDeletionJob + listKind: SnapshotDeletionJobList + plural: snapshotdeletionjobs + singular: snapshotdeletionjob + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: SnapshotDeletionJob is the Schema for the snapshotdeletionjobs + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: SnapshotDeletionJobSpec defines the desired state of SnapshotDeletionJob + properties: + datacenter: + description: Datacenter refers to the datacenter the snapshot belongs to. + type: string + datastores: + description: Datastores refer to the datastores to which snapshots + belong. + items: + type: string + type: array + fcdId: + description: FcdId refers to the Id of FCD + type: string + snapshotPrefix: + default: snapshot + description: SnapshotPrefix is the prefix used in the snapshot name. + type: string + snapshotId: + description: SnapshotId refers to Id of the snapshot + type: string + required: + - snapshotPrefix + type: object + status: + description: SnapshotDeletionJobStatus defines the observed state of SnapshotDeletionJob + properties: + endTime: + description: End time of the snapshot deletion job + format: date-time + type: string + overallPhase: + description: Overall phase of the snapshot deletion job + type: string + snapshotDeletionTasks: + description: Name of snapshotdeletiontask instances created for each + snapshot. + items: + type: string + type: array + startTime: + description: Start time of the snapshot deletion job + format: date-time + type: string + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: snapshotdeletiontasks.cnsmanager.cns.vmware.com +spec: + group: cnsmanager.cns.vmware.com + names: + kind: SnapshotDeletionTask + listKind: SnapshotDeletionTaskList + plural: snapshotdeletiontasks + singular: snapshotdeletiontask + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: SnapshotDeletionTask is the Schema for the snapshotdeletiontasks + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: SnapshotDeletionTaskSpec defines the desired state of SnapshotDeletionTask + properties: + datacenter: + description: Datacenter refers to the datacenter the snapshot belongs to + type: string + datastore: + description: Datastore refers to the datastore to which snapshot belongs + type: string + fcdId: + description: FcdId refers to Id of FCD + type: string + snapshotId: + description: SnapshotId refers to Id of the snapshot + type: string + required: + - datacenter + - datastore + - fcdId + - snapshotId + type: object + status: + description: SnapshotDeletionTaskStatus defines the observed state of + SnapshotDeletionTask + properties: + cnsTaskId: + description: CnsTaskID refers to the task ID in CNS for snapshot deletion + type: string + endTime: + description: Time at which the task finished processing. + format: date-time + type: string + error: + description: Error indicates any error while running the task + type: string + phase: + description: Phase describes the current phase of the task + type: string + snapshotDescription: + description: SnapshotDescription refers to the description of the + snapshot. + type: string + startTime: + description: The timestamp at which the task was invoked + format: date-time + type: string + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: @@ -250,6 +429,8 @@ rules: - orphanvolumestats - volumemigrationjobs - volumemigrationtasks + - snapshotdeletionjobs + - snapshotdeletiontasks verbs: - create - delete @@ -264,6 +445,8 @@ rules: - orphanvolumestats/status - volumemigrationjobs/status - volumemigrationtasks/status + - snapshotdeletionjobs/status + - snapshotdeletiontasks/status verbs: - get - patch @@ -306,14 +489,19 @@ data: config.json: | { "auth-type": "%AUTH_TYPE%", - "snapshot_prefix": "snapshot", + "snapshot-prefixes": ["snapshot", "AstrolabeSnapshot"], "auto-delete-ov": "disable", + "monitor-orphan-snapshots": true, + "auto-delete-orphan-snapshots": false, "cns-manager-namespace": "%CNS_MANAGER_NAMESPACE%", "max-volume-migration-job-workers": "10", "max-volume-migration-task-workers": "10", "volume-migration-job-cleanup-elapse-time-mins": "720", "volume-migration-job-cleanup-interval-mins": "30", - "orphan-volume-detection-interval-mins": "50" + "snapshot-deletion-job-cleanup-elapse-time-mins": "720", + "snapshot-deletion-job-cleanup-interval-mins": "30", + "orphan-volume-detection-interval-mins": "50", + "orphan-snapshot-detection-interval-mins": "60" } --- apiVersion: apps/v1 @@ -380,7 +568,7 @@ spec: - name: swagger-api mountPath: /api - name: cns-manager - image: projects.registry.vmware.com/cns_manager/cns-manager:r0.2.0 + image: projects.registry.vmware.com/cns_manager/cns-manager:r0.3.0-rc.1 resources: requests: cpu: 500m diff --git a/deploy/basic-auth/nginx.conf b/deploy/basic-auth/nginx.conf index 7054e30..15686bf 100644 --- a/deploy/basic-auth/nginx.conf +++ b/deploy/basic-auth/nginx.conf @@ -54,4 +54,4 @@ http { proxy_read_timeout 30m; } } -} \ No newline at end of file +} diff --git a/deploy/deploy.sh b/deploy/deploy.sh index 22f865a..f0cb0a3 100755 --- a/deploy/deploy.sh +++ b/deploy/deploy.sh @@ -17,7 +17,7 @@ TLS_FLAG=$6 if ! [ $AUTH_MECHANISM == "basicauth" -o $AUTH_MECHANISM == "oauth2" ] then - echo "Auth mechanism needs to be either basicauth or auth2." + echo "Auth mechanism needs to be either basicauth or oauth2." exit 1 fi diff --git a/deploy/oauth2/deploy-template.yaml b/deploy/oauth2/deploy-template.yaml index 71d4a24..dba7aed 100644 --- a/deploy/oauth2/deploy-template.yaml +++ b/deploy/oauth2/deploy-template.yaml @@ -6,7 +6,7 @@ metadata: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: cns-manager + name: cns-manager-syspriv-rolebinding subjects: - kind: ServiceAccount name: cns-manager @@ -38,13 +38,13 @@ spec: properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object @@ -96,13 +96,13 @@ spec: properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object @@ -180,13 +180,13 @@ spec: properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object @@ -238,6 +238,185 @@ status: conditions: [] storedVersions: [] --- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: snapshotdeletionjobs.cnsmanager.cns.vmware.com +spec: + group: cnsmanager.cns.vmware.com + names: + kind: SnapshotDeletionJob + listKind: SnapshotDeletionJobList + plural: snapshotdeletionjobs + singular: snapshotdeletionjob + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: SnapshotDeletionJob is the Schema for the snapshotdeletionjobs + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: SnapshotDeletionJobSpec defines the desired state of SnapshotDeletionJob + properties: + datacenter: + description: Datacenter refers to the datacenter the snapshot belongs to. + type: string + datastores: + description: Datastores refer to the datastores to which snapshots + belong. + items: + type: string + type: array + fcdId: + description: FcdId refers to the Id of FCD + type: string + snapshotPrefix: + default: snapshot + description: SnapshotPrefix is the prefix used in the snapshot name. + type: string + snapshotId: + description: SnapshotId refers to Id of the snapshot + type: string + required: + - snapshotPrefix + type: object + status: + description: SnapshotDeletionJobStatus defines the observed state of SnapshotDeletionJob + properties: + endTime: + description: End time of the snapshot deletion job + format: date-time + type: string + overallPhase: + description: Overall phase of the snapshot deletion job + type: string + snapshotDeletionTasks: + description: Name of snapshotdeletiontask instances created for each + snapshot. + items: + type: string + type: array + startTime: + description: Start time of the snapshot deletion job + format: date-time + type: string + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: snapshotdeletiontasks.cnsmanager.cns.vmware.com +spec: + group: cnsmanager.cns.vmware.com + names: + kind: SnapshotDeletionTask + listKind: SnapshotDeletionTaskList + plural: snapshotdeletiontasks + singular: snapshotdeletiontask + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: SnapshotDeletionTask is the Schema for the snapshotdeletiontasks + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: SnapshotDeletionTaskSpec defines the desired state of SnapshotDeletionTask + properties: + datacenter: + description: Datacenter refers to the datacenter the snapshot belongs to + type: string + datastore: + description: Datastore refers to the datastore to which snapshot belongs + type: string + fcdId: + description: FcdId refers to Id of FCD + type: string + snapshotId: + description: SnapshotId refers to id of the snapshot + type: string + required: + - datacenter + - datastore + - fcdId + - snapshotId + type: object + status: + description: SnapshotDeletionTaskStatus defines the observed state of + SnapshotDeletionTask + properties: + cnsTaskId: + description: CnsTaskID refers to the task ID in CNS for snapshot deletion + type: string + endTime: + description: Time at which the task finished processing. + format: date-time + type: string + error: + description: Error indicates any error while running the task + type: string + phase: + description: Phase describes the current phase of the task + type: string + snapshotDescription: + description: SnapshotDescription refers to the description of the + snapshot. + type: string + startTime: + description: The timestamp at which the task was invoked + format: date-time + type: string + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: @@ -250,6 +429,8 @@ rules: - orphanvolumestats - volumemigrationjobs - volumemigrationtasks + - snapshotdeletionjobs + - snapshotdeletiontasks verbs: - create - delete @@ -264,6 +445,8 @@ rules: - orphanvolumestats/status - volumemigrationjobs/status - volumemigrationtasks/status + - snapshotdeletionjobs/status + - snapshotdeletiontasks/status verbs: - get - patch @@ -279,7 +462,7 @@ rules: - apiGroups: - "" resources: - - secrets + - secrets verbs: - get - list @@ -307,14 +490,19 @@ data: { "auth-type": "%AUTH_TYPE%", "allowedUsers": ["johndoe@helloabc.com"], - "snapshot_prefix": "snapshot", + "snapshot-prefixes": ["snapshot", "AstrolabeSnapshot"], "auto-delete-ov": "disable", + "monitor-orphan-snapshots": true, + "auto-delete-orphan-snapshots": false, "cns-manager-namespace": "%CNS_MANAGER_NAMESPACE%", "max-volume-migration-job-workers": "10", "max-volume-migration-task-workers": "10", "volume-migration-job-cleanup-elapse-time-mins": "720", "volume-migration-job-cleanup-interval-mins": "30", - "orphan-volume-detection-interval-mins": "50" + "snapshot-deletion-job-cleanup-elapse-time-mins": "720", + "snapshot-deletion-job-cleanup-interval-mins": "30", + "orphan-volume-detection-interval-mins": "50", + "orphan-snapshot-detection-interval-mins": "60" } --- apiVersion: apps/v1 @@ -416,7 +604,7 @@ spec: - name: swagger-api mountPath: /api - name: cns-manager - image: projects.registry.vmware.com/cns_manager/cns-manager:r0.2.0 + image: projects.registry.vmware.com/cns_manager/cns-manager:r0.3.0-rc.1 resources: requests: cpu: 500m diff --git a/deploy/oauth2/nginx.conf b/deploy/oauth2/nginx.conf index 20bf36d..a658e1b 100644 --- a/deploy/oauth2/nginx.conf +++ b/deploy/oauth2/nginx.conf @@ -56,25 +56,28 @@ http { proxy_send_timeout 300; } - #Since /waitforjob is supposed to be a blocking API call, set a long timeout of 1d - location /1.0.0/waitforjob { - auth_request /oauth2/auth; - # pass information via X-User and X-Forwarded-Email headers to backend, - # requires running with --set-xauthrequest flag - auth_request_set $user $upstream_http_x_auth_request_user; - auth_request_set $email $upstream_http_x_auth_request_email; - proxy_set_header X-User $user; - proxy_set_header X-Forwarded-Email $email; - # if you enabled --cookie-refresh, this is needed for it to work with auth_request - auth_request_set $auth_cookie $upstream_http_set_cookie; - add_header Set-Cookie $auth_cookie; - - proxy_pass http://localhost:8100; - proxy_set_header Host $host; - proxy_buffering on; - proxy_read_timeout 1d; - proxy_connect_timeout 1d; - proxy_send_timeout 1d; + #Since /waitforjob is supposed to be a blocking API call, set a long timeout of 1d + location /1.0.0/waitforjob { + auth_request /oauth2/auth; + + # pass information via X-User and X-Forwarded-Email headers to backend, + # requires running with --set-xauthrequest flag + auth_request_set $user $upstream_http_x_auth_request_user; + auth_request_set $email $upstream_http_x_auth_request_email; + proxy_set_header X-User $user; + proxy_set_header X-Forwarded-Email $email; + + # if you enabled --cookie-refresh, this is needed for it to work with auth_request + auth_request_set $auth_cookie $upstream_http_set_cookie; + add_header Set-Cookie $auth_cookie; + + proxy_pass http://localhost:8100; + proxy_set_header Host $host; + proxy_buffering on; + + proxy_read_timeout 1d; + proxy_connect_timeout 1d; + proxy_send_timeout 1d; } # Since DELETE /orphanvolumes could be a long running operation, @@ -120,4 +123,4 @@ http { proxy_pass_request_body off; } } -} \ No newline at end of file +} diff --git a/deploy/swagger-template.yaml b/deploy/swagger-template.yaml index a212926..a206952 100644 --- a/deploy/swagger-template.yaml +++ b/deploy/swagger-template.yaml @@ -19,8 +19,12 @@ tags: description: Operations invoked directly on datastores. - name: JobDetails description: Operations related to CNS manager asynchronous jobs. - - name: OrphanVolume + - name: OrphanVolume description: Everything about orphan volumes. + - name: OrphanSnapshot + description: Everything about orphan snapshots. + - name: SnapshotForVolume + description: Operations related to volume Snapshots. paths: /listregisteredclusters: get: @@ -49,11 +53,13 @@ paths: post: tags: - ClusterRecordKeeping - summary: Register a cluster with the CNS Manager. - description: "The API takes kubeconfig of a given cluster as an input. Make sure to copy the \ - \ contents of the Cluster KubeConfig to a file. The kubeconfig is stored securely inside \ - \ a k8s secret on the cluster where CNS manager is deployed. The API additionally takes optional \ - \ params to read cluster-id set for CSI driver from the CSI secret." + summary: Register a Kubernetes cluster with CNS Manager. + description: > + The API takes kubeconfig of a given cluster as an input. Make sure to copy the + contents of the Cluster KubeConfig to a file. The kubeconfig is stored securely inside + a k8s secret on the cluster where CNS manager is deployed. + The API additionally takes optional params like CSI driver clusterId or CSI driver namespace and config secret name + to read cluster-id from the CSI secret. operationId: registercluster requestBody: content: @@ -65,29 +71,40 @@ paths: type: string format: binary description: A file with cluster kubeconfig content. - allowEmptyValue: false - required: true required: - clusterKubeConfigFile parameters: - name: csiDriverSecretName in: query - description: Refers to the name of the config secret of vsphere-csi-driver. + description: (Optional) Refers to the name of the config secret of vsphere-csi-driver. style: form explode: true schema: type: string format: string default: vsphere-config-secret - - name: csiDriverSecretNamespace + - name: csiDriverNamespace in: query - description: Refers to the namespace of the config secret of vsphere-csi-driver. + description: (Optional) Refers to the namespace of vsphere-csi-driver. style: form explode: true schema: type: string - format: string + format: string default: vmware-system-csi + - name: clusterId + in: query + description: > + (Optional) Cluster Id of the cluster to be registered with the CNS Manager. + This cluster Id needs to be the same that's used in the vSphere CSI driver config of the Kubernetes cluster. + For vanilla Kubernetes distributions deployed using [VMware's recommended way](https://docs.vmware.com/en/VMware-vSphere-Container-Storage-Plug-in/2.0/vmware-vsphere-csp-getting-started/GUID-BFF39F1D-F70A-4360-ABC9-85BDAFBE8864.html), + it will be present in the CSI secret and will be auto-computed from the provided kubeConfig. + For other Kubernetes distributions, please check their docs to determine how they're configuring clusterId for the vSphere CSI driver in the Kubernetes cluster. + style: form + explode: true + schema: + type: string + format: string responses: "200": description: Returns RegisterClusterResult. @@ -202,9 +219,9 @@ paths: - name: sourceDatastore in: query description: "(Optional) Name of the source datastore. Specify only if all\ - \ volumes from source datastore need to be migrated to destination datastore,\ - \ and don't specify fcd Ids in that case. If specific list of fcd Ids is\ - \ provided, then source datastore field will be ignored." + \ volumes from source datastore need to be migrated to destination datastore,\ + \ and don't specify fcd Ids in that case. If specific list of fcd Ids is\ + \ provided, then source datastore field will be ignored." required: false style: form explode: true @@ -223,7 +240,7 @@ paths: - name: fcdIdsToMigrate in: query description: "(Optional) Array of FCD ids to migrate. If not specified, all\ - \ volumes from source datastore will be migrated to destination datastore." + \ volumes from source datastore will be migrated to destination datastore." required: false style: form explode: true @@ -244,9 +261,9 @@ paths: - name: skipVolumeAccessibilityCheck in: query description: "(Optional) If this flag is set to 'true', it will force migrate the volumes without\ - \ checking if they will be accessible on target datastore from all cluster nodes(or topology-matching\ - \ nodes in a topology-aware environment). This may affect the application availability if it gets scheduled\ - \ on a cluster node that can't access the target datastore. So it's NOT recommended to set this flag to true." + \ checking if they will be accessible on target datastore from all cluster nodes(or topology-matching\ + \ nodes in a topology-aware environment). This may affect the application availability if it gets scheduled\ + \ on a cluster node that can't access the target datastore. So it's NOT recommended to set this flag to true." required: false style: form explode: true @@ -306,22 +323,22 @@ paths: /waitforjob: get: tags: - - JobDetails + - JobDetails summary: Wait until a job is successful or failed. description: "This is a blocking API that waits for job to get successful or \n\ fail. Unlike `getJobStatus` API which fetches the current\nstatus of the job,\ \ this will wait for the job to finish before \nreturning the job result response." operationId: waitForJob parameters: - - name: jobId - in: query - description: Job Id for which to wait to complete. - required: true - style: form - explode: true - schema: - type: string - format: string + - name: jobId + in: query + description: Job Id for which to wait to complete. + required: true + style: form + explode: true + schema: + type: string + format: string responses: "200": description: Returns JobResult. @@ -332,10 +349,10 @@ paths: /suspendvolumeprovisioning: post: tags: - - DatastoreOperations + - DatastoreOperations summary: Suspend Create Volume operation on datastore. description: "This API will block creation of new File and Block volumes on the specified datastore. To unblock volume provisioning, invoke ResumeVolumeProvisioning API. \n\ - Other volume operations like attach, detach, delete etc. will not get affected for existing volumes." + Other volume operations like attach, detach, delete etc. will not get affected for existing volumes." operationId: suspendVolumeProvisioning parameters: - name: datacenter @@ -372,7 +389,7 @@ paths: /resumevolumeprovisioning: post: tags: - - DatastoreOperations + - DatastoreOperations summary: Resume Create Volume operation on datastore. description: "This API will unblock creation of new File and Block volumes on the specified datastore. To block volume provisioning, invoke SuspendVolumeProvisioning API." operationId: resumeVolumeProvisioning @@ -408,132 +425,519 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - /orphanvolumes: - get: - tags: - - OrphanVolume - summary: List all the orphan volumes. - description: >- - Returns a list of orphan volumes for the given input parameters, which could be attached or detached. - Since the detection of orphan volumes is an expensive operation, the operation is performed asynchronously at regular intervals. - This API returns the list of orphan volumes found in the last run of the operation. - - - The response body contains the following fields: - 1. `TotalOrphans` - The total number of orphan volumes found. - - 2. `OrphanVolumes` - The list of orphan volumes found. - - 3. `RetryAfterMinutes` - The time in minutes after which the next retry should be attempted to get the updated orphan volume list. - - 4. `TotalOrphansAttached` - The total number of orphan volumes found that are attached to a VM. - - 5. `TotalOrphansDetached` - The total number of orphan volumes found that are detached. - - - Orphan volumes are safe to delete since there is no PersistentVolume in the Kubernetes cluster referring to them. - operationId: orphanVolumeList - parameters: - - name: includeDetails - in: query - description: Set to "true" to get a detailed dump of the orphan volume. - required: true - style: form - explode: true - schema: - type: boolean - format: boolean - default: false - - name: datacenter - in: query - description: (Optional) Datacenter name to narrow down the orphan volume search. - required: false - style: form - explode: true - schema: - type: string - format: string - - name: datastores - in: query - description: (Optional) List of comma-separated datastores. Specify only if - the `datacenter` param is specified. - required: false - style: form - explode: true - schema: - type: string - format: string - responses: - "200": - description: Returns OrphanVolumeResult. - content: - application/json: - schema: - $ref: '#/components/schemas/OrphanVolumeResult' - headers: - X-Retry-After: - description: The number of seconds to wait before retrying the request. - schema: - type: string - default: - description: unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - delete: - tags: - - OrphanVolume - summary: Delete orphan volumes. - description: Delete the orphan volumes for the given criteria. - operationId: orphanVolumeDelete - parameters: - - name: deleteAttachedOrphans - in: query - description: >- - Set to `true` to delete attached orphans. When set to `true`, - the API will detach the orphan volume from the VM before deleting it. - required: true - style: form - explode: true - schema: - type: boolean - format: boolean - default: false - - name: datacenter - in: query - description: (Optional) Datacenter name to narrow down the deletion of orphan volumes to. - required: false - style: form - explode: true - schema: - type: string - format: string - - name: datastores - in: query - description: (Optional) List of comma-separated datastores to narrow down - the deletion of orphan volumes to. Specify only if the `datacenter` param - is specified. - required: false - style: form - explode: true - schema: - type: string - format: string - responses: - "200": - description: Returns OrphanVolumeDeleteResult. - content: - application/json: - schema: - $ref: '#/components/schemas/OrphanVolumeDeleteResult' - default: - description: unexpected error - content: - application/json: - schema: + /orphanvolumes: + get: + tags: + - OrphanVolume + summary: List all the orphan volumes. + description: > + Returns a list of orphan volumes for the given input parameters, which could be attached or detached. + Since the detection of orphan volumes is an expensive operation, the operation is performed asynchronously at regular intervals. + This API returns the list of orphan volumes found in the last run of the operation. + + + If the request is successful, the response will contain the following: + + 1. `TotalOrphans` - The total number of orphan volumes found. + + 2. `OrphanVolumes` - The list of orphan volumes found. + + 3. `RetryAfterMinutes` - The time in minutes after which the next retry should be attempted to get the updated orphan volume list. + + 4. `TotalOrphansAttached` - The total number of orphan volumes found that are attached to a VM. + + 5. `TotalOrphansDetached` - The total number of orphan volumes found that are detached. + + 6. `Limit` - The maximum number of orphan volumes to be returned. + + 7. `NextOffset` - The offset of the next page if there are more orphan volumes to query. + + Orphan volumes are safe to delete since there is no PersistentVolume in the Kubernetes cluster referring to them. + operationId: orphanVolumeList + parameters: + - name: includeDetails + in: query + description: Set to "true" to get a detailed dump of the orphan volume. + required: true + style: form + explode: true + schema: + type: boolean + format: boolean + default: false + - name: datacenter + in: query + description: (Optional) Datacenter name to narrow down the orphan volume search. + required: false + style: form + explode: true + schema: + type: string + format: string + - name: datastores + in: query + description: (Optional) List of comma-separated datastores. Specify only if + the `datacenter` param is specified. + required: false + style: form + explode: true + schema: + type: string + format: string + - $ref: '#/components/parameters/PageOffset' + - $ref: '#/components/parameters/PageLimit' + responses: + "200": + description: Returns OrphanVolumeResult. + content: + application/json: + schema: + $ref: '#/components/schemas/OrphanVolumeResult' + headers: + X-Retry-After: + $ref: '#/components/headers/X-Retry-After' + X-Limit: + $ref: '#/components/headers/X-Limit' + X-Next-Offset: + $ref: '#/components/headers/X-Next-Offset' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + tags: + - OrphanVolume + summary: Delete orphan volumes. + description: Delete the orphan volumes for the given criteria. + operationId: orphanVolumeDelete + parameters: + - name: deleteAttachedOrphans + in: query + description: >- + Set to `true` to delete attached orphans. When set to `true`, + the API will detach the orphan volume from the VM before deleting it. + required: true + style: form + explode: true + schema: + type: boolean + format: boolean + default: false + - name: datacenter + in: query + description: (Optional) Datacenter name to narrow down the deletion of orphan volumes to. + required: false + style: form + explode: true + schema: + type: string + format: string + - name: datastores + in: query + description: (Optional) List of comma-separated datastores to narrow down + the deletion of orphan volumes to. Specify only if the `datacenter` param + is specified. + required: false + style: form + explode: true + schema: + type: string + format: string + responses: + "200": + description: Returns OrphanVolumeDeleteResult. + content: + application/json: + schema: + $ref: '#/components/schemas/OrphanVolumeDeleteResult' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /orphansnapshots: + get: + tags: + - OrphanSnapshot + summary: List all the orphan snapshots. + description: |- + Use this API to identify orphan snapshots. From vSphere CSI plugin's perspective, + orphan snapshots are FCD snapshots that were initiated through the vSphere CSI driver + but do not have a corresponding VolumeSnapshotContent object in the Kubernetes cluster. + snapshotPrefix is the prefix used in the snapshot description. Its default value is “snapshot”, + which is also the default value used by snapshot sidecar in CSI and it can be configured based + on prefix used in the snapshot sidecar. Use the `snapshotPrefix` parameter to specify alternate + prefix. + + From Velero vSphere plugin's perspective, orphan snapshots are snapshots whose upload is failing + with multiple attempts or snapshots whose local deletion is failing after successful upload. + For Velero vSphere plugin, user has to specify “AstrolabeSnapshot” as the snapshotPrefix. + + GET API for orphan snapshots support pagination. The response body contains totalOrphanSnapshots, + limit and offset values. Also, response header contains X-Limit and X-Next-Offset values. Based on these + values user can decide if there are more results to be fetched. + Since the detection of orphan snapshots is an expensive operation, the operation is performed asynchronously + at regular intervals. This API returns the list of orphan snapshots found in the last run of the operation. + `retryAfterMinutes` in response body indicates the time in minutes after which the next retry should be + attempted to get the updated orphan snapshot list. + operationId: orphanSnapshotsList + parameters: + - name: datacenter + in: query + description: (Optional) Datacenter name to narrow down the orphan snapshots + search. + required: false + style: form + explode: true + schema: + type: string + format: string + - name: datastores + in: query + description: (Optional) List of comma-separated datastores. Specify only if + the `datacenter` param is specified. + required: false + style: form + explode: true + schema: + type: string + format: string + - name: snapshotPrefix + in: query + description: (Optional) The snapshot prefix indicates the prefix used in snapshot description. + required: false + style: form + explode: true + schema: + type: string + format: string + default: snapshot + - name: limit + in: query + description: (Optional) Limit specifies the maximum entries that should be displayed in single request. + required: false + style: form + explode: true + schema: + type: integer + format: int64 + default: 50 + minimum: 1 + maximum: 100 + - name: offset + in: query + description: (Optional) Offset specifies the starting point of the result set. + required: false + style: form + explode: true + schema: + type: integer + format: int64 + default: 0 + minimum: 0 + responses: + "200": + description: Returns list of orphan snapshots. + content: + application/json: + schema: + $ref: '#/components/schemas/OrphanSnapshotResult' + headers: + X-Limit: + description: The maximum entries that are displayed in single request. + schema: + type: string + X-Next-Offset: + description: The starting point of the next result set. + schema: + type: string + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + tags: + - OrphanSnapshot + summary: Delete orphan snapshots. + description: |- + Use this API to identify and delete orphan snapshots. From vSphere CSI plugin's perspective, + orphan snapshots are FCD snapshots that were initiated through the vSphere CSI driver + but do not have a corresponding VolumeSnapshotContent object in the Kubernetes cluster. + snapshotPrefix is the prefix used in the snapshot description. Its default value is “snapshot”, + which is also the default value used by snapshot sidecar in CSI and it can be configured based + on prefix used in the snapshot sidecar. Use the `snapshotPrefix` parameter to specify alternate + prefix. + + From Velero vSphere plugin's perspective, orphan snapshots are snapshots whose upload is failing + with multiple attempts or snapshots whose local deletion is failing after successful upload. + For Velero vSphere plugin, user has to specify “AstrolabeSnapshot” as the snapshotPrefix. + + Orphan snapshot deletion operation is performed asynchronously. It returns a job id, + the status of which can be retrieved using `jobStatus` API. + operationId: orphanSnapshotsDelete + parameters: + - name: datacenter + in: query + description: (Optional) Datacenter name to narrow down the orphan snapshots + search. + required: false + style: form + explode: true + schema: + type: string + format: string + - name: datastores + in: query + description: (Optional) List of comma-separated datastores. Specify only if + the `datacenter` param is specified. + required: false + style: form + explode: true + schema: + type: string + format: string + - name: snapshotPrefix + in: query + description: (Optional) The snapshot prefix indicates the prefix used in snapshot description. + required: false + style: form + explode: true + schema: + type: string + format: string + default: snapshot + responses: + "202": + description: Returns a job Id, status of which can be fetched using jobStatus API. + content: + application/json: + schema: + $ref: '#/components/schemas/SnapshotDeleteResult' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /volumes/{volumeId}/snapshots: + get: + tags: + - SnapshotForVolume + summary: List all the snapshots for a specific volume + description: |- + Use this API to retrieve all the snapshots for a specific volume. + operationId: ListAllSnapshotsForVolume + parameters: + - name: volumeId + in: path + description: Unique Id of the volume. + required: true + schema: + type: string + format: string + - name: datacenter + in: query + description: Datacenter name to which volume and snapshots belong to. + required: true + style: form + explode: true + schema: + type: string + format: string + - name: datastore + in: query + description: Datastore name to which volume and snapshots belong to. + required: true + style: form + explode: true + schema: + type: string + format: string + - name: snapshotPrefix + in: query + description: |- + (Optional) The snapshot prefix indicates the prefix used in snapshot description. + If snapshot prefix is not specified, then it will list all snapshots of a volume. + required: false + style: form + explode: true + schema: + type: string + format: string + responses: + 200: + description: Returns details of all snapshots of a volume. + content: + application/json: + schema: + $ref: '#/components/schemas/SnapshotsForVolumeResult' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + tags: + - SnapshotForVolume + summary: Delete all the snapshots for a specific volume + description: |- + Use this API to delete all the snapshots for a specific volume. + Snapshot deletion operation is performed asynchronously. It returns a job id, + the status of which can be retrieved using `jobStatus` API. + operationId: deleteAllSnapshotsForVolume + parameters: + - name: volumeId + in: path + description: Unique Id of the volume. + required: true + schema: + type: string + format: string + - name: datacenter + in: query + description: Datacenter name to which volume and snapshots belong to. + required: true + style: form + explode: true + schema: + type: string + format: string + - name: datastore + in: query + description: Datastore name to which volume and snapshots belong to. + required: true + style: form + explode: true + schema: + type: string + format: string + - name: snapshotPrefix + in: query + description: |- + (Optional) The snapshot prefix indicates the prefix used in snapshot description. + If snapshot prefix is not specified, then it will delete all snapshots of a volume. + required: false + style: form + explode: true + schema: + type: string + format: string + responses: + 202: + description: Returns a job Id, status of which can be fetched using jobStatus API. + content: + application/json: + schema: + $ref: '#/components/schemas/SnapshotDeleteResult' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /volumes/{volumeId}/snapshots/{snapshotId}: + delete: + tags: + - SnapshotForVolume + summary: Delete one specific snapshot for volume + description: |- + Use this API to delete the specific snapshot of a volume. + Snapshot deletion operation is performed asynchronously. It returns a job id, + the status of which can be retrieved using `jobStatus` API. + operationId: deleteSnapshotForVolume + parameters: + - name: volumeId + in: path + description: Unique Id of the volume. + required: true + schema: + type: string + format: string + - name: snapshotId + in: path + description: Unique Id of the snapshot. + required: true + schema: + type: string + format: string + - name: datacenter + in: query + description: Datacenter name to which volume and snapshot belongs to. + required: true + style: form + explode: true + schema: + type: string + format: string + - name: datastore + in: query + description: Datastore name to which volume and snapshot belongs to. + required: true + style: form + explode: true + schema: + type: string + format: string + responses: + 202: + description: Returns a job Id, status of which can be fetched using jobStatus API. + content: + application/json: + schema: + $ref: '#/components/schemas/SnapshotDeleteResult' + default: + description: unexpected error + content: + application/json: + schema: $ref: '#/components/schemas/Error' components: + headers: + X-Retry-After: + required: false + description: The number of seconds to wait before retrying the request. + schema: + type: string + X-Limit: + required: false + description: The maximum entries that are displayed in single request. + schema: + type: string + X-Next-Offset: + required: false + description: The starting point of the next result set. + This field is returned only if there are more orphan volumes to query. + schema: + type: string + parameters: + PageLimit: + name: limit + in: query + description: |- + (Optional) The limit indicates the maximum number of orphan volumes + to be returned. + required: false + schema: + type: integer + minimum: 0 + maximum: 2500 + PageOffset: + name: offset + in: query + description: |- + (Optional) The offset indicates the starting point of the result + set. + required: false + schema: + type: integer + minimum: 0 + default: 0 schemas: Error: required: @@ -608,11 +1012,13 @@ components: description: Input parameters of the job. oneOf: - $ref: '#/components/schemas/VolumeMigrationJobParameters' + - $ref: '#/components/schemas/SnapshotDeletionJobParameters' jobStatus: type: object description: Status of individual tasks and the overall job status. oneOf: - $ref: '#/components/schemas/VolumeMigrationJobStatus' + - $ref: '#/components/schemas/SnapshotDeletionJobStatus' example: phase: Running jobId: volumemigrationjob-d1e10795-700f-11ec-bcf8-8630aaccb28e @@ -806,17 +1212,17 @@ components: message: type: string description: Result of suspending volume provisioning on datastore. - example: "Successfully suspended volume provisioning on datstore nfs0-1." + example: "Successfully suspended volume provisioning on datastore nfs0-1." example: - message: Successfully suspended volume provisioning on datstore nfs0-1. + message: Successfully suspended volume provisioning on datastore nfs0-1. ResumeVolumeProvisioningResult: properties: message: type: string description: Result of resuming volume provisioning on datastore. - example: "Successfully resumed volume provisioning on datstore nfs0-1." + example: "Successfully resumed volume provisioning on datastore nfs0-1." example: - message: Successfully resumed volume provisioning on datstore nfs0-1. + message: Successfully resumed volume provisioning on datastore nfs0-1. OrphanVolumeDetails: type: object description: OrphanVolumeDetails represents if the orphan volume is attached to a VM or not. @@ -888,30 +1294,36 @@ components: properties: totalOrphans: type: integer - description: The total orphan volumes returned. - format: int64 + description: The total number of orphan volumes returned. example: 1 totalOrphansAttached: type: integer - description: This field is set only if includeDetails is set to true. - format: int64 + description: The total number of orphan volumes that are attached to a VM. + This field is returned only if includeDetails is set to true. example: 1 totalOrphansDetached: type: integer - description: This field is set only if includeDetails is set to true. - format: int64 + description: The total number of orphan volumes that are not attached to a VM. + This field is set only if includeDetails is set to true. example: 1 orphanVolumes: type: array - description: Array of orphan volumes + description: Array of orphan volumes. items: $ref: '#/components/schemas/OrphanVolume' retryAfterMinutes: type: integer description: The time in minutes after which the next retry should be attempted to get the updated orphan volume list. - format: int64 example: 1 + limit: + type: integer + description: The maximum number of orphan volumes returned. + example: 100 + nextOffset: + type: integer + description: The offset of the next page if there are more orphan volumes to query. + example: 100 example: totalOrphansAttached: 2 totalOrphansDetached: 1 @@ -943,7 +1355,9 @@ components: attached: false capacityInMb: 100 totalOrphans: 3 - retryAfter: 10 + retryAfterMinutes: 10 + limit: 3 + nextOffset: 3 OrphanVolumeDeleteResult: type: object description: OrphanVolumeDeleteResult is the result of deleting orphan volumes. @@ -1019,4 +1433,227 @@ components: example: Failed to delete orphan volume example: volumeId: 64d6787e-397b-4c99-a151-c6f37c49fcff - reason: Failed to delete orphan volume \ No newline at end of file + reason: Failed to delete orphan volume + OrphanSnapshotResult: + properties: + totalOrphanSnapshots: + type: integer + description: The total orphan snapshots returned. + format: int64 + example: 1 + limit: + type: integer + description: Limit specifies the maximum number of entries that are displayed in single request. + format: int64 + example: 50 + offset: + type: integer + description: Offset specifies the starting point of the result set. + format: int64 + example: 0 + orphanSnapshots: + type: array + description: Array of orphan snapshots + items: + $ref: '#/components/schemas/OrphanSnapshot' + retryAfterMinutes: + type: integer + description: Since the detection of orphan snapshots is an expensive operation, + the operation is performed asynchronously at regular intervals. This API returns + the list of orphan snapshots found in the last run of the operation. + `retryAfterMinutes` indicates the time in minutes after which the next retry should be + attempted to get the updated orphan snapshot list. + format: int64 + example: 60 + example: + totalOrphanSnapshots: 2 + limit: 50 + offset: 0 + orphanSnapshots: + - volumeId: 64d6787e-397b-4c99-a151-c6f37c49fcff + volumeSnapshotId: 74d6787e-397b-4c99-a151-c6f37c49fcff + datacenter: DC-1 + datastore: vsanDatastore + createTime: 2021-07-23 19:19:59.365062 +0000 UTC + snapshotDescription: Sample + - volumeId: 84d6787e-397b-4c99-a151-c6f37c49fcff + volumeSnapshotId: 94d6787e-397b-4c99-a151-c6f37c49fcff + datacenter: DC-1 + datastore: vsanDatastore + createTime: 2021-07-23 19:19:59.365063 +0000 UTC + snapshotDescription: Sample2 + retryAfterMinutes: 60 + OrphanSnapshot: + properties: + volumeId: + type: string + description: FCD Id of the orphan snapshot. + example: 64d6787e-397b-4c99-a151-c6f37c49fcff + volumeSnapshotId: + type: string + description: Snapshot Id of the orphan snapshot. + example: 74d6787e-397b-4c99-a151-c6f37c49fcff + datacenter: + type: string + description: Datacenter where the orphan snapshot is located. + example: DC-1 + datastore: + type: string + description: Datastore where the orphan snapshot is located. + example: vsanDatastore + createTime: + type: string + description: Create time of the orphan snapshot. + example: 2021-07-23 19:19:59.365062 +0000 UTC + snapshotDescription: + type: string + description: Description of orphan snapshot + example: Sample + example: + volumeId: 64d6787e-397b-4c99-a151-c6f37c49fcff + volumeSnapshotId: 74d6787e-397b-4c99-a151-c6f37c49fcff + datacenter: DC-1 + datastore: vsanDatastore + createTime: 2021-07-23 19:19:59.365062 +0000 UTC + snapshotDescription: Sample + SnapshotDeleteResult: + properties: + jobId: + type: string + description: Identifier of the snapshot deletion job submitted + example: snapshotdeletionjob-d1e10795-700f-11ec-bcf8-8630aaccb28e + example: + jobId: snapshotdeletionjob-d1e10795-700f-11ec-bcf8-8630aaccb28e + SnapshotDeletionJobParameters: + properties: + fcdId: + type: string + description: fcdId is the identifier of FCD. + example: 64d6787e-397b-4c99-a151-c6f37c49fcff + snapshotId: + type: string + description: snapshotId is the identifier of snapshot. + example: 785g347e-397b-4c99-a151-c6f37c805gh98 + datacenter: + type: string + description: datacenter to which snapshots belong. + example: VSAN-DC + datastores: + type: array + description: datastores to which snapshots belong. + items: + type: string + snapshotPrefix: + type: string + description: snapshotPrefix is the prefix used in the snapshot description. + example: snapshot + SnapshotDeletionJobStatus: + properties: + totalSnapshotsPlannedForDeletion: + type: integer + description: Total snapshots which will be deleted as part of this job. + format: int32 + example: 2 + totalSnapshotsSuccessfullyDeleted: + type: integer + description: Total snapshots which got successfully deleted as part of this job. + format: int32 + example: 2 + totalSnapshotsWithFailedDeletion: + type: integer + description: Total snapshots whose deletion failed as part of this job. + format: int32 + example: 0 + startTime: + type: string + description: Time at which the job started processing. + format: date-time + example: "2022-02-18T22:28:54Z" + endTime: + type: string + description: Time at which the job completed processing. + format: date-time + example: "2022-02-18T22:29:01Z" + snapshotDeletionTasks: + type: array + description: Array of status of individual snapshot deletion tasks in the + job. + items: + $ref: '#/components/schemas/SnapshotDeletionTaskStatus' + SnapshotDeletionTaskStatus: + properties: + fcdId: + type: string + description: Id of the FCD to which snapshot belongs. + example: 64d6787e-397b-4c99-a151-c6f37c49fcff + snapshotId: + type: string + description: Id of the snapshot to be deleted. + example: 785g347e-397b-4c99-a151-c6f37c805gh98 + datacenter: + type: string + description: datacenter to which snapshot belongs. + example: VSAN-DC + datastore: + type: string + description: datastore to which snapshot belongs. + example: vsanDatastore + snapshotDescription: + type: string + description: description of the snapshot. + example: AstrolabeSnapshot + phase: + type: string + description: Current phase of the snapshot deletion task. + example: Success + enum: + - Queued + - Running + - Success + - Error + taskStartTime: + type: string + description: The timestamp at which the task was invoked. + format: date-time + example: "2022-02-18T22:28:54Z" + taskEndTime: + type: string + description: The timestamp at which the task finished. + format: date-time + example: "2022-02-18T22:28:54Z" + error: + $ref: "#/components/schemas/Fault" + SnapshotsForVolumeResult: + properties: + Snapshots: + $ref: '#/components/schemas/SnapshotDetails' + SnapshotDetails: + properties: + snapshotId: + type: string + description: Id of the snapshot. + example: 74d6787e-397b-4c99-a151-c6f37c49fcff + volumeId: + type: string + description: Id of the volume. + example: 64d6787e-397b-4c99-a151-c6f37c49fcff + createTime: + type: string + description: Time when snapshot is created. + example: "2022-12-22 19:57:09.250871 +0000 UTC" + snapshotDescription: + type: string + description: Description of the snapshot. + example: Sample + velerovSpherePluginSnapshotPhase: + type: string + description: Phase of the sanpshot if it is created by Velero vSphere plugin. + example: Uploaded + associatedVolumeSnapshotContent: + type: string + description: Associated VolumeSnapshotContent name if snapshot is created by CSI driver. + example: snapcontent-72cafd03-b848-4628-b41f-2194cffc71d0 + owner: + type: string + description: Owner who created this snapshot. e.g. vSphere CSI driver, Velero vSphere plugin etc. + example: vSphere CSI driver diff --git a/docs/book/features/orphan_snapshots.md b/docs/book/features/orphan_snapshots.md new file mode 100644 index 0000000..df05dcb --- /dev/null +++ b/docs/book/features/orphan_snapshots.md @@ -0,0 +1,77 @@ +## Orphan snapshots detection and clean-up +From vSphere CSI driver's perspective, orphan snapshots are vSphere snapshots that were initiated through the vSphere CSI driver but do not have a corresponding VolumeSnapshotContent object in Kubernetes clusters on the vCenter. +From Velero vSphere plugin's perspective, orphan snapshots are vSphere snapshots whose local deletion is failing after successful upload to the remote repository. +Velero vSphere plugin performs following steps as part of backup: +1. Take a snapshot of the volume. +2. Upload the snapshot to a remote repository. +3. Delete the snapshot. +In these steps, deletion of local snapshot could fail, which leaves behind a snapshot. It can be considered as an orphan snapshot. + +Orphan snapshot detection algorithm considers snapshot prefix for listing a snapshot as an orphan snapshot. Snapshot prefix is the prefix used in the snapshot description (snapshot description can be fetched using the GET /volumes/{volumeId}/snapshots API or will be available in CNS spec). +For example, vSphere CSI driver creates snapshots with default prefix of “snapshot”. So, all these snapshot’s description has prefix “snapshot”. Similarly, Velero vSphere plugin uses snapshot prefix as “AstrolabeSnapshot”. +CNS manager by default considers [“snapshot”, “AstrolableSnapshot”] as snapshot prefixes. These values are configurable using `snapshot-prefixes` parameter in the `cnsmanager-config` ConfigMap. + +Since these orphan snapshots occupy space in the datastore and are not really used in Kubernetes, it's useful to identify and cleanup orphan snapshots periodically. +This functionality provides a set of APIs to detect and delete orphan snapshots on-demand. + +### Supported versions +* vSphere version: 7.0.u3+ +* Kubernetes version: 1.26+ +* vSphere CSI driver version: 2.6+ +* Velero vSphere plugin version: v1.4.3+ + +### Which orphan snapshots are skipped from detection/deletion ? +Some snapshots will not be considered during orphan snapshot detection/deletion. These include: +* Snapshots created out of band (not using vSphere CSI driver or Velero vSphere plugin). +* Statically provisioned CNS snapshots whose description doesn't start with snapshotPrefix(es) registered with CNS manager. +* Snapshots belonging to Kubernetes clusters which are not registered with CNS manager. + +### A reminder to register all Kubernetes clusters! +Before you start using orphan snapshot functionality, it's imperative that you register all the Kubernetes clusters in vCenter with CNS Manager, so that orphan snapshots are detected correctly. Any newly added Kubernetes cluster should also be immediately registered. + +### APIs provided +1. *GET /orphansnapshots* + +This API is used to get list of orphan snapshots. It takes optional parameters, datacenter & list of datastores, and returns orphan snapshots for them. +- If datacenter is not specified, then it returns all orphan snapshots in the vCenter (all datastores on all datacenters ). +- If only datacenter is specified, then it returns orphan snapshots in all datastores in the datacenter. +- If both datacenter & list of datastores is specified, it returns orphan snapshots in specified datastores on the datacenter. +This API also takes optional parameter snapshotPrefix, which indicates the prefix used in the snapshot description. So, this API returns orphan snapshots whose description’s prefix matches with the specified snapshot prefix. Default value of this parameter is “snapshot”. + +There could be hundreds of orphan snapshots, so this API supports pagination as well. It takes optional parameters limit (default value 50) and offset (default value 0). Limit specifies the maximum entries that should be displayed in single request, whereas offset specifies the starting point of the result set. + +Detection of orphan snapshots can be a time-consuming operation if there are large number of orphans. Hence it is performed asynchronously at regular intervals and the response is cached. This API returns list of orphan snapshots computed in the last run, along with the next operation interval (`RetryAfterMinutes`). +**Note:** For newly deployed CNS manager application, when orphan snapshots are being computed in the background for the first time, the API may return no orphan snapshots. It should then be re-tried after `RetryAfterMinutes` to get orphan snapshots computed in the latest run. + +2. *DELETE /orphansnapshots* +This API is used to delete orphan snapshots. It takes optional parameters, datacenter & list of datastores, and deletes orphan snapshots from them with the same logic explained above. +This API also takes optional parameter snapshotPrefix, which indicates the prefix used in the snapshot description. + +Please note if there are large number of orphan snapshots in the system or if there's a slowness in vCenter networking/storage, the orphan snapshot deletion may take longer. That is why, orphan snapshot deletion operation is performed asynchronously. +It creates a job to delete these orphan snapshots in the background and returns the job Id to user, the status of this job can be retrieved using `getjobstatus` API. + + +Apart from APIs provided for detection/deletion of orphan snapshots, there are separate APIs to list/delete snapshots of a specific volume or to delete an individual snapshot. + +3. *GET /volumes/{volumeId}/snapshots* +This API lists all the snapshots for a specific volume. It takes required parameters datacenter and datastore name to which volume and snapshots belong to. +This API also takes optional parameter snapshotPrefix which indicates the prefix used in snapshot description. If snapshot prefix is not specified, then it lists all snapshots of a volume. Otherwise it lists only those snapshots of volume whose description’s prefix matches with the specified snapshot prefix. + +4. *DELETE /volumes/{volumeId}/snapshots* +This API deletes all snapshots of a specific volume. Similar to GET API, it takes required parameters datacenter and datastore and optional parameter snapshotPrefix. +Deletion of all snapshots of a volume is performed asynchronously. It creates a job to delete these snapshots in the background and returns the job Id to user, the status of this job can be retrieved using `getjobstatus` API. + +5. *DELETE /volumes/{volumeId}/snapshots/{snapshotId}* +This API deletes a specific snapshot belonging to a volume. It takes required parameters datacenter and datastore name to which volume and snapshot belongs to. +Deletion of a snapshot is performed asynchronously. It creates a job to delete this snapshot in the background and returns the job Id to user, the status of this job can be retrieved using `getjobstatus` API. + +Two APIs are being offered to check the status of the snapshot deletion job (A job corresponds to a single invocation of the API, that can have multiple tasks corresponding to separate snapshot deletion). +i. *GET /getjobstatus* +This API returns the current status of the job. A job can be in one of the following status: + * Queued - Job has been created but hasn't started processing. + * Running - Job is currently executing. + * Success - Job has completed successfully with all tasks succeeding. + * Error - Job ran but some or all of its tasks failed. +ii. *GET /waitforjob* +This is a blocking API that waits for job to be successful or fail. Unlike getjobstatus API, this will wait for the job to finish before returning the job result response. +