Skip to content

Commit

Permalink
Merge pull request #22 from prashanthpx/volupdate
Browse files Browse the repository at this point in the history
Adding patch functionality for px
  • Loading branch information
lpabon authored Aug 9, 2019
2 parents 82eee11 + fc7767f commit 2a7ff87
Show file tree
Hide file tree
Showing 5 changed files with 334 additions and 0 deletions.
24 changes: 24 additions & 0 deletions cmd/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,27 @@ func testCreateIoProfVolume(t *testing.T, volName string, size uint64, IoProfile

assert.True(t, util.ListContainsSubString(lines, fmt.Sprintf("Volume %s created with id", volName)))
}

func testPatchVolumeHalevel(t *testing.T, volName string, haLevel int) {
cli := fmt.Sprintf("px patch volume %s --halevel %d", volName, haLevel)
lines, _, _ := executeCli(cli)
assert.Equal(t, "Volume "+volName+" parameter updated successfully", lines[0])
}

func testPatchVolumeHalevelWithNodes(t *testing.T, volName string, haLevel int64, node string) {
cli := fmt.Sprintf("px patch volume %s --halevel %d --node %s", volName, haLevel, node)
lines, _, _ := executeCli(cli)
assert.Equal(t, "Volume "+volName+" parameter updated successfully", lines)
}

func testPatchVolumeResize(t *testing.T, volName string, size uint64) {
cli := fmt.Sprintf("px patch volume %s --size %d", volName, size)
lines, _, _ := executeCli(cli)
assert.Equal(t, "Volume "+volName+" parameter updated successfully", lines[0])
}

func testPatchVolumeShared(t *testing.T, volName string, shared bool) {
cli := fmt.Sprintf("px patch volume %s --shared %t", volName, shared)
lines, _, _ := executeCli(cli)
assert.Equal(t, "Volume "+volName+" parameter updated successfully", lines[0])
}
39 changes: 39 additions & 0 deletions cmd/patch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
Copyright © 2019 Portworx
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 cmd

import (
"github.com/portworx/px/pkg/util"
"github.com/spf13/cobra"
)

var patchCmd *cobra.Command

// patchCmd represents the patch command
var _ = RegisterCommandVar(func() {
patchCmd = &cobra.Command{
Use: "patch",
Short: "Update field(s) of a Portworx resource",
Run: func(cmd *cobra.Command, args []string) {
util.Printf("Please see px patch --help for more information")
},
}
})

var _ = RegisterCommandInit(func() {
rootCmd.AddCommand(patchCmd)
})
153 changes: 153 additions & 0 deletions cmd/patchVolume.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
Copyright © 2019 Portworx
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 cmd

import (
"fmt"

api "github.com/libopenstorage/openstorage-sdk-clients/sdk/golang"
"github.com/portworx/px/pkg/portworx"
"github.com/portworx/px/pkg/util"
"github.com/spf13/cobra"
)

type volumeUpdateOpts struct {
req *api.SdkVolumeUpdateRequest
halevel int64
replicaSet []string
size uint64
shared bool
sticky bool
}

var (
updateReq *volumeUpdateOpts
patchVolumeCmd *cobra.Command
)

// updateVolumeCmd represents the updateVolume command
var _ = RegisterCommandVar(func() {
updateReq = &volumeUpdateOpts{
req: &api.SdkVolumeUpdateRequest{},
}

patchVolumeCmd = &cobra.Command{
Use: "volume [NAME]",
Short: "Update field(s) of a portworx volume",
Example: `$ px patch volume test --halevel 3
This set halevel of volume to 3.
$px patch volume test --size 2
Updating volume size to 2GiB
$px patch volume test --sticky
Updating volume to be sticky
$px patch volume test --shared
Updating volume to shared`,

Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("Must supply a name for the volume")
}
return nil
},
RunE: updateVolume,
}
})

var _ = RegisterCommandInit(func() {
patchCmd.AddCommand(patchVolumeCmd)

patchVolumeCmd.Flags().Int64Var(&updateReq.halevel, "halevel", 0, "New replication factor (Valid Range: [1, 3]) (default 1)")
patchVolumeCmd.Flags().StringSliceVarP(&updateReq.replicaSet, "nodes", "n", []string{}, "Desired set of nodes for the volume data")
patchVolumeCmd.Flags().Uint64VarP(&updateReq.size, "size", "s", 0, "New size for the volume (GiB) (default 1)")
patchVolumeCmd.Flags().BoolVarP(&updateReq.shared, "shared", "r", false, "Shared is true if this volume can be remotely accessed [default false].")
patchVolumeCmd.Flags().BoolVarP(&updateReq.shared, "sticky", "t", false, "set sticky setting [default false].")
patchVolumeCmd.Flags().SortFlags = false
})

