From 42d6fdba952f467d0e01b9704a237cc2b75b026e Mon Sep 17 00:00:00 2001 From: ashahi1 Date: Tue, 30 May 2017 14:17:53 -0700 Subject: [PATCH] Optimizing volumepropverification_test Rebased changes with Govindan checkin - PR # 1286 --- tests/constants/dockercli/cmd.go | 8 +- tests/e2e/swarm_test.go | 2 +- tests/e2e/volumeproperty_test.go | 176 +++++++++++++++++++ tests/e2e/volumepropverification_test.go | 141 --------------- tests/utils/dockercli/volumelifecycle.go | 12 ++ tests/utils/verification/volumeproperties.go | 57 +++--- 6 files changed, 222 insertions(+), 174 deletions(-) create mode 100644 tests/e2e/volumeproperty_test.go delete mode 100644 tests/e2e/volumepropverification_test.go diff --git a/tests/constants/dockercli/cmd.go b/tests/constants/dockercli/cmd.go index 2b1365d70..8662ae8f0 100644 --- a/tests/constants/dockercli/cmd.go +++ b/tests/constants/dockercli/cmd.go @@ -31,7 +31,7 @@ const ( // CreateVolume create a volume with vsphere driver CreateVolume = dockerVol + " create --driver=vsphere " - // RemoveVolume constant refers delete volume command + // RemoveVolume delete volume command RemoveVolume = dockerVol + "rm " // KillDocker kill docker @@ -99,4 +99,10 @@ const ( // RemoveService remove docker services RemoveService = dockerService + "rm " + + // StopAllContainers stopping all the containers + StopAllContainers = docker + "kill $(docker ps -aq)" + + // RemoveAllContainers removing all the containers forcefully + RemoveAllContainers = docker + "rm $(docker ps -aq) -f" ) diff --git a/tests/e2e/swarm_test.go b/tests/e2e/swarm_test.go index 74fff0853..8690f90a4 100644 --- a/tests/e2e/swarm_test.go +++ b/tests/e2e/swarm_test.go @@ -112,7 +112,7 @@ func (s *SwarmTestSuite) TestDockerSwarm(c *C) { status, host := verification.IsDockerContainerRunning(s.swarmNodes, s.serviceName, 2) c.Assert(status, Equals, true, Commentf("Container %s is not running on any hosts", s.serviceName)) - containerName, err = dockercli.GetContainerName(host, s.serviceName+".1") + containerName, err := dockercli.GetContainerName(host, s.serviceName+".1") c.Assert(err, IsNil, Commentf("Failed to retrieve container name: %s", containerName)) out, err = dockercli.StopService(host, containerName) c.Assert(err, IsNil, Commentf(out)) diff --git a/tests/e2e/volumeproperty_test.go b/tests/e2e/volumeproperty_test.go new file mode 100644 index 000000000..f8927c004 --- /dev/null +++ b/tests/e2e/volumeproperty_test.go @@ -0,0 +1,176 @@ +// Copyright 2017 VMware, Inc. All Rights Reserved. +// +// 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. + +// This is an end-to-end test. Test creates volumes of different format-types +// and verifies their properties from ESX as well as docker host. +// Properties being verified - capacity, disk-format and vm-attached field. + +// Test assumes that SSH cert has been setup to enable password-less login to VM and ESX. + +package e2e + +import ( + "log" + "reflect" + "strings" + + dockerconst "github.com/vmware/docker-volume-vsphere/tests/constants/dockercli" + "github.com/vmware/docker-volume-vsphere/tests/utils/dockercli" + "github.com/vmware/docker-volume-vsphere/tests/utils/inputparams" + "github.com/vmware/docker-volume-vsphere/tests/utils/ssh" + "github.com/vmware/docker-volume-vsphere/tests/utils/verification" + . "gopkg.in/check.v1" +) + +const ( + testName = "volumeproperty" + diskStatusDetached = "detached" + size = "100MB" + diskFormatOption = " -o diskformat=" +) + +type VolumePropertyTestSuite struct { + volumeNames []string + containerName string + formatTypes []string + dockerVolumeRemoveCmd string + volumeAttached bool + config *inputparams.TestConfig +} + +func (s *VolumePropertyTestSuite) SetUpTest(c *C) { + s.config = inputparams.GetTestConfig() + if s.config == nil { + c.Skip("Unable to retrieve test config, skipping volumeproperty_test.TestVolumeProperties.") + } + s.containerName = inputparams.GetContainerNameWithTimeStamp(testName) + s.formatTypes = []string{"thin", "zeroedthick", "eagerzeroedthick"} + s.dockerVolumeRemoveCmd = dockerconst.RemoveVolume + log.Println(" SETUP Finished: volumeproperty_test.TestVolumeProperties") +} + +// TearDownTest - Removes all the containers and deletes the volumes +func (s *VolumePropertyTestSuite) TearDownTest(c *C) { + out, err := dockercli.RemoveAllContainers(s.config.DockerHosts[1]) + c.Assert(err, IsNil, Commentf(out)) + s.dockerVolumeRemoveCmd = s.dockerVolumeRemoveCmd + strings.Join(s.volumeNames, " ") + out, err = ssh.InvokeCommand(s.config.DockerHosts[1], s.dockerVolumeRemoveCmd) + c.Assert(err, IsNil, Commentf(out)) + log.Println(" CLEAN-UP Finished: volumeproperty_test.TestVolumeProperties") +} + +var _ = Suite(&VolumePropertyTestSuite{}) +var dockerCliMap = make(map[string][]string) +var adminCliMap = make(map[string][]string) +var expectedValues = make(map[string][]string) + +/* +Test steps: +1. SSH to a vm and create volumes of size 100 mb and specified disk format ["thin", "zeroedthick", "eagerzeroedthick"] +2. Do docker inspect on the volume get size, disk format and attached-to-vm field. + Expected value: {"100MB", "thin/zeroedthick/eagerzeroedthick", no-value} respectively. +3. SSH to the esx and get capacity, disk format and attached-to-vm field for the volume using Admin cli + Expected value: {"100MB", "thin/zeroedthick/eagerzeroedthick", "detached"} respectively. +4. Verifies values obtained from admin cli and docker cli. +5. SSH to the vm and run a container and mount the volume created. +6. SSH to the vm and esx and verify the attached-to-vm field for volume - both docker cli and admin cli values should be same. +7. Again verify capacity and disk format using docker cli and admin cli to make sure things are fine after running the container. + +NOTE: Do steps 5 ,6 and 7 only for volume of 'thin' disk format +*/ + +func (s *VolumePropertyTestSuite) TestVolumeProperties(c *C) { + log.Printf("START: volumeproperty_test.TestVolumeProperties") + + // create volumes of all three disk formats + s.createVolumes(c) + + // get properties for all three volumes from ESX and docker host + s.getVolumeProperties(c) + + // Verify if docker and ESX properties of all three volumes are same and as expected. + s.verifyProperties(c) + + // attach only thin volume + out, err := dockercli.AttachVolume(s.config.DockerHosts[1], s.volumeNames[0], s.containerName) + c.Assert(err, IsNil, Commentf("Failed to attach the volume [%s]", out)) + s.volumeAttached = true + + // Get volumes properties for the thin volume from docker and ESX. + s.getVolumePropertiesAdminCli(c, s.volumeNames[0]) + s.getVolumePropertiesDockerCli(c, s.volumeNames[0]) + + // Verify if docker and ESX properties of volumes are same and as expected. + s.verifyProperties(c) + + log.Printf("END: volumeproperty_test.TestVolumeProperties") +} + +// createVolumes - creates volumes of each format type +func (s *VolumePropertyTestSuite) createVolumes(c *C) { + for _, formatType := range s.formatTypes { + vname := inputparams.GetVolumeNameWithTimeStamp(formatType) + out, err := dockercli.CreateVolumeWithOptions(s.config.DockerHosts[1], vname, diskFormatOption+formatType) + s.volumeNames = append(s.volumeNames, vname) + c.Assert(err, IsNil, Commentf(out)) + } +} + +// getVolumeProperties - get properties of three volumes from ESX and docker host +func (s *VolumePropertyTestSuite) getVolumeProperties(c *C) { + // get properties for all three volumes from ESX + for _, volumeName := range s.volumeNames { + s.getVolumePropertiesAdminCli(c, volumeName) + } + // get properties for all three volumes from docker host + for _, volumeName := range s.volumeNames { + s.getVolumePropertiesDockerCli(c, volumeName) + } +} + +// getVolumePropertiesAdminCli - get properties of a volume from ESX +func (s *VolumePropertyTestSuite) getVolumePropertiesAdminCli(c *C, volumeName string) { + admincliValues := verification.GetVolumePropertiesAdminCli(volumeName, s.config.EsxHost) + c.Assert(admincliValues, HasLen, 3) + adminCliMap[volumeName] = []string{admincliValues[0], admincliValues[1], admincliValues[2]} +} + +// getVolumePropertiesDockerCli - gets properties of a volume from the docker host +func (s *VolumePropertyTestSuite) getVolumePropertiesDockerCli(c *C, volumeName string) { + out, _ := verification.GetVolumePropertiesDockerCli(volumeName, s.config.DockerHosts[1]) + dockerCliValues := strings.Fields(out) + dockerCliMap[volumeName] = []string{dockerCliValues[0], dockerCliValues[1], dockerCliValues[2]} +} + +// verifyProperties - Verify docker and ESX properties of all three volumes are same and as expected. +func (s *VolumePropertyTestSuite) verifyProperties(c *C) { + log.Println("Verify docker and ESX properties of all three volumes are same") + status := reflect.DeepEqual(dockerCliMap, adminCliMap) + c.Assert(status, Equals, true, Commentf("Admin cli: %s . Docker Cli: %s . ESX and docker properties of volumes are not same.", adminCliMap, dockerCliMap)) + + // Only for volume with 'thin' format type, after s.volumeAttached=true, modify attached-to-vm field with vm name. + if !s.volumeAttached { + for i, volumeName := range s.volumeNames { + expectedValues[volumeName] = []string{size, s.formatTypes[i], diskStatusDetached} + } + } else { + tmp := expectedValues[s.volumeNames[0]] + tmp[2] = s.config.DockerHostNames[1] + expectedValues[s.volumeNames[0]] = tmp + } + + // Verify ESX properties of all three volumes are as expected. + status = reflect.DeepEqual(expectedValues, adminCliMap) + c.Assert(status, Equals, true, Commentf("Admin cli: %s . Expected values: %s . ESX properties and expected property values of volumes are not same", adminCliMap, expectedValues)) +} diff --git a/tests/e2e/volumepropverification_test.go b/tests/e2e/volumepropverification_test.go deleted file mode 100644 index ab0a11c60..000000000 --- a/tests/e2e/volumepropverification_test.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2017 VMware, Inc. All Rights Reserved. -// -// 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. - -// This is an end-to-end test. Test will ssh to a vm and create a volume using docker cli. -// After creating a volume, test will ssh to the ESX and verify the properties of the volume. -// Properties being verified - capacity, disk-format and vm-attached field. - -// Test assumes that SSH cert has been setup to enable password-less login to VM and ESX. - -package e2e - -import ( - "log" - "os" - "strings" - "testing" - "time" - - "github.com/vmware/docker-volume-vsphere/tests/utils/inputparams" - "github.com/vmware/docker-volume-vsphere/tests/utils/ssh" - "github.com/vmware/docker-volume-vsphere/tests/utils/verification" -) - -var ( - esx = os.Getenv("ESX") - volSizes = []string{"100MB"} - vms = []string{os.Getenv("VM1")} - formatTypes = []string{"thin", "zeroedthick", "eagerzeroedthick"} - vmIP string - dockerVolmRmvCmd = "docker volume rm " - dockerCliCheck bool - containerName string -) - -func TestMain(m *testing.M) { - retCode := m.Run() - teardownFunction() - os.Exit(retCode) -} - -// clean-up function -func teardownFunction() { - ssh.InvokeCommand(vmIP, dockerVolmRmvCmd) - log.Println("-----Clean-up finished - current time: ", time.Now()) -} - -/* -Test steps: -1. SSH to a vm and create a volume of size 100 mb and specified disk format ["thin", "zeroedthick", "eagerzeroedthick"] -2. Do docker inspect on the volume and verify size, disk format and attached to vm field. - Expected value: {"100MB", "thin/zeroedthick/eagerzeroedthick", no-value} respectively. -3. SSH to the esx and verify the capacity, disk format and attached-to-vm field for the volume using Admin cli - Expected value: {"100MB", "thin/zeroedthick/eagerzeroedthick", "detached"} respectively. -4. SSH to the vm and run a container and mount the volume created -5. SSH to the vm and esx and verify the attached-to-vm field for volume - both docker cli and admin cli values should be same. -6. Again verify capacity and disk format using docker cli and admin cli to make sure things are fine after running the container. -*/ -func TestVolumeProperties(t *testing.T) { - for vmIndx := 0; vmIndx < len(vms); vmIndx++ { - log.Println("running end_to_end tests - current time: ", time.Now()) - vmIP = vms[vmIndx] - log.Println("Running test on VM - ", vmIP) - dockerCliCheck = true - for i := 0; i < len(volSizes); i++ { - for k := 0; k < len(formatTypes); k++ { - containerName = inputparams.GetContainerNameWithTimeStamp("volumeprop_test") - log.Println("Creating a volume of Format Type - ", formatTypes[k]) - volName := inputparams.GetVolumeNameWithTimeStamp("volumeprop_test") - _, err := ssh.InvokeCommand(vms[vmIndx], "docker volume create --driver=vsphere --name="+ - volName+" -o size="+volSizes[i]+" -o diskformat="+formatTypes[k]) - if err != nil { - log.Fatalf("Failed to create a volume named: %s. Error - %v ", volName, err) - } else { - log.Println("\n successfully created a volume -- ", volName) - dockerVolmRmvCmd = dockerVolmRmvCmd + " " + volName - } - log.Println("Verifying volume properties like size, disk-format and attached-to-vm fields "+ - "at vm and esx for volume - ", volName) - volmPropertiesAdminCli := verification.GetVolumePropertiesAdminCli(volName, esx) - expctdPropsAdmin := []string{"100MB", formatTypes[k], "detached"} - if !hasElement(expctdPropsAdmin, volmPropertiesAdminCli) { - log.Fatal("Volume properties on ESX fetched using admin cli does not matches with the expected values") - } - - if dockerCliCheck { - volumePropertiesDockerCli := verification.GetVolumePropertiesDockerCli(volName, vms[vmIndx]) - expctdPropsDkr := []string{"100MB", formatTypes[k], ""} - if !hasElement(expctdPropsDkr, volumePropertiesDockerCli) { - log.Fatal("Volume properties fetched using docker cli do not matches with the expected values") - } - } - ssh.InvokeCommand(vms[vmIndx], "docker run -d -v "+volName+":/vol --name "+containerName+" busybox tail -f /dev/null") - // Verifying attached to the vm field for volume - vmNameFrmAdminCli := verification.GetVMAttachedToVolUsingAdminCli(volName, esx) - if dockerCliCheck { - vmNameFrmDockerCli := verification.GetVMAttachedToVolUsingDockerCli(volName, vms[vmIndx]) - // TODO: get vm name based on ip and compare ith with the docker cli and admin cli - if vmNameFrmDockerCli != vmNameFrmAdminCli { - log.Fatalf("Information mis-match - Attached-to-VM field for volume from docker cli is [%s]"+ - "and attched-to-vm field from admin cli is [%s]", vmNameFrmDockerCli, vmNameFrmAdminCli) - } - volumePropertiesDockerCli := verification.GetVolumePropertiesDockerCli(volName, vms[vmIndx]) - expctdPropsDkr := []string{"100MB", formatTypes[k]} - if !hasElement(expctdPropsDkr, volumePropertiesDockerCli) { - log.Fatal("Volume properties on ESX fetched using docker cli do not matches with the expected values") - } - } - volmPropertiesAdminCli = verification.GetVolumePropertiesAdminCli(volName, esx) - expctdPropsAdmin = []string{"100MB", formatTypes[k]} - if !hasElement(expctdPropsAdmin, volmPropertiesAdminCli) { - log.Fatal("Volume properties on admin cli do not matches with the expected values") - } - log.Println("Finished verifying volume properties like size, disk-format and attached-to-vm fields"+ - " at vm and esx for volume - ", volName) - ssh.InvokeCommand(vms[vmIndx], "docker stop "+containerName+" ; docker rm "+containerName) - } - } - } -} - -// method checks if the output from the ssh commands contains the expected values -func hasElement(volmProps []string, op string) bool { - for i := 0; i < len(volmProps); i++ { - if !strings.Contains(op, volmProps[i]) { - log.Printf("Actual values : %s. Does not contains %s ", op, volmProps[i]) - return false - } - } - return true -} diff --git a/tests/utils/dockercli/volumelifecycle.go b/tests/utils/dockercli/volumelifecycle.go index 65aaacd0d..b92f90f9e 100644 --- a/tests/utils/dockercli/volumelifecycle.go +++ b/tests/utils/dockercli/volumelifecycle.go @@ -204,3 +204,15 @@ func IsContainerExist(ip, containerName string) bool { } return false } + +// StopAllContainers - stops all the containers on a particular vm +func StopAllContainers(ip string) (string, error) { + log.Printf("Stopping all containers on VM [%s]\n", ip) + return ssh.InvokeCommand(ip, dockercli.StopAllContainers) +} + +// RemoveAllContainers - removes all the containers on a particular vm +func RemoveAllContainers(ip string) (string, error) { + log.Printf("Removing all containers on VM [%s]\n", ip) + return ssh.InvokeCommand(ip, dockercli.RemoveAllContainers) +} diff --git a/tests/utils/verification/volumeproperties.go b/tests/utils/verification/volumeproperties.go index adcfe930f..d7c834a27 100644 --- a/tests/utils/verification/volumeproperties.go +++ b/tests/utils/verification/volumeproperties.go @@ -55,42 +55,37 @@ func GetVMAttachedToVolUsingAdminCli(volName string, hostname string) string { return volProps[1] } -// GetVolumePropertiesAdminCli returns capacity, attached-to-vm and disk-format field -// for volume using Admin cli -func GetVolumePropertiesAdminCli(volName string, hostname string) string { - cmd := admincli.ListVolumes + "-c volume,attached-to,capacity,disk-format 2>/dev/null | grep " + volName - op, _ := ssh.InvokeCommand(hostname, cmd) - if op == "" { - log.Fatal("Null value is returned by admin cli when looking for, size, disk-format and attached to vm. Output: ", op) - } - if len(strings.Fields(op)) != 4 { - log.Fatalf("Output is expected to consist of four elements only - "+ - "volume name, attached-to-vm status, size and disk-format. Actual output: %s", op) +// GetPropertiesForAllVolumesAdminCli returns a map of all the volumes from ESX and their corresponding +// properties returned - capacity, attached-to-vm and disk-format +func GetPropertiesForAllVolumesAdminCli(hostName string) map[string][]string { + log.Printf("Getting size, disk-format and attached-to-vm for all volumes from ESX [%s] using admin cli. \n", hostName) + cmd := admincli.ListVolumes + "-c volume,capacity,disk-format,attached-to 2>/dev/null | awk -v OFS='\t' '{print $1, $2, $3, $4}' | sed '1,2d' " + out, _ := ssh.InvokeCommand(hostName, cmd) + admincliValues := strings.Fields(out) + adminCliMap := make(map[string][]string) + for i := 0; i < len(admincliValues); { + adminCliMap[admincliValues[i]] = []string{admincliValues[i+1], admincliValues[i+2], admincliValues[i+3]} + i = i + 4 } - return op + return adminCliMap +} + +// GetVolumePropertiesAdminCli returns an array of properties of a volume from ESX +// properties returned - capacity, attached-to-vm and disk-format field +func GetVolumePropertiesAdminCli(volumeName, hostName string) []string { + log.Printf("Getting size, disk-format and attached-to-vm for volume [%s] from ESX [%s] using admin cli. \n", volumeName, hostName) + cmd := admincli.ListVolumes + "-c volume,capacity,disk-format,attached-to 2>/dev/null | grep " + volumeName + " | awk -v OFS='\t' '{print $2, $3, $4}' " + out, _ := ssh.InvokeCommand(hostName, cmd) + admincliValues := strings.Fields(out) + return admincliValues } // GetVolumePropertiesDockerCli returns capacity, attached-to-vm and disk-format field // for volume using Docker cli -func GetVolumePropertiesDockerCli(volName string, hostname string) string { - cmd := dockercli.InspectVolume + " --format '{{index .Status.capacity.size}} {{index .Status.diskformat}} {{index .Status \"attached to VM\"}}' " + volName - op, _ := ssh.InvokeCommand(hostname, cmd) - expctedLen := 0 - if op == "" { - log.Fatal("Null value is returned by docker cli when looking for, size, disk-format and attached to vm. Output: ", op) - } - // converting the output to an array and comparing the length of array is as expected so that we do not see any - // random strings/values attached to the expected output - if strings.Contains(op, "") { - expctedLen = 4 - } else { - expctedLen = 3 - } - if len(strings.Fields(op)) != expctedLen { - log.Fatalf("Docker cli inpect output is expected to consist of three elements only - "+ - "size, disk-format and attached-to-vm status. Actual output: %s", op) - } - return op +func GetVolumePropertiesDockerCli(volumeName, hostName string) (string, error) { + log.Printf("Getting size, disk-format and attached-to-vm for volume [%s] from vm [%s] using docker cli \n", volumeName, hostName) + cmd := dockercli.InspectVolume + volumeName + " --format ' {{index .Status.capacity.size}} {{index .Status.diskformat}} {{index .Status \"attached to VM\"}}' | sed -e 's//detached/' " + return ssh.InvokeCommand(hostName, cmd) } // CheckVolumeAvailability returns true if the given volume is available