diff --git a/.travis.yml b/.travis.yml index fc800010d..cc54ddbec 100755 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,7 @@ before_install: - sudo apt-get install -y librados-dev librbd-dev - sudo apt-get install -y lvm2 tgt open-iscsi - sudo docker pull p1c2u/openapi-spec-validator + - sudo pip install robotframework matrix: @@ -34,8 +35,21 @@ matrix: install: # Build OpenSDS Controller source code - make all + # Start lvm e2e test + # - split_line "Start lvm e2e test" + - sudo install/devsds/uninstall.sh --purge + - sudo install/devsds/install.sh + - export OPENSDS_AUTH_STRATEGY=noauth + - export OPENSDS_ENDPOINT=http://localhost:50040 + - sudo echo $(ps -ef |grep osds) script: + - export PYTHONPATH=/home/travis/gopath/src/github.com/opensds/opensds/install/CI/ + - sudo cp build/out/bin/osdsctl /usr/local/bin/ + - sudo vgs + - sudo vgdisplay + - robot install/CI/hotpot.robot + - sudo cat /home/travis/gopath/src/github.com/opensds/opensds/output.xml - ./install/CI/coverage - ./install/CI/test diff --git a/README.md b/README.md index 8c8f6ae7f..bb38025ee 100755 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ -## Latest Release: v0.6.0 Capri +## Latest Release: v0.10.0 Daito -[OpenAPI doc](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/opensds/opensds/v0.6.0/openapi-spec/swagger.yaml) +[OpenAPI doc](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/opensds/opensds/v0.10.0/openapi-spec/swagger.yaml) -[Release notes](https://github.com/opensds/opensds/releases/tag/v0.6.0) +[Release notes](https://github.com/opensds/opensds/releases/tag/v0.10.0) ## Introduction diff --git a/install/CI/hotpot.py b/install/CI/hotpot.py new file mode 100644 index 000000000..34f59daa5 --- /dev/null +++ b/install/CI/hotpot.py @@ -0,0 +1,152 @@ +#!/bin/bash + +import os +import subprocess, shlex +from cStringIO import StringIO +import time + +class Hotpot(object): + + def __init__(self): + self.stderr = None + self.stdout = None + + def retry_check(self, function_to_retry): + """ + Retries function passed in 5 times with a 1 second delay inbetween + each try. Function should be passed in with lambda to call the + function instead of just get its result. + """ + check_delay = 1 + check_max_attempts = 5 + + for retry_attempt in xrange(check_max_attempts): + result = function_to_retry() + if result == "available": + return result + + print("Attempt {0} of 5".format(retry_attempt + 1)) + if retry_attempt < 4: + print("Waiting {0} seconds before " + "rechecking".format(check_delay)) + time.sleep(check_delay) + + return result + + def get_index(self, output, arg): + strip_list = [] + for line in output: + if '|' in line: + list = line.split('|') + for item in list: + strip_list.append(item.strip()) + break + return strip_list.index(arg) + + def get_status(self, command): + strip_list = [] + stdout, stderr = self.run_command(command) + output = StringIO(stdout) + for line in output: + if 'Status' not in line and '|' in line: + linelist = line.split('|') + for item in linelist: + strip_list.append(item.strip()) + + return strip_list[self.get_index(StringIO(stdout), 'Status')] + + def get_id(self, stdout): + strip_list = [] + output = StringIO(stdout) + for line in output: + if 'Id' in line and '|' in line: + linelist = line.split('|') + for item in linelist: + strip_list.append(item.strip()) + id = strip_list[2] + return id + + def run_command(self, command): + # path = "/root/gopath/src/github.com/opensds/opensds/build/out/bin/" + print("Command: {0}".format(command)) + args = shlex.split(command) + print("Args: {0}".format(args)) + process = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = process.communicate() + if stderr != '': + raise Exception(stderr) + else: + print("Stdout: {0}".format(stdout)) + return stdout, stderr + + def hello_world(self): + print "BASIC HOTPOT TESTING!" + + def pool_list(self): + self.run_command('build/out/bin/osdsctl pool list') + + def profile_list(self): + return self.run_command('osdsctl profile list') + + def dock_list(self): + self.run_command('build/out/bin/osdsctl dock list') + + def volume_list(self): + self.run_command('osdsctl volume list') + + def fileshare_list(self): + self.run_command('osdsctl fileshare list') + + def version_list(self): + self.run_command('osdsctl version list') + + def volume_create(self): + stdout, stderr = self.run_command('build/out/bin/osdsctl volume create 1 --name=vol1') + return self.get_id(stdout) + + def check_volume_status_available(self, volume_id): + time.sleep(5) + command = 'osdsctl volume list' + ' ' + '--id' + ' ' + volume_id + status = self.retry_check(lambda: self.get_status(command)) + if status != "available": + raise Exception("The volume status is: ",status) + + def volume_delete(self, volume_id): + command = 'osdsctl volume delete' + ' ' + volume_id + self.run_command(command) + + def fileshare_create(self): + stdout, stderr = self.run_command('osdsctl fileshare create 2 --name=randomfile') + return self.get_id(stdout) + + def check_fileshare_status_available(self, fileshare_id): + time.sleep(5) + command = 'osdsctl fileshare list' + ' ' + '--id' + ' ' + fileshare_id + status = self.retry_check(lambda: self.get_status(command)) + if status != "available": + raise Exception("The fileshare status is: ", status) + def fileshare_create_acl(self): + stdout, stderr = self.run_command('osdsctl fileshare create 2 --name=randomfile') + return self.get_id(stdout) + + def fileshare_delete(self, fileshare_id): + command = 'osdsctl fileshare delete' + ' ' + fileshare_id + self.run_command(command) + + def profile_create_block(self): + stdout, stderr = self.run_command('osdsctl profile create '"'"'{"name": "adefault_block_test", "description": "default policy", "storageType": "block"}'"'"'') + return self.get_id(stdout) + + def profile_delete_block(self, block_profile_id): + command = 'osdsctl profile delete' + ' ' + block_profile_id + self.run_command(command) + + def profile_create_file(self): + stdout, stderr = self.run_command('osdsctl profile create '"'"'{"name": "default_file_test", "description": "default policy", "storageType": "file", "provisioningProperties":{"ioConnectivity": {"accessProtocol": "NFS"},"DataStorage":{"StorageAccessCapability":["Read","Write","Execute"]}}}'"'"'') + return self.get_id(stdout) + + def profile_delete_file(self, file_profile_id): + command = 'osdsctl profile delete' + ' ' + file_profile_id + self.run_command(command) diff --git a/install/CI/hotpot.robot b/install/CI/hotpot.robot new file mode 100644 index 000000000..dc60fcec5 --- /dev/null +++ b/install/CI/hotpot.robot @@ -0,0 +1,71 @@ +*** Settings *** +Library hotpot.Hotpot WITH NAME CLI + +*** Variables *** +${volume_id} "" +${fileshare_id} "" +${file_profile_id} "" +${block_profile_id} "" + +*** Test Cases *** +1st Hotpot Test + CLI.Hello World + +Version List + CLI.Version List + +Dock List + CLI.Dock List + +Profile List + ${out} ${err} = CLI.Profile List + Log Profile output is ${out} + +Pool List + CLI.Pool List + +Volume List + CLI.Volume List + +Fileshare List + CLI.Fileshare List + +Profile Create Block + ${block_profile_id} = CLI.Profile Create Block + Set Global Variable ${block_profile_id} + Log The block_profile_id is ${block_profile_id} + +Profile Create File + ${file_profile_id} = CLI.Profile Create File + Set Global Variable ${file_profile_id} + Log The file_profile_id is ${file_profile_id} + +Volume Create + ${volume_id} = CLI.Volume Create + Set Global Variable ${volume_id} + Log The volume_id is ${volume_id} + +Check Volume Status Available + CLI.Check volume status available ${volume_id} + +Volume Delete + Log The volume_id is ${volume_id} + CLI.Volume Delete ${volume_id} + +Fileshare Create + ${fileshare_id} = CLI.Fileshare Create + Set Global Variable ${fileshare_id} + Log The volume_id is ${fileshare_id} + +Check FileShare Status Available + CLI.Check fileshare status available ${fileshare_id} + +Fileshare Delete + Log The fileshare_id is ${fileshare_id} + CLI.Fileshare Delete ${fileshare_id} + +Profile Delete File + CLI.Profile Delete File ${file_profile_id} + +Profile Delete Block + CLI.Profile Delete Block ${block_profile_id} diff --git a/install/CI/test.py b/install/CI/test.py new file mode 100644 index 000000000..b3904dd0a --- /dev/null +++ b/install/CI/test.py @@ -0,0 +1,152 @@ +#!/bin/bash + +import os +import subprocess, shlex +from cStringIO import StringIO +import time + +class Hotpot(object): + + def __init__(self): + self.stderr = None + self.stdout = None + + def retry_check(self, function_to_retry): + """ + Retries function passed in 5 times with a 1 second delay inbetween + each try. Function should be passed in with lambda to call the + function instead of just get its result. + """ + check_delay = 1 + check_max_attempts = 5 + + for retry_attempt in xrange(check_max_attempts): + result = function_to_retry() + if result == "available": + return result + + print("Attempt {0} of 5".format(retry_attempt + 1)) + if retry_attempt < 4: + print("Waiting {0} seconds before " + "rechecking".format(check_delay)) + time.sleep(check_delay) + + return result + + def get_index(self, output, arg): + strip_list = [] + for line in output: + if '|' in line: + list = line.split('|') + for item in list: + strip_list.append(item.strip()) + break + return strip_list.index(arg) + + def get_status(self, command): + strip_list = [] + stdout, stderr = self.run_command(command) + output = StringIO(stdout) + for line in output: + if 'Status' not in line and '|' in line: + linelist = line.split('|') + for item in linelist: + strip_list.append(item.strip()) + + return strip_list[self.get_index(StringIO(stdout), 'Status')] + + def get_id(self, stdout): + strip_list = [] + output = StringIO(stdout) + for line in output: + if 'Id' in line and '|' in line: + linelist = line.split('|') + for item in linelist: + strip_list.append(item.strip()) + id = strip_list[2] + return id + + def run_command(self, command): + # path = "/root/gopath/src/github.com/opensds/opensds/build/out/bin/" + print("Command: {0}".format(command)) + args = shlex.split(command) + print("Args: {0}".format(args)) + process = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = process.communicate() + if stderr != '': + raise Exception(stderr) + else: + print("Stdout: {0}".format(stdout)) + return stdout, stderr + + def hello_world(self): + print "BASIC HOTPOT TESTING!" + + def pool_list(self): + self.run_command('osdsctl pool list') + + def profile_list(self): + return self.run_command('osdsctl profile list') + + def dock_list(self): + self.run_command('osdsctl dock list') + + def volume_list(self): + self.run_command('osdsctl volume list') + + def fileshare_list(self): + self.run_command('osdsctl fileshare list') + + def version_list(self): + self.run_command('osdsctl version list') + + def volume_create(self): + stdout, stderr = self.run_command('osdsctl volume create 2 --name=vol1') + return self.get_id(stdout) + + def check_volume_status_available(self, volume_id): + time.sleep(5) + command = 'osdsctl volume list' + ' ' + '--id' + ' ' + volume_id + status = self.retry_check(lambda: self.get_status(command)) + if status != "available": + raise Exception("The volume status is: ",status) + + def volume_delete(self, volume_id): + command = 'osdsctl volume delete' + ' ' + volume_id + self.run_command(command) + + def fileshare_create(self): + stdout, stderr = self.run_command('osdsctl fileshare create 2 --name=randomfile') + return self.get_id(stdout) + + def check_fileshare_status_available(self, fileshare_id): + time.sleep(5) + command = 'osdsctl fileshare list' + ' ' + '--id' + ' ' + fileshare_id + status = self.retry_check(lambda: self.get_status(command)) + if status != "available": + raise Exception("The fileshare status is: ", status) + def fileshare_create_acl(self): + stdout, stderr = self.run_command('osdsctl fileshare create 2 --name=randomfile') + return self.get_id(stdout) + + def fileshare_delete(self, fileshare_id): + command = 'osdsctl fileshare delete' + ' ' + fileshare_id + self.run_command(command) + + def profile_create_block(self): + stdout, stderr = self.run_command('osdsctl profile create '"'"'{"name": "adefault_block_test", "description": "default policy", "storageType": "block"}'"'"'') + return self.get_id(stdout) + + def profile_delete_block(self, block_profile_id): + command = 'osdsctl profile delete' + ' ' + block_profile_id + self.run_command(command) + + def profile_create_file(self): + stdout, stderr = self.run_command('osdsctl profile create '"'"'{"name": "default_file_test", "description": "default policy", "storageType": "file", "provisioningProperties":{"ioConnectivity": {"accessProtocol": "NFS"},"DataStorage":{"StorageAccessCapability":["Read","Write","Execute"]}}}'"'"'') + return self.get_id(stdout) + + def profile_delete_file(self, file_profile_id): + command = 'osdsctl profile delete' + ' ' + file_profile_id + self.run_command(command) \ No newline at end of file