Complete teardown implementation.
Add demo.sh to support hands on demo
Change-Id: Idf235957bd992e6d7482c8241f6ba8b8944c2826
Signed-off-by: jf9860 <jf9860@att.com>
diff --git a/docker/demo.sh b/docker/demo.sh
new file mode 100644
index 0000000..98dc123
--- /dev/null
+++ b/docker/demo.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+# Set the defaults
+if [ $# -eq 0 ];then
+ echo "Usage: demo.sh init"
+ echo " demo.sh preload <vnf_name> <module_name>"
+ echo " demo.sh appc <module_name>"
+ exit
+fi
+##
+## if more than 1 tag is supplied, the must be provided with -i or -e
+##
+while [ $# -gt 0 ]
+do
+ key="$1"
+
+ case $key in
+ init)
+ TAG="InitDemo"
+ shift
+ ;;
+ preload)
+ TAG="PreloadDemo"
+ shift
+ if [ $# -ne 2 ];then
+ echo "Usage: demo.sh preload <vnf_name> <module_name>"
+ exit
+ fi
+ VARIABLES="$VARIABLES -v VNF_NAME:$1"
+ shift
+ VARIABLES="$VARIABLES -v MODULE_NAME:$1"
+ shift
+ ;;
+ appc)
+ TAG="APPCMountPointDemo"
+ shift
+ if [ $# -ne 1 ];then
+ echo "Usage: demo.sh appc <module_name>"
+ exit
+ fi
+ VARIABLES="$VARIABLES -v MODULE_NAME:$1"
+ shift
+ ;;
+ *)
+ echo "Usage: demo.sh init"
+ echo " demo.sh preload <vnf_name> <module_name>"
+ echo " demo.sh appc <module_name>"
+ exit
+ esac
+done
+
+ETEHOME=/var/opt/OpenECOMP_ETE
+VARIABLEFILES="-V /share/config/vm_properties.py -V /share/config/robot_properties_ete.py -V /share/config/robot_preload_parameters.py"
+docker exec openecompete_container ${ETEHOME}/runTags.sh ${VARIABLEFILES} ${VARIABLES} -d /share/logs/demo/${TAG} -i ${TAG} 2> ${TAG}.out
\ No newline at end of file
diff --git a/robot/assets/templates/aai/add_cloud_region_body.template b/robot/assets/templates/aai/add_cloud_region_body.template
deleted file mode 100644
index 95b2525..0000000
--- a/robot/assets/templates/aai/add_cloud_region_body.template
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "cloud-owner": "${cloud_owner}",
- "cloud-region-id": "${cloud_region_id}",
- "cloud-type": "${cloud_type}",
- "owner-defined-type": "${owner_defined_type}",
- "cloud-region-version": "${cloud_region_version}",
- "cloud-zone": "${cloud_zone}",
- "tenants": {
- "tenant": [{
- "tenant-id": "${tenant_id}",
- "tenant-name": "${tenant_name}"
-
- }]
- }
-}
\ No newline at end of file
diff --git a/robot/assets/templates/aai/add_demo_customer.template b/robot/assets/templates/aai/add_demo_customer.template
new file mode 100644
index 0000000..e56577c
--- /dev/null
+++ b/robot/assets/templates/aai/add_demo_customer.template
@@ -0,0 +1,47 @@
+{
+ "global-customer-id" : "${global_customer_id}",
+ "subscriber-name" : "${subscriber_name}",
+ "subscriber-type" : "${subscriber_type}",
+ "service-subscriptions" : {
+ "service-subscription" : [{
+ "service-type" : "${service1}",
+ "relationship-list" : {
+ "relationship" : [{
+ "related-to" : "tenant",
+ "relationship-data" : [{
+ "relationship-key" : "cloud-region.cloud-owner",
+ "relationship-value" : "${cloud_owner}"
+ }, {
+ "relationship-key" : "cloud-region.cloud-region-id",
+ "relationship-value" : "${cloud_region_id}"
+ }, {
+ "relationship-key" : "tenant.tenant-id",
+ "relationship-value" : "${tenant_id}"
+ }
+ ]
+ }
+ ]
+ }
+ }, {
+ "service-type" : "${service2}",
+ "relationship-list" : {
+ "relationship" : [{
+ "related-to" : "tenant",
+ "relationship-data" : [{
+ "relationship-key" : "cloud-region.cloud-owner",
+ "relationship-value" : "${cloud_owner}"
+ }, {
+ "relationship-key" : "cloud-region.cloud-region-id",
+ "relationship-value" : "${cloud_region_id}"
+ }, {
+ "relationship-key" : "tenant.tenant-id",
+ "relationship-value" : "${tenant_id}"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+}
diff --git a/robot/assets/templates/aai/add_tenant_body.template b/robot/assets/templates/aai/add_tenant_body.template
index a3cea10..a7dbbbf 100644
--- a/robot/assets/templates/aai/add_tenant_body.template
+++ b/robot/assets/templates/aai/add_tenant_body.template
@@ -5,6 +5,7 @@
"owner-defined-type": "${owner_defined_type}",
"cloud-region-version": "${cloud_region_version}",
"cloud-zone": "${cloud_zone}",
+ ${resource_version}
"tenants": {
"tenant": [{
"tenant-id": "${tenant_id}",
diff --git a/robot/resources/aai/create_tenant.robot b/robot/resources/aai/create_tenant.robot
index da21ac9..e5a5596 100644
--- a/robot/resources/aai/create_tenant.robot
+++ b/robot/resources/aai/create_tenant.robot
@@ -28,12 +28,24 @@
Inventory Tenant
[Documentation] Inventorys a Tenant in A&AI
[Arguments] ${cloud_owner} ${cloud_region_id} ${cloud_type} ${owner_defined_type} ${cloud_region_version} ${cloud_zone} ${tenant_id} ${tenant_name}
+ ${json_resource_version}= Get Resource Version If Exists ${cloud_owner} ${cloud_region_id} ${cloud_type} ${owner_defined_type} ${cloud_region_version} ${cloud_zone}
${data_template}= OperatingSystem.Get File ${AAI_ADD_TENANT_BODY}
- ${arguments}= Create Dictionary cloud_owner=${cloud_owner} cloud_region_id=${cloud_region_id} cloud_type=${cloud_type} owner_defined_type=${owner_defined_type} cloud_region_version=${cloud_region_version} cloud_zone=${cloud_zone} tenant_id=${tenant_id} tenant_name=${tenant_name}
+ ${arguments}= Create Dictionary cloud_owner=${cloud_owner} cloud_region_id=${cloud_region_id} cloud_type=${cloud_type} owner_defined_type=${owner_defined_type} cloud_region_version=${cloud_region_version} cloud_zone=${cloud_zone} tenant_id=${tenant_id} tenant_name=${tenant_name} resource_version=${json_resource_version}
${data}= Fill JSON Template ${data_template} ${arguments}
${put_resp}= Run A&AI Put Request ${INDEX PATH}${ROOT_TENANT_PATH}${cloud_owner}/${cloud_region_id} ${data}
- Should Be Equal As Strings ${put_resp.status_code} 201
- [Return] ${put_resp.status_code}
+ ${status_string}= Convert To String ${put_resp.status_code}
+ Should Match Regexp ${status_string} ^(201|200)$
+
+Get Resource Version If Exists
+ [Documentation] Creates a service in A&AI if it doesn't exist
+ [Arguments] ${cloud_owner} ${cloud_region_id} ${cloud_type} ${owner_defined_type} ${cloud_region_version} ${cloud_zone}
+ ${resource_version}= Set Variable
+ ${resp}= Get Cloud Region ${cloud_owner} ${cloud_region_id}
+ Return from Keyword if '${resp.status_code}' != '200' ${resource_version}
+ ${json}= Set Variable ${resp.json()}
+ ${resource_version}= Catenate ${json['resource-version']}
+ [Return] "resource-version":"${resource_version}",
+
Delete Tenant
[Documentation] Removes both Tenant
@@ -66,6 +78,12 @@
Run Keyword If '${status}' == 'PASS' Update Tenant Dictionary ${dict} ${resp.json()}
[Return] ${dict}
+Get Cloud Region
+ [Documentation] Returns the Cloud Region if it exists
+ [Arguments] ${cloud_owner} ${cloud_region_id}
+ ${resp}= Run A&AI Get Request ${INDEX PATH}${ROOT_TENANT_PATH}${cloud_owner}/${cloud_region_id}
+ [Return] ${resp}
+
Update Tenant Dictionary
[Arguments] ${dict} ${json}
${list}= Evaluate ${json}['tenant']
diff --git a/robot/resources/aai/service_instance.robot b/robot/resources/aai/service_instance.robot
index c9fdadd..5fffa02 100644
--- a/robot/resources/aai/service_instance.robot
+++ b/robot/resources/aai/service_instance.robot
@@ -14,6 +14,7 @@
Resource ../stack_validation/validate_vlb.robot
Resource ../stack_validation/validate_vfw.robot
Resource ../stack_validation/validate_vvg.robot
+Resource ../aai/aai_interface.robot
*** Variables ***
${INDEX PATH} /aai/v8
@@ -26,6 +27,7 @@
${GENERIC_VNF_PATH_TEMPLATE} /network/generic-vnfs/generic-vnf/\${vnf_id}/vf-modules/vf-module/\${vf_module_id}
${VLB_CLOSED_LOOP_HACK_BODY} robot/assets/templates/aai/vlb_closed_loop_hack.template
+${VLB_CLOSED_LOOP_DELETE}
*** Keywords ***
Validate Service Instance
@@ -60,7 +62,12 @@
${data}= Fill JSON Template File ${VLB_CLOSED_LOOP_HACK_BODY} ${dict}
${put_resp}= Run A&AI Put Request ${INDEX PATH}${datapath} ${data}
${status_string}= Convert To String ${put_resp.status_code}
- Should Match Regexp ${status_string} ^(201|412)$
+ Should Match Regexp ${status_string} ^(201|412)$
+ Set Test Variable ${VLB_CLOSED_LOOP_DELETE} ${datapath}
+
+Teardown VLB Closed Loop Hack
+ Return From Keyword If ' ${VLB_CLOSED_LOOP_DELETE}' == ''
+ Delete A&AI Entity ${VLB_CLOSED_LOOP_DELETE}
Validate VF Module
diff --git a/robot/resources/asdc_interface.robot b/robot/resources/asdc_interface.robot
index 35fdecf..7967067 100644
--- a/robot/resources/asdc_interface.robot
+++ b/robot/resources/asdc_interface.robot
@@ -47,8 +47,8 @@
*** Keywords ***
Distribute Model From ASDC
[Documentation] goes end to end creating all the asdc objects based ona model and distributing it to the systems. it then returns the service name, vf name and vf module name
- [Arguments] ${model_zip_path}
- ${catalog_service_id}= Add ASDC Catalog Service
+ [Arguments] ${model_zip_path} ${catalog_service_name}=
+ ${catalog_service_id}= Add ASDC Catalog Service ${catalog_service_name}
${catalog_resource_ids}= Create List
: FOR ${zip} IN @{model_zip_path}
\ ${loop_catalog_resource_id}= Setup ASDC Catalog Resource ${zip}
@@ -283,9 +283,11 @@
Should Be Equal As Strings ${resp.status_code} 200
Add ASDC Catalog Service
[Documentation] Creates an asdc Catalog Service and returns its id
+ [Arguments] ${catalog_service_name}
${uuid}= Generate UUID
- ${shortened_uuid}= Evaluate str("${uuid}")[:23]
- ${map}= Create Dictionary service_name=${shortened_uuid}
+ ${shortened_uuid}= Evaluate str("${uuid}")[:23]
+ ${catalog_service_name}= Set Variable If '${catalog_service_name}' =='' ${shortened_uuid} ${catalog_service_name}
+ ${map}= Create Dictionary service_name=${catalog_service_name}
${data}= Fill JSON Template File ${ASDC_CATALOG_SERVICE_TEMPLATE} ${map}
${resp}= Run ASDC Post Request ${ASDC_CATALOG_SERVICES_PATH} ${data} ${ASDC_DESIGNER_USER_ID}
Should Be Equal As Strings ${resp.status_code} 201
diff --git a/robot/resources/demo_preload.robot b/robot/resources/demo_preload.robot
new file mode 100644
index 0000000..92fcafb
--- /dev/null
+++ b/robot/resources/demo_preload.robot
@@ -0,0 +1,94 @@
+*** Settings ***
+Documentation This test template encapsulates the VNF Orchestration use case.
+
+Resource test_templates/model_test_template.robot
+Resource test_templates/vnf_orchestration_test_template.robot
+Resource asdc_interface.robot
+
+Library UUID
+Library Collections
+Library OperatingSystem
+Library HttpLibrary.HTTP
+Library ExtendedSelenium2Library
+
+*** Variables ***
+
+${ADD_DEMO_CUSTOMER_BODY} robot/assets/templates/aai/add_demo_customer.template
+${AAI_INDEX_PATH} /aai/v8
+${VF_MODULES_NAME} _Demo_VFModules.json
+${FILE_CACHE} /share/
+
+*** Keywords ***
+Load Customer And Models
+ [Documentation] Use openECOMP to Orchestrate a service.
+ [Arguments] ${customer_name}
+ Setup Orchestrate VNF ${GLOBAL_AAI_CLOUD_OWNER} ${GLOBAL_OPENSTACK_SERVICE_REGION} SharedNode OwnerType v1 CloudZone
+ Set Test Variable ${CUSTOMER_NAME} ${customer_name}
+ ${status} ${value}= Run Keyword And Ignore Error Distribute Model vFW demoVFW
+ ${status} ${value}= Run Keyword And Ignore Error Distribute Model vLB demoVLB
+ ## MSO polling is 60 second intervals
+ Sleep 60s
+ Create Customer For VNF Demo ${CUSTOMER_NAME} ${CUSTOMER_NAME} INFRA ${GLOBAL_AAI_CLOUD_OWNER} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${TENANT_ID}
+
+Distribute Model
+ [Arguments] ${service} ${modelName}
+ ${service_model_type} ${vnf_type} ${vf_modules}= Model Distribution For Directory ${service} ${modelName}
+ ${jsonString}= Evaluate json.dumps(${vf_modules}) json
+ OperatingSystem.Create File ${FILE_CACHE}${service}${VF_MODULES_NAME} ${jsonString}
+
+Create Customer For VNF Demo
+ [Documentation] Create demo customer for the demo
+ [Arguments] ${customer_name} ${customer_id} ${customer_type} ${clouder_owner} ${cloud_region_id} ${tenant_id}
+ ${data_template}= OperatingSystem.Get File ${ADD_DEMO_CUSTOMER_BODY}
+ ${arguments}= Create Dictionary subscriber_name=${customer_name} global_customer_id=${customer_id} subscriber_type=${customer_type} cloud_owner=${clouder_owner} cloud_region_id=${cloud_region_id} tenant_id=${tenant_id}
+ Set To Dictionary ${arguments} service1=vFW service2=vLB
+ ${data}= Fill JSON Template ${data_template} ${arguments}
+ ${put_resp}= Run A&AI Put Request ${INDEX PATH}${ROOT_CUSTOMER_PATH}${customer_id} ${data}
+ ${status_string}= Convert To String ${put_resp.status_code}
+ Should Match Regexp ${status_string} ^(201|412)$
+ Create Service If Not Exists vFW
+ Create Service If Not Exists vLB
+
+
+Preload Demo
+ [Arguments] ${vnf_name} ${vf_module_name}
+ ${vf_modules}= Create List
+ ${status} ${generic_vnf}= Run Keyword And Ignore Error Get Service Instance ${vnf_name}
+ Run Keyword If '${status}' == 'FAIL' FAIL VNF Name: ${vnf_name} is not found.
+ ${vnf_type}= Set Variable ${generic_vnf['vnf-type']}
+ ${relationships}= Set Variable ${generic_vnf['relationship-list']['relationship']}
+ ${relationship_data}= Get Relationship Data ${relationships}
+ :for ${r} in @{relationship_data}
+ \ ${service}= Set Variable If '${r['relationship-key']}' == 'service-subscription.service-type' ${r['relationship-value']} ${service}
+ \ ${service_instance_id}= Set Variable If '${r['relationship-key']}' == 'service-instance.service-instance-id' ${r['relationship-value']} ${service_instance_id}
+ ${data}= OperatingSystem.Get File ${FILE_CACHE}${service}${VF_MODULES_NAME}
+ ${vf_modules}= Evaluate json.loads('''${data}''') json
+ Log ${generic_vnf}
+ Log ${service_instance_id},${vnf_name},${vnf_type},${vf_module_name},${vf_modules},${service}
+ Setup Browser
+ Preload Vnf ${service_instance_id} ${vnf_name} ${vnf_type} ${vf_module_name} ${vf_modules} ${service} demo
+ [Teardown] Close All Browsers
+
+Get Relationship Data
+ [Arguments] ${relationships}
+ :for ${r} in @{relationships}
+ \ ${status} ${relationship_data} Run Keyword And Ignore Error Set Variable ${r['relationship-data']}
+ \ Return From Keyword If '${status}' == 'PASS' ${relationship_data}
+
+
+Get Service Instance
+ [Arguments] ${vnf_name}
+ ${resp}= Run A&AI Get Request ${AAI_INDEX PATH}/network/generic-vnfs/generic-vnf?vnf-name=${vnf_name}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+
+APPC Mount Point
+ [Arguments] ${vf_module_name}
+ Run Openstack Auth Request auth
+ ${status} ${stack_info}= Run Keyword and Ignore Error Wait for Stack to Be Deployed auth ${vf_module_name} timeout=120s
+ Run Keyword if '${status}' == 'FAIL' FAIL ${vf_module_name} Stack is not found
+ ${stack_id}= Get From Dictionary ${stack_info} id
+ ${server_list}= Get Openstack Servers auth
+ ${vpg_name_0}= Get From Dictionary ${stack_info} vpg_name_0
+ ${vpg_public_ip}= Get Server Ip ${server_list} ${stack_info} vpg_name_0 network_name=public
+ ${appc}= Create Mount Point In APPC ${vpg_name_0} ${vpg_public_ip}
diff --git a/robot/resources/heatbridge.robot b/robot/resources/heatbridge.robot
index eb6a9ed..972c59d 100644
--- a/robot/resources/heatbridge.robot
+++ b/robot/resources/heatbridge.robot
@@ -8,15 +8,22 @@
Resource openstack/keystone_interface.robot
Resource openstack/heat_interface.robot
Resource openstack/nova_interface.robot
+Resource openstack/neutron_interface.robot
Resource aai/aai_interface.robot
*** Variables ***
-${VERSIONED_INDEX_PATH} /aai/v8
${MULTIPART_PATH} /bulkadd
${NAMED_QUERY_PATH} /aai/search/named-query
${NAMED_QUERY_TEMPLATE} robot/assets/templates/aai/named_query.template
${REVERSE_HEATBRIDGE}
+${BASE_URI} /cloud-infrastructure/cloud-regions/cloud-region/\${cloud}/\${region}
+${IMAGE_URI} ${BASE_URI}/images/image/\${image_id}
+${FLAVOR_URI} ${BASE_URI}/flavors/flavor/\${flavor}
+${VSERVER_URI} ${BASE_URI}/tenants/tenant/\${tenant}/vservers/vserver/\${vserver_id}
+${L_INTERFACE_URI} ${VSERVER_URI}/l-interfaces/l-interface/\${linterface_id}
+
+
*** Keywords ***
Execute Heatbridge
@@ -34,11 +41,13 @@
Init Bridge ${openstack_identity_url} ${GLOBAL_VM_PROPERTIES['openstack_username']} ${GLOBAL_VM_PROPERTIES['openstack_password']} ${tenant_id} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${GLOBAL_AAI_CLOUD_OWNER}
${request}= Bridge Data ${stack_id}
Log ${request}
- ${resp}= Run A&AI Put Request ${VERSIONED_INDEX_PATH}${MULTIPART_PATH} ${request}
+ ${resp}= Run A&AI Put Request ${VERSIONED_INDEX_PATH}${MULTIPART_PATH} ${request}
Should Be Equal As Strings ${resp.status_code} 200
- Generate Reverse Heatbridge ${request}
+ ${reverse_heatbridge}= Generate Reverse Heatbridge From Stack Info ${stack_info}
+ Set Test Variable ${REVERSE_HEATBRIDGE} ${reverse_heatbridge}
Run Validation Query ${stack_info} ${service}
+
Run Validation Query
[Documentation] Run A&AI query to validate the bulk add
[Arguments] ${stack_info} ${service}
@@ -56,93 +65,61 @@
${resp}= Run A&AI Post Request ${NAMED_QUERY_PATH} ${request}
Should Be Equal As Strings ${resp.status_code} 200
-Generate Reverse Heatbridge
- [Documentation] Turn all of the HB puts into deletes...
- [Arguments] ${heatbridge_string}
- ${heatbridge}= To Json ${heatbridge_string}
- ${list}= Get From Dictionary ${heatbridge} transactions
- ${transactions}= Create List
- ${dupeDict} Create Dictionary
- :for ${t} in @{list}
- \ ${entry}= Get Deletes From Heatbridge ${t} ${dupeDict}
- \ Run Keyword If len(${entry}) > 0 Append To List ${transactions} ${entry}
- ${reverse}= Create Dictionary transactions=${transactions}
- Set Test Variable ${REVERSE_HEATBRIDGE} ${reverse}
- [Return] ${REVERSE_HEATBRIDGE}
-
-Get Deletes From Heatbridge
- [Documentation] Turn all of the HB puts into deletes... Should be one 'put' with one
- ... Not sure why this is structured this way, dictionary with operation as the key
- ... So only one occurrance of an each operation, but with list of urls/bodies
- ... So multiple gets, puts, etc. but in which order???
- [Arguments] ${putDict} ${dupeDict}
- ${deleteDict}= Create Dictionary
- ${keys}= Get Dictionary Keys ${putDict}
- # We do not expect anyhting other than 'put'
- :for ${key} in @{keys}
- \ Should be Equal ${key} put
- \ ${list}= Get From Dictionary ${putDict} put
- \ ${deleteList}= Get List Of Deletes ${list} ${dupeDict}
- \ Run Keyword If len(${deleteList}) > 0 Set To Dictionary ${deleteDict} delete=${deleteList}
- [Return] ${deleteDict}
-
-Get List Of Deletes
- [Documentation] Turn the list of puts into a list of deletes...
- ... There is only on hash per 'put' but it looks like there can be more...
- [Arguments] ${putList} ${dupeDict}
- ${deleteList}= Create List
- :for ${put} in @{putList}
- \ ${uri}= Get From Dictionary ${put} uri
- \ Continue For Loop If '${uri}' in ${dupeDict}
- \ ${delete}= Create Dictionary uri=${uri}
- \ Append To List ${deleteList} ${delete}
- \ Set To Dictionary ${dupeDict} ${uri}=${uri}
- [Return] ${deleteList}
-
-Execute Bulk Transaction
- [Arguments] ${transaction}
- :for ${put} in ${transaction}
- \ Execute Put List ${put}
-
-Execute Put List
- [Arguments] ${put}
- Log ${put}
- ${list}= Get From Dictionary ${put} put
- :for ${request} in @{list}
- \ Execute Single Put ${request}
-
-Execute Single Put
- [Arguments] ${request}
- ${data}= Get From Dictionary ${request} body
- ${path}= Get From Dictionary ${request} uri
- ${resp}= Run A&AI Put Request ${VERSIONED_INDEX_PATH}${path} ${data}
- Should Be Equal As Strings ${resp.status_code} 201
-
Execute Reverse Heatbridge
- [Documentation] VID has already torn down the stack, reverse HB
- [Arguments] ${reverse_heatbridge}
- ${resp}= Run A&AI Put Request ${VERSIONED_INDEX_PATH}${MULTIPART_PATH} ${reverse_heatbridge}
- Should Be Equal As Strings ${resp.status_code} 200
-
+ [Documentation] VID has already torn down the stack, reverse HB
+ Return From Keyword If len(${REVERSE_HEATBRIDGE}) == 0
+ :for ${uri} in @{REVERSE_HEATBRIDGE}
+ \ Run Keyword And Ignore Error Delete A&AI Entity ${uri}
-Execute Heatbridge Teardown
- [Documentation] Run teardown against the stack to generate a bulkadd message that removes it
- [Arguments] ${stack_name}
+Generate Reverse Heatbridge From Stack Name
+ [Arguments] ${stack_name}
Run Openstack Auth Request auth
- ${stack_info}= Wait for Stack to Be Deployed auth ${stack_name}
+ ${stack_info}= Wait for Stack to Be Deployed auth ${stack_name} timeout=10s
+ ${reverse_heatbridge}= Generate Reverse Heatbridge From Stack Info ${stack_info}
+ [Return] ${reverse_heatbridge}
+
+Generate Reverse Heatbridge From Stack Info
+ [Arguments] ${stack_info}
+ ${reverse_heatbridge}= Create List
+ ${stack_name}= Get From Dictionary ${stack_info} name
${stack_id}= Get From Dictionary ${stack_info} id
${tenant_id}= Get From Dictionary ${stack_info} OS::project_id
+ ${keys}= Create Dictionary region=${GLOBAL_OPENSTACK_SERVICE_REGION} cloud=${GLOBAL_AAI_CLOUD_OWNER} tenant=${tenant_id}
${stack_resources}= Get Stack Resources auth ${stack_name} ${stack_id}
${resource_list}= Get From Dictionary ${stack_resources} resources
- Get Length ${resource_list}
- Log ${resource_list}
:FOR ${resource} in @{resource_list}
\ Log ${resource}
- \ Run Keyword If '${resource['resource_type']}' == 'OS::Nova::Server' Execute Server Teardown auth ${resource['physical_resource_id']}
-
-Execute Server Teardown
+ \ Run Keyword If '${resource['resource_type']}' == 'OS::Neutron::Port' Generate Linterface Uri auth ${resource['physical_resource_id']} ${reverse_heatbridge} ${keys}
+ :FOR ${resource} in @{resource_list}
+ \ Log ${resource}
+ \ Run Keyword If '${resource['resource_type']}' == 'OS::Nova::Server' Generate Vserver Uri auth ${resource['physical_resource_id']} ${reverse_heatbridge} ${keys} ${resource_list}
+ [Return] ${reverse_heatbridge}
+
+Generate Vserver Uri
[Documentation] Run teardown against the server to generate a message that removes it
- [Arguments] ${alias} ${server_id}
- ${server}= Get Openstack Server By Id ${alias} ${server_id}
- Log ${server}
\ No newline at end of file
+ [Arguments] ${alias} ${port_id} ${reverse_heatbridge} ${keys} ${resource_list}
+ ${resp}= Get Openstack Server By Id ${alias} ${port_id}
+ Return From Keyword If '${resp.status_code}' != '200'
+ ${info}= Set Variable ${resp.json()}
+ Set To Dictionary ${keys} vserver_id=${info['server']['id']}
+ Set To Dictionary ${keys} flavor=${info['server']['flavor']['id']}
+ Set To Dictionary ${keys} image_id=${info['server']['image']['id']}
+ ${uri}= Template String ${VSERVER_URI} ${keys}
+ Append To List ${reverse_heatbridge} ${uri}
+ ${uri}= Template String ${FLAVOR_URI} ${keys}
+ Append To List ${reverse_heatbridge} ${uri}
+ ${uri}= Template String ${IMAGE_URI} ${keys}
+ Append To List ${reverse_heatbridge} ${uri}
+
+Generate Linterface Uri
+ [Documentation] Run teardown against the server to generate a message that removes it
+ [Arguments] ${alias} ${server_id} ${reverse_heatbridge} ${keys}
+ ${resp}= Get Openstack Port By Id ${alias} ${server_id}
+ Return From Keyword If '${resp.status_code}' != '200'
+ ${info}= Set Variable ${resp.json()}
+ Set To Dictionary ${keys} vserver_id=${info['port']['device_id']}
+ Set To Dictionary ${keys} linterface_id=${info['port']['name']}
+ ${uri}= Template String ${L_INTERFACE_URI} ${keys}
+ Append To List ${reverse_heatbridge} ${uri}
+
diff --git a/robot/resources/openstack/neutron_interface.robot b/robot/resources/openstack/neutron_interface.robot
index 77635cd..a88a943 100644
--- a/robot/resources/openstack/neutron_interface.robot
+++ b/robot/resources/openstack/neutron_interface.robot
@@ -112,6 +112,12 @@
:for ${port} in @{ports['ports']}
\ Run Keyword If '${net['network_id']}' == '${port['network_id']}' Append To List ${net_ports} ${port}
[Return] ${net_ports}
+
+Get Openstack Port By Id
+ [Arguments] ${alias} ${port_id}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_NEUTRON_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NEUTRON_PORT_PATH}/${port_id}
+ [Return] ${resp}
+
Delete Openstack Port
[Arguments] ${alias} ${port_id}
diff --git a/robot/resources/test_templates/model_test_template.robot b/robot/resources/test_templates/model_test_template.robot
index 263c592..e97984d 100644
--- a/robot/resources/test_templates/model_test_template.robot
+++ b/robot/resources/test_templates/model_test_template.robot
@@ -23,7 +23,7 @@
*** Keywords ***
Model Distribution For Directory
- [Arguments] ${service}
+ [Arguments] ${service} ${catalog_service_name}=
${directory_list}= Get From Dictionary ${GLOBAL_SERVICE_FOLDER_MAPPING} ${service}
${ziplist}= Create List
:for ${directory} in @{directory_list}
@@ -32,7 +32,7 @@
\ OperatingSystem.Create Directory ${ASDC_ASSETS_DIRECTORY}/temp
\ Create Zip From Files In Directory ${folder} ${zip}
\ Append To List ${ziplist} ${zip}
- ${catalog_service_name} ${catalog_resource_name} ${vf_modules} ${catalog_resource_ids} ${catalog_service_id} Distribute Model From ASDC ${ziplist}
+ ${catalog_service_name} ${catalog_resource_name} ${vf_modules} ${catalog_resource_ids} ${catalog_service_id} Distribute Model From ASDC ${ziplist} ${catalog_service_name}
Set Test Variable ${CATALOG_RESOURCE_IDS} ${catalog_resource_ids}
Set Test Variable ${CATALOG_SERVICE_ID} ${catalog_service_id}
[Return] ${catalog_service_name} ${catalog_resource_name} ${vf_modules}
diff --git a/robot/resources/test_templates/vnf_orchestration_test_template.robot b/robot/resources/test_templates/vnf_orchestration_test_template.robot
index 00f15cf..a149745 100644
--- a/robot/resources/test_templates/vnf_orchestration_test_template.robot
+++ b/robot/resources/test_templates/vnf_orchestration_test_template.robot
@@ -5,6 +5,7 @@
Resource ../vid/vid_interface.robot
Resource ../aai/service_instance.robot
Resource ../vid/create_vid_vnf.robot
+Resource ../vid/teardown_vid.robot
Resource ../sdngc_interface.robot
Resource model_test_template.robot
@@ -31,10 +32,12 @@
${STACK_NAME}
${SERVICE}
${VVG_SERVER_ID}
+${SERVICE_INSTANCE_ID}
*** Keywords ***
Orchestrate VNF
+ [Documentation] Use openECOMP to Orchestrate a service.
[Arguments] ${customer_name} ${service} ${product_family} ${lcp_region} ${tenant}
${uuid}= Generate UUID
Set Test Variable ${CUSTOMER_NAME} ${customer_name}_${uuid}
@@ -51,6 +54,7 @@
Setup Browser
Login To VID GUI
${service_instance_id}= Create VID Service Instance ${customer_name} ${service_model_type} ${service} ${service_name}
+ Set Test Variable ${SERVICE_INSTANCE_ID} ${service_instance_id}
Validate Service Instance ${service_instance_id} ${service} ${customer_name}
Create VID VNF ${service_instance_id} ${vnf_name} ${product_family} ${lcp_region} ${tenant} ${vnf_type}
${vf_module_type} ${closedloop_vf_module}= Preload Vnf ${service_instance_id} ${vnf_name} ${vnf_type} ${vf_module_name} ${vf_modules} ${service} ${uuid}
@@ -61,7 +65,6 @@
Execute Heatbridge ${vf_module_name} ${service_instance_id} ${service}
Validate VF Module ${vf_module_name} ${service}
[Return] ${vf_module_name} ${service}
- [Teardown] Close All Browsers
Create Customer For VNF
@@ -73,7 +76,8 @@
Create Service If Not Exists ${service_type}
Setup Orchestrate VNF
- [Documentation] Called before each test case to ensure data required by the Orchstrate VNF exists
+ [Documentation] Called before each test case to ensure tenant and region data
+ ... required by the Orchstrate VNF exists in A&AI
[Arguments] ${cloud_owner} ${cloud_region_id} ${cloud_type} ${owner_defined_type} ${cloud_region_version} ${cloud_zone}
Initialize Tenant From Openstack
Initialize Regions From Openstack
@@ -82,19 +86,22 @@
Log Orchestrate VNF setup complete
Initialize Tenant From Openstack
+ [Documentation] Initialize the tenant test variables
Run Openstack Auth Request auth
${tenants}= Get Current Openstack Tenant auth
${tenant_name}= Evaluate $tenants.get("name")
${tenant_id}= Evaluate $tenants.get("id")
- Set Suite Variable ${TENANT_NAME} ${tenant_name}
- Set Suite Variable ${TENANT_ID} ${tenant_id}
+ Set Test Variable ${TENANT_NAME} ${tenant_name}
+ Set Test Variable ${TENANT_ID} ${tenant_id}
Initialize Regions From Openstack
+ [Documentation] Initialize the regions test variable
Run Openstack Auth Request auth
${regs}= Get Openstack Regions auth
- Set Suite Variable ${REGIONS} ${regs}
+ Set Test Variable ${REGIONS} ${regs}
Create VVG Server
+ [Documentation] For the VolumeGroup test case, create a server to attach the volume group to be orchestrated.
[Arguments] ${uuid}
Run Openstack Auth Request auth
${vvg_server_name}= Catenate vVG_${uuid}
@@ -106,7 +113,9 @@
Set To Dictionary ${vvg_params} nova_instance ${server_id}
Wait for Server to Be Active auth ${server_id}
-Get VVG Preload Parameters
+Get VVG Preload Parameters
+ [Documentation] Get preload parameters for the VVG test case so we can include
+ ... the nova_instance id of the attached server
${test_dict}= Get From Dictionary ${GLOBAL_PRELOAD_PARAMETERS} Vnf-Orchestration
${vvg_params} Get From Dictionary ${test_dict} vvg_preload.template
[Return] ${vvg_params}
@@ -114,15 +123,15 @@
Teardown VNF
[Documentation] Called at the end of a test case to tear down the VNF created by Orchestrate VNF
Teardown VVG Server
- # Free up rackspace resources until true teardown is implemented
- Run Keyword If '${TEST STATUS}' == 'PASS' Teardown Stack ${STACK_NAME}
- Set Test Variable ${VVG_SERVER_ID} ''
-
- ## Conditional remove so as to enable manual teardown testing of failed stacks
+ Teardown VLB Closed Loop Hack
+ Run Keyword If '${TEST STATUS}' == 'PASS' Teardown VID ${SERVICE_INSTANCE_ID} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${TENANT_ID}
Run Keyword If '${TEST STATUS}' == 'PASS' Teardown Model Distribution
- Log Teardown VNF not completely implemented
+ Run Keyword If '${TEST STATUS}' == 'PASS' Clean A&AI Inventory
+ Close All Browsers
+ Log Teardown VNF implemented for successful tests only
Teardown VVG Server
+ [Documentation] Teardown the server created as a place to mount the Volume Group.
Return From Keyword if '${VVG_SERVER_ID}' == ''
Delete Server auth ${VVG_SERVER_ID}
Wait for Server To Be Deleted auth ${VVG_SERVER_ID}
@@ -131,7 +140,7 @@
Log Teardown VVG Server Completed
Teardown Stack
- [Documentation] Called at the end of a test case to tear down the Stack created by Orchestrate VNF
+ [Documentation] OBSOLETE - Called at the end of a test case to tear down the Stack created by Orchestrate VNF
[Arguments] ${stack}
Run Openstack Auth Request auth
${stack_info}= Get Stack Details auth ${stack}
@@ -141,43 +150,13 @@
Delete Openstack Stack auth ${stack} ${stack_id}
Log Deleted ${stack} ${stack_id}
Run Keyword If '${key_pair_status}' == 'PASS' Delete Openstack Keypair auth ${keypair_name}
- ## Removed code to remove all of the IPs from the oam network - didn't help
-
-
-Get Ecomp Private Net Ports
- [Arguments] ${alias} ${stack_info} ${service}
- ${list}= Create List
- ${netid}= Get From Dictionary ${stack_info} ecomp_private_net_id
- ${cidr}= Get From Dictionary ${stack_info} ecomp_private_net_cidr
- ${ip_addresses}= Get Ecomp Ip Addresses ${stack_info} ${service}
- ${net_ports}= Get Openstack Ports For Subnet ${alias} ${netid} ${cidr}
- :for ${ip_address} in @{ip_addresses}
- \ ${port}= Find Ecomp Port ${net_ports} ${ip_address}
- \ Run Keyword If ${port} is not None Append To List ${list} ${port}
- [Return] ${list}
-
-Get Ecomp Ip Addresses
- [Arguments] ${stack_info} ${service}
- ${ip_addresses}= Create List
- ${names}= Get From Dictionary ${GLOBAL_SERVICE_ECOMP_IP_MAPPING} ${service}
- :for ${name} in @{names}
- \ ${ip}= Get From Dictionary ${stack_info} ${name}
- \ Append To List ${ip_addresses} ${ip}
- [Return] ${ip_addresses}
-
-Find Ecomp Port
- [Arguments] ${ports} ${ip_address}
- :for ${port} in @{ports}
- \ Return From Keyword If '${port['fixed_ips'][0]['ip_address']}' == '${ip_address}' ${port}
- [Return] None
-
+ Teardown VLB Closed Loop Hack
Clean A&AI Inventory
[Documentation] Clean up Tenant in A&AI, Create Customer, Create Service and related relationships
- [Arguments] ${customer_id} ${cloud_owner} ${service_type}
:FOR ${region} IN @{REGIONS}
- \ Delete Tenant ${TENANT_ID} ${cloud_owner} ${region}
- \ Delete Cloud Region ${TENANT_ID} ${cloud_owner} ${region}
- Delete Customer ${customer_id}
- Delete Service If Exists ${service_type}
+ \ Delete Tenant ${TENANT_ID} ${GLOBAL_AAI_CLOUD_OWNER} ${region}
+ \ Delete Cloud Region ${TENANT_ID} ${GLOBAL_AAI_CLOUD_OWNER} ${region}
+ Delete Customer ${CUSTOMER_NAME}
+ Delete Service If Exists ${SERVICE}
diff --git a/robot/resources/vid/teardown_vid.robot b/robot/resources/vid/teardown_vid.robot
index 50b5051..8840854 100644
--- a/robot/resources/vid/teardown_vid.robot
+++ b/robot/resources/vid/teardown_vid.robot
@@ -11,20 +11,36 @@
*** Variables ***
${VID_ENV} /vid
-${VID_SERVICE_MODELS_SEARCH_URL} ${GLOBAL_VID_SERVER}${VID_ENV}/serviceModels.htm#/instances/subdetails?selectedSubscriber=\${customer_id}
-
+${VID_SERVICE_MODELS_SEARCH_CUST} ${GLOBAL_VID_SERVER}${VID_ENV}/serviceModels.htm#/instances/subdetails?selectedSubscriber=\${customer_id}
+${VID_SERVICE_MODELS_SEARCH_URL} ${GLOBAL_VID_SERVER}${VID_ENV}/serviceModels.htm#/instances/services
*** Keywords ***
Teardown VID
[Documentation] Teardown the VID This assumes that the any runnign stacks have been torn down
- [Arguments] ${service_instance_id} ${lcp_region} ${tenant}
- # Keep going to the VID service instance until all of the remove icons are goe
+ [Arguments] ${service_instance_id} ${lcp_region} ${tenant}
+ Return From Keyword If len('${service_instance_id}') == 0
+ # Keep going to the VID service instance until we get the pop-up alert that there is no service instance
Wait Until Keyword Succeeds 300s 1s Delete VID ${service_instance_id} ${lcp_region} ${tenant}
Delete VID
[Documentation] Teardown the next VID entity that has a Remove icon.
- [Arguments] ${service_instance_id} ${lcp_region} ${tenant}
+ [Arguments] ${service_instance_id} ${lcp_region} ${tenant}
+ # For vLB closed loop, we may have 2 vf modules and the vDNS one needs to be removed first.
+ ${remove_order}= Create List vDNS_Ete Vfmodule_Ete
+
+ # FAIL status is returned in ${vfmodule} because FAIL are ignored during teardown
+ ${status} ${vfmodule}= Run Keyword and Ignore Error Delete Next VID Entity ${service_instance_id} ${lcp_region} ${tenant} ${remove_order}
+ Return From Keyword If '${status}' == 'FAIL'
+ Return From Keyword If '${vfmodule}' == 'FAIL'
+ # After tearing down a VF module, execute the reverse HB for it to remove the references from A&AI
+ Run Keyword If 'Vfmodule_Ete' in '${vfmodule}' Execute Reverse Heatbridge
+ Fail Continue with Next Remove
+
+Delete Next VID Entity
+ [Documentation] Teardown the next VID entity that has a Remove icon.
+ [Arguments] ${service_instance_id} ${lcp_region} ${tenant} ${remove_order}
+ ${vfmodule}= Catenate
Go To ${VID_SERVICE_MODELS_SEARCH_URL}
Wait Until Page Contains Please search by timeout=60s
Wait Until Page Contains Element xpath=//div[@class='statusLine aaiHidden'] timeout=60s
@@ -32,32 +48,44 @@
# If we don't wait for this control to be enabled, the submit results in a 'not found' pop-up (UnexpectedAlertPresentException)
Input Text When Enabled //input[@name='selectedServiceInstance'] ${service_instance_id}
- Click Button button=Submit
- Wait Until Page Contains Element link=View/Edit timeout=60s
+
+ # When Handle alert detects a pop-up. it will return FAIL and we are done
+ # Return from Keyword is required because FAIL is inored during teardown
+ ${status} ${value} Run Keyword And Ignore Error Handle Alert
+ Return From Keyword If '${status}' == 'FAIL' ${status}
+ ${status} ${value} Run Keyword And Ignore Error Wait Until Page Contains Element link=View/Edit timeout=60s
+ Return From Keyword If '${status}' == 'FAIL' ${status}
+
+
Click Element link=View/Edit
Wait Until Page Contains View/Edit Service Instance timeout=60s
- ${status} ${data}= Run Keyword And Ignore Error Wait Until Element Is Visible xpath=//li/div/a/span[@class='glyphicon glyphicon-remove'] timeout=120s
- Return From Keyword If '${status}' == 'FAIL'
+ Wait Until Element Is Visible xpath=//a/span[@class='glyphicon glyphicon-remove'] timeout=120s
- # At least one more Remove!
-
- # This list is a bit ogf a hack to determine the order of removal if there is more than one remove icon.
- # Cannot tell how this will hold up once all of the VID removes are working for all conditions.
- ${remove_order}= Create List Vfmodule_Ete
:for ${remove_first} in @{remove_order}
- \ ${status} ${data}= Run Keyword And Ignore Error Page Should Contain Element xpath=//li/div[contains(.,'${remove_first}')]/a/span[@class='glyphicon glyphicon-remove']
- \ Run Keyword If '${status}' == 'PASS' Click On Element When Visible xpath=//li/div[contains(.,'${remove_first}')]/a/span[@class='glyphicon glyphicon-remove'] timeout=120s
- \ Run Keyword If '${status}' == 'FAIL' Click On Element When Visible xpath=//li/div/a/span[@class='glyphicon glyphicon-remove'] timeout=120s
+ \ ${remove_xpath}= Set Variable //li/div[contains(.,'${remove_first}')]/a/span[@class='glyphicon glyphicon-remove']
+ \ ${status} ${data}= Run Keyword And Ignore Error Page Should Contain Element xpath=${remove_xpath}
+ \ Exit For Loop If '${status}' == 'PASS'
+ \ ${remove_xpath}= Set Variable //li/div/a/span[@class='glyphicon glyphicon-remove']
+ Click On Element When Visible xpath=${remove_xpath}
- Wait Until Page Contains Element xpath=//select[@parameter-id='lcpRegion']
- Select From List By Label xpath=//select[@parameter-id='lcpRegion'] ${lcp_region}
- Select From List By Label xpath=//select[@parameter-id='tenant'] ${tenant}
+ ${status} ${value}= Run Keyword and Ignore Error Wait Until Page Contains Element xpath=//select[@parameter-id='lcpRegion']
+ Run Keyword If '${status}'=='PASS' Select From List By Label xpath=//select[@parameter-id='lcpRegion'] ${lcp_region}
+ Run Keyword If '${status}'=='PASS' Select From List By Label xpath=//select[@parameter-id='tenant'] ${tenant}
+ ${status} ${vfmodule}= Run Keyword And Ignore Error Get Text xpath=//td[contains(text(), 'Vf Module Name')]/../td[2]
Click Element xpath=//div[@class='buttonRow']/button[@ngx-enabled='true']
#//*[@id="mContent"]/div/div/div/div/table/tbody/tr/td/div/div[2]/div/div[1]/div[5]/button[1]
- Wait Until Page Contains Status:COMPLETE - 300s
+ Wait Until Page Contains 100 % 300s
${response text}= Get Text xpath=//div[@ng-controller='deletionDialogController']//div[@ng-controller= 'msoCommitController']/pre[@class = 'log ng-binding']
${request_id}= Parse Request Id ${response text}
- Click Element button=Close
+ Click Element xpath=//div[@class='ng-scope']/div[@class = 'buttonRow']/button[text() = 'Close']
Poll MSO Get Request ${GLOBAL_MSO_STATUS_PATH}${request_id} COMPLETE
- Fail Successful VID Delete - continue with next delete
+ [Return] ${vfmodule}
+Handle Alert
+ [Documentation] When service instance has been deleted, an alert will be triggered on the search to end the loop
+ ... The various Alert keywords did not prevent the alert exception on the Click ELement, hence this roundabout way of handling the alert
+ Run Keyword And Ignore Error Click Element button=Submit
+ ${status} ${t}= Run Keyword And Ignore Error Get Alert Message
+ Return From Keyword If '${status}' == 'FAIL'
+ Fail ${t}
+
\ No newline at end of file
diff --git a/robot/testsuites/demo.robot b/robot/testsuites/demo.robot
new file mode 100644
index 0000000..5c8f415
--- /dev/null
+++ b/robot/testsuites/demo.robot
@@ -0,0 +1,25 @@
+*** Settings ***
+Documentation Executes the VNF Orchestration Test cases including setup and teardown
+...
+
+Resource ../resources/demo_preload.robot
+*** Variables ***
+
+${VNF_NAME} DemoVNF
+${MODULE_NAME} DemoModuleName
+
+*** Test Cases ***
+Initialize Customer And Models
+ [Tags] InitDemo
+ Load Customer And Models Demonstration
+
+Preload VNF
+ [Tags] PreloadDemo
+ Preload Demo ${VNF_NAME} ${MODULE_NAME}
+
+Create APPC Mount Point
+ [Tags] APPCMountPointDemo
+ APPC Mount Point ${MODULE_NAME}
+
+
+
diff --git a/robot/testsuites/health-check.robot b/robot/testsuites/health-check.robot
index 0a05375..d27c38e 100644
--- a/robot/testsuites/health-check.robot
+++ b/robot/testsuites/health-check.robot
@@ -14,12 +14,8 @@
Resource ../resources/portal_interface.robot
Resource ../resources/mr_interface.robot
Resource ../resources/aaf_interface.robot
-Resource ../resources/heatbridge.robot
*** Test Cases ***
-Do Teardown
- Execute Heatbridge Teardown Vfmodule_Ete_Name49a8fbc5-3e94-430d-80d6-a52826961170
-
Basic DCAE Health Check
[Tags] health
Run DCAE Health Check