Skip to content

Commit

Permalink
Initial support for persistent volumes REST api endpoints Signed-off-by:
Browse files Browse the repository at this point in the history
Viraj Vora <viraj.vora@hpe.com>
  • Loading branch information
Viraj Vora committed Aug 6, 2020
1 parent a8982a6 commit 4c61f55
Show file tree
Hide file tree
Showing 6 changed files with 585 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Expand Up @@ -9,3 +9,10 @@ This is the first release of the SimpliVity Go SDK and it adds support for the b
- OmniStack cluster
- Policy
- Virtual machine

# unreleased
#### Notes
This version adds support of persistent volumes to the SimpliVity Go SDK

#### Features supported
- Persistent volumes
5 changes: 5 additions & 0 deletions endpoints-support.md
Expand Up @@ -16,6 +16,11 @@ Refer SimpliVity REST API doc for the resource endpoints documentation [HPE Simp
|<sub>/omnistack_clusters </sub> |GET |
| **Policies**
|<sub>/policies </sub> |GET |
| **Persistent Volumes**
|<sub>/persistent_volumes </sub> |GET |
|<sub>/persistent_volumes/set_policy </sub> |POST |
|<sub>/persistent_volumes/{pvId} </sub> |GET |
|<sub>/persistent_volumes/{pvId}/backup </sub> |POST |
| **Virtual Machines**
|<sub>/virtual_machines </sub> |GET |
|<sub>/virtual_machines/set_policy </sub> |POST |
Expand Down
99 changes: 99 additions & 0 deletions examples/persistent_volumes/persistent_volumes.go
@@ -0,0 +1,99 @@
package main

import (
"fmt"
"time"

"github.com/HewlettPackard/simplivity-go/ovc"
)

func main() {
var (
pvName = "pvc-test_fcd"
pvByName *ovc.PersistentVolume
currentTime = time.Now().String()
)

//Create an ovc client
client, err := ovc.NewClient("username", "password", "ovc_ip", "certificate_path_if_needed")
if err != nil {
fmt.Println(err)
}

//Get all persistent volume resources without Filter
fmt.Println("\nGet all persistent volumes without params")
pvList, err := client.PersistentVolumes.GetAll(ovc.GetAllParams{})
if err != nil {
fmt.Println(err)
}
fmt.Println(pvList.Limit, pvList.Count, pvList.Offset, pvList.Members[0])
for _, pv := range pvList.Members {
fmt.Println(pv.Name + "\n")
}

//Get All PV resources with Filters
fmt.Println("\nGet all PVs with params")
pvList, err = client.PersistentVolumes.GetAll(ovc.GetAllParams{Limit: 1, Filters: map[string]string{"name": pvName}})
if err != nil {
fmt.Println(err)
}
for _, pv := range pvList.Members {
fmt.Println(pv.Name + "\n")
}

//Get a PV resource by its name
fmt.Println("\nGet a PV resource by it's name.")
pvByName, err = client.PersistentVolumes.GetByName(pvName)
if err != nil {
fmt.Println(err)
}
fmt.Println(pvByName)

//Get a PV resource by its id
fmt.Println("\nGet a VM resource by it's id.")
pvById, err := client.PersistentVolumes.GetById(pvByName.Id)
if err != nil {
fmt.Println(err)
}
fmt.Println(pvById)

//Set policy for a single and multiple PVs
policyList, err := client.Policies.GetAll(ovc.GetAllParams{Limit: 1})
if err != nil {
fmt.Println(err)
}
if policyList != nil {
//Get one of the backup policies
policy := policyList.Members[0]
fmt.Println("\nPolicy to set is ", policy)

//Set policy for multiple PVs
fmt.Println("\nSet policy for multiple PVs")
pvs := []*ovc.PersistentVolume{pvByName}
err := client.PersistentVolumes.SetPolicyForMultiplePVs(policy, pvs)
if err != nil {
fmt.Println(err)
}
}

//Take a backup of a Persistent Volume
fmt.Println("Take backup of a Peristent Volume")
backupName := "backup_" + currentTime
backReq := &ovc.CreateBackupRequest{Name: backupName}
_, err = pvByName.CreateBackup(backReq, nil)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Backup operation was Successful")
}

// Get backups of a PV
fmt.Println("\nGet all backups of a PV")
backupList, err := pvByName.GetBackups()
if err != nil {
fmt.Println(err)
}
for _, backup := range backupList.Members {
fmt.Println(backup.Name)
}
}
2 changes: 2 additions & 0 deletions ovc/ovc.go
Expand Up @@ -105,6 +105,7 @@ type Client struct {
Datastores *DatastoreResource
Hosts *HostResource
OmniStackClusters *OmniStackClusterResource
PersistentVolumes *PersistentVolumeResource
Policies *PolicyResource
VirtualMachines *VirtualMachineResource
Tasks *TaskResource
Expand Down Expand Up @@ -149,6 +150,7 @@ func NewClient(username string, password string, ovc_ip string, ssl_certificate
c.Hosts = (*HostResource)(&c.common)
c.OmniStackClusters = (*OmniStackClusterResource)(&c.common)
c.VirtualMachines = (*VirtualMachineResource)(&c.common)
c.PersistentVolumes = (*PersistentVolumeResource)(&c.common)
c.Policies = (*PolicyResource)(&c.common)
c.Tasks = (*TaskResource)(&c.common)

Expand Down
238 changes: 238 additions & 0 deletions ovc/persistent_volumes.go
@@ -0,0 +1,238 @@
package ovc

import (
"encoding/json"
"errors"
"fmt"
"log"
)

// Support for persistent_volume is added in v1.16 in SimpliVity
var header = map[string]string{
"Accept": "application/vnd.simplivity.v1.16+json",
"Content-Type": "application/vnd.simplivity.v1.16+json",
}

// PersistentVolumeResource handles communications with the the Persistent Volume resource methods
//
// SimpliVity API docs:<link>
type PersistentVolumeResource resourceClient

// Persistent Volumes GetAll response
type PersistentVolumeList struct {
Offset int `json:"offset,omitempty"`
Count int `json:"count,omitempty"`
Limit int `json:"limit,omitempty"`
Members []*PersistentVolume `json:"persistent_volumes,omitempty"`
}

// PersistentVolume represents a SimpliVity persistent volume
type PersistentVolume struct {
Name string `json:"name,omitempty"`
Id string `json:"id,omitempty"`
State string `json:"state,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
DeletedAt string `json:"deleted_at,omitempty"`
PolicyName string `json:"policy_name,omitempty"`
PolicyId string `json:"policy_id,omitempty"`
DatastoreName string `json:"datastore_name,omitempty"`
DatastoreId string `json:"datastore_id,omitempty"`
OmniStackClusterName string `json:"omnistack_cluster_name,omitempty"`
OmniStackClusterId string `json:"omnistack_cluster_id,omitempty"`
AppAwareVMStatus string `json:"app_aware_vm_status,omitempty"`
HypervisorObjectId string `json:"hypervisor_object_id,omitempty"`
HypervisorType string `json:"hypervisor_type,omitempty"`
HypervisorManagementSystem string `json:"hypervisor_management_system,omitempty"`
HypervisorManagementSystemName string `json:"hypervisor_management_system_name,omitempty"`
HostId string `json:"host_id,omitempty"`
ComputeClusterParentHypervisorObjectId string `json:"compute_cluster_parent_hypervisor_object_id,omitempty"`
ComputeClusterParentName string `json:"compute_cluster_parent_name,omitempty"`
ClusterGroupIds []string `json:"cluster_group_ids,omitempty"`
ReplicaSet []ReplicaSetList `json:"replica_set,omitempty"`
}

// GetAll returns all the persistent volumes filtered by the query parameters.
// Filters:
// id: The unique identifier (UID) of the persistent volume to return
// Accepts: Single value, comma-separated list
// name: The name of the persistent_volumes to return
// Accepts: Single value, comma-separated list, pattern using one or more
// asterisk characters as a wildcard
// omnistack_cluster_id: The unique identifier (UID) of the omnistack_cluster
// that is associated with the instances to return
// Accepts: Single value, comma-separated list
// omnistack_cluster_name: The name of the omnistack_cluster that
// is associated with the instances to return.
// Accepts: Single value, comma-separated list.
// compute_cluster_parent_hypervisor_object_id: The unique identifier (UID)
// of the hypervisor that contains the omnistack_cluster that is associated
// with the instances to return
// Accepts: Single value, comma-separated list.
// compute_cluster_parent_name: The name of the hypervisor that contains the
// omnistack_cluster that is associated with the instances to return
// Accepts: Single value, comma-separated list
// hypervisor_management_system: The IP address of the hypervisor associated
// with the persistent volume.
// Accepts: Single value, comma-separated list, pattern using one
// or more asterisk characters as a wildcard
// hypervisor_management_system_name: The name of the hypervisor associated
// with the persistent volume
// Accepts: Single value, comma-separated list, pattern using one or more
// asterisk characters as a wildcard
// datastore_id: The unique identifier (UID) of the datastore that is associated
// with the instances to return
// Accepts: Single value, comma-separated list
// datastore_name: The name of the datastore that is associated with the
// instances to return
// Accepts: Single value, comma-separated list
// policy_id: The unique identifier (UID) of the policy that is associated
// with the instances to return
// Accepts: Single value, comma-separated list
// policy_name: The name of the policy that is associated with the instances to return
// Accepts: Single value, comma-separated list
// hypervisor_object_id: The unique identifier (UID) of the hypervisor-based instance
// that is associated with the instances to return
// Accepts: Single value, comma-separated list
// created_after: The earliest creation time after the persistent volumes to return were
// created, expressed in ISO-8601 form, based on Coordinated Universal Time (UTC)
// created_before: The latest creation time before the persistent volumes to return were
// created, expressed in ISO-8601 form, based on Coordinated Universal Time (UTC)
// state: The state of the persistent volume that is associated with the instances to return
// Accepts: Single value, comma-separated list
// app_aware_vm_status: The status of the ability of the persistent volume to take
// an application-consistent backup that uses Microsoft VSS
// Accepts: Single value, comma-separated list
// host_id: The unique identifier (UID) of the persistent_volume host.
func (p *PersistentVolumeResource) GetAll(params GetAllParams) (*PersistentVolumeList, error) {
var (
path = "/persistent_volumes"
pvList PersistentVolumeList
)

qrStr := params.QueryString()
resp, err := p.client.DoRequest("GET", path, qrStr, nil, header)
if err != nil {
return &pvList, err
}

err = json.Unmarshal(resp, &pvList)
if err != nil {
return &pvList, err
}

return &pvList, nil
}

// GetBy searches for PV resources with single filter.
func (p *PersistentVolumeResource) GetBy(fieldName string, value string) ([]*PersistentVolume, error) {
filters := map[string]string{fieldName: value}
pvList, err := p.GetAll(GetAllParams{Filters: filters})
if err != nil {
log.Println(err)
return nil, err
}

pvs := pvList.Members
return pvs, nil
}

// GetByName searches for a PV by its name
func (p *PersistentVolumeResource) GetByName(name string) (*PersistentVolume, error) {
pvs, err := p.GetBy("name", name)

if err != nil {
log.Println(err)
return nil, err
}

if len(pvs) > 0 {
pv := pvs[0]
return pv, nil
}

return nil, errors.New("Resource doesn't exist")
}

// GetById searches for a PV by its id
func (p *PersistentVolumeResource) GetById(id string) (*PersistentVolume, error) {
pvs, err := p.GetBy("id", id)

if err != nil {
log.Println(err)
return nil, err
}

if len(pvs) > 0 {
pv := pvs[0]
return pv, nil
}

return nil, errors.New("Resource doesn't exist")
}

// SetPolicyForMultiplePVs sets a policy for list of PV resources.
func (p *PersistentVolumeResource) SetPolicyForMultiplePVs(policy *Policy, pvs []*PersistentVolume) error {
path := fmt.Sprintf("/persistent_volumes/set_policy")
if len(pvs) < 1 {
return errors.New("Pass a list of PV resoures")
}

pv_ids := []string{}
for _, pv := range pvs {
pv_ids = append(pv_ids, pv.Id)
}

body := map[string]interface{}{"policy_id": policy.Id, "persistent_volume_id": pv_ids}
resp, err := p.client.DoRequest("POST", path, "", body, header)
if err != nil {
return err
}

_, err = commonClient.Tasks.WaitForTask(resp)
if err != nil {
return err
}

return nil
}

// CreateBackup creates a backup of the PV.
func (p *PersistentVolume) CreateBackup(req *CreateBackupRequest, dest *OmniStackCluster) (*Backup, error) {
path := fmt.Sprintf("/persistent_volumes/%s/backup", p.Id)
if dest != nil {
req.Destination = dest.Id
}

resp, err := commonClient.DoRequest("POST", path, "", req, header)
if err != nil {
log.Println(err)
return nil, err
}

task, err := commonClient.Tasks.WaitForTask(resp)
if err != nil {
log.Println(err)
return nil, err
}

resources := task.AffectedResources
if len(resources) < 1 {
err_message := "Backup was not successful. Error code:" + string(task.ErrorCode)
return nil, errors.New(err_message)
}

resource_id := resources[0].ObjectId
backup, err := commonClient.Backups.GetById(resource_id)
return backup, nil
}

// GetBackups gets all the backups of a PV.
func (p *PersistentVolume) GetBackups() (*BackupList, error) {
backupList, err := commonClient.Backups.GetAll(GetAllParams{Filters: map[string]string{"pv": p.Name}})
if err != nil {
log.Println(err)
return nil, err
}

return backupList, nil
}

0 comments on commit 4c61f55

Please sign in to comment.