func updateVolume(cmd *cobra.Command, args []string) error {
ctx, conn, err := PxConnectDefault()
if err != nil {
return err
}
// To track if any value of updateReq is set.
updateReqSet := false

defer conn.Close()
// fetch the volume name from args
updateReq.req.VolumeId = args[0]
updateReq.req.Spec = &api.VolumeSpecUpdate{}

// check if halevel providied is valid one
if updateReq.halevel > 0 {
updateReq.req.Spec.HaLevelOpt = &api.VolumeSpecUpdate_HaLevel{
HaLevel: int64(updateReq.halevel),
}
// Replicaset needs to be passed due to know volume driver issue (pwx-9500)
// If user provides one it will be overriden and need to have additional checks.
updateReq.req.Spec.ReplicaSet = &api.ReplicaSet{
Nodes: updateReq.replicaSet,
}
updateReqSet = true
}

// check prvoide size is valid
if updateReq.size > 0 {
//Provided size has to be converted to bytes
updateReq.req.Spec.SizeOpt = &api.VolumeSpecUpdate_Size{
Size: (updateReq.size * 1024 * 1024 * 1024),
}
updateReqSet = true
}

// For setting volume as shared or not
if updateReq.shared {
updateReq.req.Spec.SharedOpt = &api.VolumeSpecUpdate_Shared{
Shared: updateReq.shared,
}
updateReqSet = true
}

// for setting volume to be sticky
if updateReq.sticky {
updateReq.req.Spec.StickyOpt = &api.VolumeSpecUpdate_Sticky{
Sticky: updateReq.sticky,
}
updateReqSet = true
}

if !updateReqSet {
return util.PxErrorMessage(err, "Must supply any one of the flags with valid parameters."+
"Please see help for more info")
}

// Before submitting the request, need to make sure volumespec is checked for valid flag combinations.
err = portworx.ValidateVolumeSpec(updateReq.req.Spec)
if err != nil {
// validation of VolumeSpec has failed, hence return failure
return err
}

volumes := api.NewOpenStorageVolumeClient(conn)
_, err = volumes.Update(ctx, updateReq.req)
if err != nil {
return util.PxErrorMessage(err, "Failed to patch volume")
}
util.Printf("Volume %s parameter updated successfully\n", updateReq.req.VolumeId)
return nil
}
81 changes: 81 additions & 0 deletions cmd/patchVolume_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
Copyright © 2019 Portworx
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 cmd

import (
"testing"

"github.com/stretchr/testify/assert"
)

// TestPatchVolumeHalevel runs a series of volume patching test
func TestPatchVolumeHalevel(t *testing.T) {
volName := genVolName("testVol")
haLevel := 2
volCreate(t, volName)
// Now update halevel to 2
testPatchVolumeHalevel(t, volName, haLevel)
volCleanup(t, volName)
}

func TestPatchVolumeResize(t *testing.T) {
volName := genVolName("testVol")
var size uint64
// Setting size to 2GB
size = 2
volCreate(t, volName)

// Now update halevel to 2
testPatchVolumeResize(t, volName, size)
volCleanup(t, volName)
}

func TestPatchVolumeShared(t *testing.T) {
volName := genVolName("testVol")
shared := true

volCreate(t, volName)
// Now update shared to true
testPatchVolumeShared(t, volName, shared)
volCleanup(t, volName)
}

func TestPatchVolumeUnsetShared(t *testing.T) {
volName := genVolName("testVol")
sharedTrue := true
sharedFalse := false

volCreate(t, volName)
// Now update shared to true
testPatchVolumeShared(t, volName, sharedTrue)
//Now unset shared aka to false
testPatchVolumeShared(t, volName, sharedFalse)
volCleanup(t, volName)
}

// Helper to create a volume
func volCreate(t *testing.T, volName string) {
// Create a volume
testCreateVolume(t, volName, 1)
// Verify that the volume got created
assert.True(t, testHasVolume(volName))
}

// Helper function to cleanup volume created
func volCleanup(t *testing.T, volName string) {
// Delete Volume
testDeleteVolume(t, volName)
}
37 changes: 37 additions & 0 deletions pkg/portworx/volspecvalidation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
Copyright © 2019 Portworx
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 portworx

import (
"fmt"

api "github.com/libopenstorage/openstorage-sdk-clients/sdk/golang"
)

// ValidateVolumeSpec checks if a volume spec if valid. Currently due to volume driver limitation, only few
// combination of fields can be set as paramaters in VolumeSpecUpdate. This function will check for the same.
func ValidateVolumeSpec(volspec *api.VolumeSpecUpdate) error {
// case of checking possible halevel flag combination
if volspec.GetHaLevel() > 0 {
if volspec.GetSize() > 0 || volspec.GetShared() || volspec.GetSticky() {
// Please have unique msgs for each case so it's easy for use to identity the
// flags mismatch combination.
return fmt.Errorf("Invalid halevel flag combination. Size, Shared or Sticky flag not supported " +
"with halevel flag")
}
}
return nil
}

0 comments on commit 2a7ff87

Please sign in to comment.