aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerard Damm <gerard.damm@wipro.com>2018-03-30 14:19:00 +0000
committerGerrit Code Review <gerrit@opnfv.org>2018-03-30 14:19:00 +0000
commitc74e914c628819473625c3bfd03d4535e6e64bb8 (patch)
tree9cedfc5dd249125f2ca70f5f83bea49f85091a93
parenta645d4029db2e1d994585ce68bb9d0522fefc535 (diff)
parenta5ff1317e4b3be39aaaec22716b438c6c12c5652 (diff)
Merge "UC2 update with Openstack SDK interface and common test logic"
-rw-r--r--lib/auto/testcase/resiliency/AutoResilItfCloud.py150
-rw-r--r--lib/auto/testcase/resiliency/AutoResilMain.py1
-rw-r--r--lib/auto/testcase/resiliency/AutoResilMgTestDef.py120
-rw-r--r--lib/auto/testcase/resiliency/clouds.yaml42
4 files changed, 237 insertions, 76 deletions
diff --git a/lib/auto/testcase/resiliency/AutoResilItfCloud.py b/lib/auto/testcase/resiliency/AutoResilItfCloud.py
index 69c5327..302a662 100644
--- a/lib/auto/testcase/resiliency/AutoResilItfCloud.py
+++ b/lib/auto/testcase/resiliency/AutoResilItfCloud.py
@@ -33,14 +33,15 @@
######################################################################
# import statements
import AutoResilGlobal
+import time
# for method 1 and 2
-#import openstack
+import openstack
#for method 3
-from openstack import connection
+#from openstack import connection
-def os_list_servers(conn):
+def openstack_list_servers(conn):
"""List OpenStack servers."""
# see https://docs.openstack.org/python-openstacksdk/latest/user/proxies/compute.html
if conn != None:
@@ -49,14 +50,20 @@ def os_list_servers(conn):
try:
i=1
for server in conn.compute.servers():
- print('Server',str(i),'\n',server,'n')
+ print('Server',str(i))
+ print(' Name:',server.name)
+ print(' ID:',server.id)
+ print(' key:',server.key_name)
+ print(' status:',server.status)
+ print(' AZ:',server.availability_zone)
+ print('Details:\n',server)
i+=1
except Exception as e:
print("Exception:",type(e), e)
print("No Servers\n")
-def os_list_networks(conn):
+def openstack_list_networks(conn):
"""List OpenStack networks."""
# see https://docs.openstack.org/python-openstacksdk/latest/user/proxies/network.html
if conn != None:
@@ -65,14 +72,14 @@ def os_list_networks(conn):
try:
i=1
for network in conn.network.networks():
- print('Network',str(i),'\n',network,'n')
+ print('Network',str(i),'\n',network,'\n')
i+=1
except Exception as e:
print("Exception:",type(e), e)
print("No Networks\n")
-def os_list_volumes(conn):
+def openstack_list_volumes(conn):
"""List OpenStack volumes."""
# see https://docs.openstack.org/python-openstacksdk/latest/user/proxies/block_storage.html
# note: The block_storage member will only be added if the service is detected.
@@ -82,14 +89,20 @@ def os_list_volumes(conn):
try:
i=1
for volume in conn.block_storage.volumes():
- print('Volume',str(i),'\n',volume,'n')
+ print('Volume',str(i))
+ print(' Name:',volume.name)
+ print(' ID:',volume.id)
+ print(' size:',volume.size)
+ print(' status:',volume.status)
+ print(' AZ:',volume.availability_zone)
+ print('Details:\n',volume)
i+=1
except Exception as e:
print("Exception:",type(e), e)
print("No Volumes\n")
-
-def os_list_users(conn):
+
+def openstack_list_users(conn):
"""List OpenStack users."""
# see https://docs.openstack.org/python-openstacksdk/latest/user/guides/identity.html
if conn != None:
@@ -98,13 +111,13 @@ def os_list_users(conn):
try:
i=1
for user in conn.identity.users():
- print('User',str(i),'\n',user,'n')
+ print('User',str(i),'\n',user,'\n')
i+=1
except Exception as e:
print("Exception:",type(e), e)
print("No Users\n")
-
-def os_list_projects(conn):
+
+def openstack_list_projects(conn):
"""List OpenStack projects."""
# see https://docs.openstack.org/python-openstacksdk/latest/user/guides/identity.html
if conn != None:
@@ -113,14 +126,14 @@ def os_list_projects(conn):
try:
i=1
for project in conn.identity.projects():
- print('Project',str(i),'\n',project,'n')
+ print('Project',str(i),'\n',project,'\n')
i+=1
except Exception as e:
print("Exception:",type(e), e)
print("No Projects\n")
-
-def os_list_domains(conn):
+
+def openstack_list_domains(conn):
"""List OpenStack domains."""
# see https://docs.openstack.org/python-openstacksdk/latest/user/guides/identity.html
if conn != None:
@@ -129,7 +142,7 @@ def os_list_domains(conn):
try:
i=1
for domain in conn.identity.domains():
- print('Domain',str(i),'\n',domain,'n')
+ print('Domain',str(i),'\n',domain,'\n')
i+=1
except Exception as e:
print("Exception:",type(e), e)
@@ -138,14 +151,17 @@ def os_list_domains(conn):
-
-
+
+
def gdtest_openstack():
- # Method 1: assume there is a clouds.yaml file in PATH, starting path search with local directory
+
+ # Method 1 (preferred) : assume there is a clouds.yaml file in PATH, starting path search with local directory
#conn = openstack.connect(cloud='armopenstack', region_name='RegionOne')
- #conn = openstack.connect(cloud='hpe16openstack', region_name='RegionOne')
- # getting error: AttributeError: module 'openstack' has no attribute 'connect'
+ #conn = openstack.connect(cloud='hpe16openstackEuphrates', region_name='RegionOne')
+ conn = openstack.connect(cloud='hpe16openstackFraser', region_name='RegionOne')
+ # if getting error: AttributeError: module 'openstack' has no attribute 'connect', check that openstack is installed for this python version
+
# Method 2: pass arguments directly, all as strings
# see details at https://docs.openstack.org/python-openstacksdk/latest/user/connection.html
@@ -163,19 +179,20 @@ def gdtest_openstack():
# password='opnfv_secret',
# region_name='RegionOne',
# )
- # getting error: AttributeError: module 'openstack' has no attribute 'connect'
+ # if getting error: AttributeError: module 'openstack' has no attribute 'connect', check that openstack is installed for this python version
+
# Method 3: create Connection object directly
- auth_args = {
- #'auth_url': 'https://10.10.50.103:5000/v2.0', # Arm
- #'auth_url': 'http://10.16.0.101:5000/v2.0', # hpe16, Euphrates
- 'auth_url': 'http://10.16.0.107:5000/v3', # hpe16, Fraser
- 'project_name': 'admin',
- 'username': 'admin',
- 'password': 'opnfv_secret',
- 'region_name': 'RegionOne',
- 'domain': 'Default'}
- conn = connection.Connection(**auth_args)
+ # auth_args = {
+ # #'auth_url': 'https://10.10.50.103:5000/v2.0', # Arm
+ # #'auth_url': 'http://10.16.0.101:5000/v2.0', # hpe16, Euphrates
+ # 'auth_url': 'http://10.16.0.107:5000/v3', # hpe16, Fraser
+ # 'project_name': 'admin',
+ # 'username': 'admin',
+ # 'password': 'opnfv_secret',
+ # 'region_name': 'RegionOne',
+ # 'domain': 'Default'}
+ # conn = connection.Connection(**auth_args)
#conn = connection.Connection(
#auth_url='http://10.16.0.107:5000/v3',
@@ -184,12 +201,65 @@ def gdtest_openstack():
#password='opnfv_secret')
- os_list_servers(conn)
- os_list_networks(conn)
- os_list_volumes(conn)
- os_list_users(conn)
- os_list_projects(conn)
- os_list_domains(conn)
+ openstack_list_servers(conn)
+ openstack_list_networks(conn)
+ openstack_list_volumes(conn)
+ openstack_list_users(conn)
+ openstack_list_projects(conn)
+ openstack_list_domains(conn)
+
+ # VM: hpe16-Auto-UC2-gdtest-compute1
+ gds_ID = '715c677a-7914-4ca8-8c6d-75bf29eeb940'
+ gds = conn.compute.get_server(gds_ID)
+ print('\ngds.name=',gds.name)
+ print('gds.status=',gds.status)
+ print('suspending...')
+ conn.compute.suspend_server(gds_ID) # NOT synchronous: returns before suspension action is completed
+ wait_seconds = 10
+ print(' waiting',wait_seconds,'seconds...')
+ time.sleep(wait_seconds)
+ gds = conn.compute.get_server(gds_ID) # need to refresh data; not maintained live
+ print('gds.status=',gds.status)
+ print('resuming...')
+ conn.compute.resume_server(gds_ID)
+ print(' waiting',wait_seconds,'seconds...')
+ time.sleep(wait_seconds)
+ gds = conn.compute.get_server(gds_ID) # need to refresh data; not maintained live
+ print('gds.status=',gds.status)
+
+
+
+ #VM: test3
+ gds_ID = 'd3ceffc3-5967-4f18-b8b5-b1b2bd7ab76d'
+ gds = conn.compute.get_server(gds_ID)
+ print('\ngds.name=',gds.name)
+ print('gds.status=',gds.status)
+ print('suspending...')
+ conn.compute.suspend_server(gds_ID) # NOT synchronous: returns before suspension action is completed
+ wait_seconds = 10
+ print(' waiting',wait_seconds,'seconds...')
+ time.sleep(wait_seconds)
+ gds = conn.compute.get_server(gds_ID) # need to refresh data; not maintained live
+ print('gds.status=',gds.status)
+ print('resuming...')
+ conn.compute.resume_server(gds_ID)
+ print(' waiting',wait_seconds,'seconds...')
+ time.sleep(wait_seconds)
+ gds = conn.compute.get_server(gds_ID) # need to refresh data; not maintained live
+ print('gds.status=',gds.status)
+
+ #Volume: hpe16-Auto-UC2-gdtest-volume1
+ gdv_ID = '5a6c1dbd-5097-4a9b-8f79-6f03cde18bf6'
+ gdv = conn.block_storage.get_volume(gdv_ID)
+ # no API for stopping/restarting a volume... only delete. ONAP would have to completely migrate a VNF depending on this volume
+ print('\ngdv.name=',gdv.name)
+ print('gdv.status=',gdv.status)
+ #gdv_recreate = gdv
+ #print('deleting...')
+ #conn.block_storage.delete_volume(gdv_ID)
+ #conn.block_storage.delete_volume(gdv)
+ #print('recreating...')
+ #gdv = conn.block_storage.create_volume(<attributes saved in gdv_recreate>)
# get_server(server): Get a single Server
@@ -211,7 +281,7 @@ def main():
gdtest_openstack()
- print("Ciao\n")
+ print("\nCiao\n")
if __name__ == "__main__":
main()
diff --git a/lib/auto/testcase/resiliency/AutoResilMain.py b/lib/auto/testcase/resiliency/AutoResilMain.py
index 2f67bdf..1d21f6a 100644
--- a/lib/auto/testcase/resiliency/AutoResilMain.py
+++ b/lib/auto/testcase/resiliency/AutoResilMain.py
@@ -164,7 +164,6 @@ def main():
print("Problem with test definition: empty")
sys.exit() # stop entire program, because test definition MUST be correct
else:
- # TODO run test: call selected test definition run_test_code() method
test_def = get_indexed_item_from_list(selected_test_def_ID, AutoResilGlobal.test_definition_list)
if test_def != None:
test_def.run_test_code()
diff --git a/lib/auto/testcase/resiliency/AutoResilMgTestDef.py b/lib/auto/testcase/resiliency/AutoResilMgTestDef.py
index 9667f93..7e0b50d 100644
--- a/lib/auto/testcase/resiliency/AutoResilMgTestDef.py
+++ b/lib/auto/testcase/resiliency/AutoResilMgTestDef.py
@@ -320,10 +320,62 @@ class TestDefinition(AutoBaseObject):
def run_test_code(self):
- """Run currently selected test code."""
+ """Run currently selected test code. Common code runs here, specific code is invoked through test_code_list and test_code_ID."""
try:
+ # here, trigger start code from challenge def (to simulate VM failure), manage Recovery time measurement,
+ # specific monitoring of VNF, trigger stop code from challenge def
+
+ time1 = datetime.now() # get time as soon as execution starts
+
+ # create challenge execution instance
+ chall_exec_ID = 1 # ideally, would be incremented, but need to maintain a number of challenge executions somewhere. or could be random.
+ chall_exec_name = 'challenge execution' # challenge def ID is already passed
+ chall_exec_challDefID = self.challenge_def_ID
+ chall_exec = ChallengeExecution(chall_exec_ID, chall_exec_name, chall_exec_challDefID)
+ chall_exec.log.append_to_list('challenge execution created')
+
+ # create test execution instance
+ test_exec_ID = 1 # ideally, would be incremented, but need to maintain a number of text executions somewhere. or could be random.
+ test_exec_name = 'test execution' # test def ID is already passed
+ test_exec_testDefID = self.ID
+ test_exec_userID = '' # or get user name from getpass module: import getpass and test_exec_userID = getpass.getuser()
+ test_exec = TestExecution(test_exec_ID, test_exec_name, test_exec_testDefID, chall_exec_ID, test_exec_userID)
+ test_exec.log.append_to_list('test execution created')
+
+ # get time1 before anything else, so the setup time is counted
+ test_exec.start_time = time1
+
+ # get challenge definition instance, and start challenge
+ challenge_def = get_indexed_item_from_list(self.challenge_def_ID, AutoResilGlobal.challenge_definition_list)
+ challenge_def.run_start_challenge_code()
+
+ # memorize challenge start time
+ chall_exec.start_time = datetime.now()
+ test_exec.challenge_start_time = chall_exec.start_time
+
+ # call specific test definition code, via table of functions; this code should monitor a VNF and return when restoration is observed
test_code_index = self.test_code_ID - 1 # lists are indexed from 0 to N-1
- self.test_code_list[test_code_index]() # invoke corresponding method, via index
+ self.test_code_list[test_code_index]() # invoke corresponding method, via index; could check for return code
+
+ # memorize restoration detection time and compute recovery time
+ test_exec.restoration_detection_time = datetime.now()
+ recovery_time_metric_def = get_indexed_item_from_file(1,FILE_METRIC_DEFINITIONS) # get Recovery Time metric definition: ID=1
+ test_exec.recovery_time = recovery_time_metric_def.compute(test_exec.challenge_start_time, test_exec.restoration_detection_time)
+
+ # stop challenge
+ challenge_def.run_stop_challenge_code()
+
+ # memorize challenge stop time
+ chall_exec.stop_time = datetime.now()
+ chall_exec.log.append_to_list('challenge execution finished')
+
+ # write results to CSV files, memorize test finish time
+ chall_exec.write_to_csv()
+ test_exec.finish_time = datetime.now()
+ test_exec.log.append_to_list('test execution finished')
+ test_exec.write_to_csv()
+
+
except Exception as e:
print(type(e), e)
sys.exit()
@@ -350,13 +402,10 @@ class TestDefinition(AutoBaseObject):
"""Test case code number 005."""
print("This is test_code005 from TestDefinition #", self.ID, ", test case #", self.test_case_ID, sep='')
- # here, trigger start code from challenge def (to simulate VM failure), manage Recovery time measurement,
- # monitoring of VNF, trigger stop code from challenge def, perform restoration of VNF
- challenge_def = get_indexed_item_from_list(self.challenge_def_ID, AutoResilGlobal.challenge_definition_list)
- if challenge_def != None:
- challenge_def.run_start_challenge_code()
- challenge_def.run_stop_challenge_code()
-
+ # specific VNF recovery monitoring, specific metrics if any
+ # interact with ONAP, periodic query about VNF status; may also check VM or container status directly with VIM
+ # return when VNF is recovered
+ # may provision for failure to recover (max time to wait; return code: recovery OK boolean)
def test_code006(self):
"""Test case code number 006."""
@@ -437,9 +486,9 @@ def init_test_definitions():
test_definitions = []
# add info to list in memory, one by one, following signature values
- test_def_ID = 1
+ test_def_ID = 5
test_def_name = "VM failure impact on virtual firewall (vFW VNF)"
- test_def_challengeDefID = 1
+ test_def_challengeDefID = 5
test_def_testCaseID = 5
test_def_VNFIDs = [1]
test_def_associatedMetricsIDs = [2]
@@ -466,14 +515,20 @@ def init_test_definitions():
######################################################################
class ChallengeType(Enum):
- # server-level failures
+ # physical server-level failures 1XX
COMPUTE_HOST_FAILURE = 100
DISK_FAILURE = 101
LINK_FAILURE = 102
NIC_FAILURE = 103
- # network-level failures
- OVS_BRIDGE_FAILURE = 200
- # security stresses
+
+ # cloud-level failures 2XX
+ CLOUD_COMPUTE_FAILURE = 200
+ SDN_C_FAILURE = 201
+ OVS_BRIDGE_FAILURE = 202
+ CLOUD_STORAGE_FAILURE = 203
+ CLOUD_NETWORK_FAILURE = 204
+
+ # security stresses 3XX
HOST_TAMPERING = 300
HOST_INTRUSION = 301
NETWORK_INTRUSION = 302
@@ -619,9 +674,26 @@ class ChallengeDefinition(AutoBaseObject):
def start_challenge_code005(self):
"""Start Challenge code number 005."""
print("This is start_challenge_code005 from ChallengeDefinition #",self.ID, sep='')
+ # challenge #5, related to test case #5, i.e. test def #5
+ # cloud reference (name and region) should be in clouds.yaml file
+ # conn = openstack.connect(cloud='cloudNameForChallenge005', region_name='regionNameForChallenge005')
+ # TestDef knows VNF, gets VNF->VM mapping from ONAP, passes VM ref to ChallengeDef
+ # ChallengeDef suspends/resumes VM
+ # conn.compute.servers() to get list of servers, using VM ID, check server.id and/or server.name
+ # conn.compute.suspend_server(this server id)
+
+
def stop_challenge_code005(self):
"""Stop Challenge code number 005."""
print("This is stop_challenge_code005 from ChallengeDefinition #",self.ID, sep='')
+ # challenge #5, related to test case #5, i.e. test def #5
+ # cloud reference (name and region) should be in clouds.yaml file
+ # conn = openstack.connect(cloud='cloudNameForChallenge005', region_name='regionNameForChallenge005')
+ # TestDef knows VNF, gets VNF->VM mapping from ONAP, passes VM ref to ChallengeDef
+ # ChallengeDef suspends/resumes VM
+ # conn.compute.servers() to get list of servers, using VM ID, check server.id and/or server.name
+ # conn.compute.conn.compute.resume_server(this server id)
+
def start_challenge_code006(self):
"""Start Challenge code number 006."""
@@ -711,9 +783,9 @@ def init_challenge_definitions():
challenge_defs = []
# add info to list in memory, one by one, following signature values
- chall_def_ID = 1
+ chall_def_ID = 5
chall_def_name = "VM failure"
- chall_def_challengeType = ChallengeType.COMPUTE_HOST_FAILURE
+ chall_def_challengeType = ChallengeType.CLOUD_COMPUTE_FAILURE
chall_def_recipientID = 1
chall_def_impactedCloudResourcesInfo = "OpenStack VM on ctl02 in Arm pod"
chall_def_impactedCloudResourceIDs = [2]
@@ -722,8 +794,10 @@ def init_challenge_definitions():
chall_def_startChallengeCLICommandSent = "service nova-compute stop"
chall_def_stopChallengeCLICommandSent = "service nova-compute restart"
# OpenStack VM Suspend vs. Pause: suspend stores the state of VM on disk while pause stores it in memory (RAM)
+ # in CLI:
# $ nova suspend NAME
# $ nova resume NAME
+ # but better use openstack SDK
chall_def_startChallengeAPICommandSent = []
chall_def_stopChallengeAPICommandSent = []
@@ -1575,7 +1649,7 @@ def main():
challgs = init_challenge_definitions()
print(challgs)
- chall = get_indexed_item_from_file(1,FILE_CHALLENGE_DEFINITIONS)
+ chall = get_indexed_item_from_file(5,FILE_CHALLENGE_DEFINITIONS)
print(chall)
chall.run_start_challenge_code()
chall.run_stop_challenge_code()
@@ -1584,7 +1658,7 @@ def main():
tds = init_test_definitions()
print(tds)
- td = get_indexed_item_from_file(1,FILE_TEST_DEFINITIONS)
+ td = get_indexed_item_from_file(5,FILE_TEST_DEFINITIONS)
print(td)
#td.printout_all(0)
#td.run_test_code()
@@ -1604,8 +1678,8 @@ def main():
metricdef = get_indexed_item_from_file(1,FILE_METRIC_DEFINITIONS)
print(metricdef)
- t1 = datetime(2018,4,1,15,10,12,500000)
- t2 = datetime(2018,4,1,15,13,43,200000)
+ t1 = datetime(2018,7,1,15,10,12,500000)
+ t2 = datetime(2018,7,1,15,13,43,200000)
r1 = metricdef.compute(t1,t2)
print(r1)
print()
@@ -1646,7 +1720,7 @@ def main():
print()
- ce1 = ChallengeExecution(1,"essai challenge execution",1)
+ ce1 = ChallengeExecution(1,"essai challenge execution",5)
ce1.start_time = datetime.now()
ce1.log.append_to_list("challenge execution log event 1")
ce1.log.append_to_list("challenge execution log event 2")
@@ -1668,7 +1742,7 @@ def main():
print()
- te1 = TestExecution(1,"essai test execution",1,1,"Gerard")
+ te1 = TestExecution(1,"essai test execution",5,1,"Gerard")
te1.start_time = datetime.now()
te1.challenge_start_time = ce1.start_time # illustrate how to set test execution challenge start time
print("te1.challenge_start_time:",te1.challenge_start_time)
diff --git a/lib/auto/testcase/resiliency/clouds.yaml b/lib/auto/testcase/resiliency/clouds.yaml
index 593a07c..e6ec824 100644
--- a/lib/auto/testcase/resiliency/clouds.yaml
+++ b/lib/auto/testcase/resiliency/clouds.yaml
@@ -14,9 +14,9 @@ clouds:
armopenstack:
auth:
auth_url: https://10.10.50.103:5000/v2.0
+ project_name: admin
username: admin
password: opnfv_secret
- project_name: admin
region_name: RegionOne
# Openstack instance on LaaS hpe16, from OPNFV Euphrates, controller IP@ (mgt: 172.16.10.101; public: 10.16.0.101)
@@ -27,9 +27,9 @@ clouds:
hpe16openstackEuphrates:
auth:
auth_url: http://10.16.0.101:5000/v2.0
+ project_name: admin
username: admin
password: opnfv_secret
- project_name: admin
region_name: RegionOne
# Openstack instance on LaaS hpe16, from OPNFV Fraser, controller IP@ (mgt: 172.16.10.36; public: 10.16.0.107)
@@ -37,12 +37,16 @@ clouds:
# admin: http://172.16.10.36:35357/v3
# internal: http://172.16.10.36:5000/v3
# public: http://10.16.0.107:5000/v3
+ # Horizon: https://10.16.0.107:8078, but need SSH port forwarding through 10.10.100.26 to be reached from outside
+ # "If you are using Identity v3 you need to specify the user and the project domain name"
hpe16openstackFraser:
auth:
auth_url: http://10.16.0.107:5000/v3
+ project_name: admin
username: admin
password: opnfv_secret
- project_name: admin
+ user_domain_name: Default
+ project_domain_name: Default
region_name: RegionOne
# ubuntu@ctl01:~$ openstack project show admin
@@ -78,14 +82,28 @@ clouds:
# | name | heat_user_domain |
# +-------------+---------------------------------------------+
-export OS_AUTH_URL=http://10.16.0.107:5000/v3
-export OS_PROJECT_ID=04fcfe7aa83f4df79ae39ca748aa8637
-export OS_PROJECT_NAME="admin"
-export OS_USER_DOMAIN_NAME="Default"
-export OS_USERNAME="admin"
-export OS_PASSWORD="opnfv_secret"
-export OS_REGION_NAME="RegionOne"
-export OS_INTERFACE=public
-export OS_IDENTITY_API_VERSION=3
+# admin user (from Horizon on hpe16):
+# Domain ID default
+# Domain Name Default
+# User Name admin
+# Description None
+# ID df0ea50cfcff4bbfbfdfefccdb018834
+# Email root@localhost
+# Enabled Yes
+# Primary Project ID 04fcfe7aa83f4df79ae39ca748aa8637
+# Primary Project Name admin
+
+
+
+
+# export OS_AUTH_URL=http://10.16.0.107:5000/v3
+# export OS_PROJECT_ID=04fcfe7aa83f4df79ae39ca748aa8637
+# export OS_PROJECT_NAME="admin"
+# export OS_USER_DOMAIN_NAME="Default"
+# export OS_USERNAME="admin"
+# export OS_PASSWORD="opnfv_secret"
+# export OS_REGION_NAME="RegionOne"
+# export OS_INTERFACE=public
+# export OS_IDENTITY_API_VERSION=3