diff options
author | jf9860 <jf9860@att.com> | 2017-02-22 16:52:54 -0500 |
---|---|---|
committer | jf9860 <jf9860@att.com> | 2017-02-22 17:02:20 -0500 |
commit | 75010a4fe2ec3e182b45196e7e5b2c7889673092 (patch) | |
tree | bb235c1a4732e7c49f53b2f309ebced3f6d9cf80 /robot | |
parent | 0f7f2653d2190514d923046b40975967f82b0b3e (diff) |
Complete teardown implementation.
Add demo.sh to support hands on demo
Change-Id: Idf235957bd992e6d7482c8241f6ba8b8944c2826
Signed-off-by: jf9860 <jf9860@att.com>
Diffstat (limited to 'robot')
-rw-r--r-- | robot/assets/templates/aai/add_cloud_region_body.template | 15 | ||||
-rw-r--r-- | robot/assets/templates/aai/add_demo_customer.template | 47 | ||||
-rw-r--r-- | robot/assets/templates/aai/add_tenant_body.template | 1 | ||||
-rw-r--r-- | robot/resources/aai/create_tenant.robot | 24 | ||||
-rw-r--r-- | robot/resources/aai/service_instance.robot | 9 | ||||
-rw-r--r-- | robot/resources/asdc_interface.robot | 10 | ||||
-rw-r--r-- | robot/resources/demo_preload.robot | 94 | ||||
-rw-r--r-- | robot/resources/heatbridge.robot | 139 | ||||
-rw-r--r-- | robot/resources/openstack/neutron_interface.robot | 6 | ||||
-rw-r--r-- | robot/resources/test_templates/model_test_template.robot | 4 | ||||
-rw-r--r-- | robot/resources/test_templates/vnf_orchestration_test_template.robot | 75 | ||||
-rw-r--r-- | robot/resources/vid/teardown_vid.robot | 74 | ||||
-rw-r--r-- | robot/testsuites/demo.robot | 25 | ||||
-rw-r--r-- | robot/testsuites/health-check.robot | 4 |
14 files changed, 346 insertions, 181 deletions
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 95b2525c..00000000 --- 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 00000000..e56577c5 --- /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 a3cea10a..a7dbbbf7 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 da21ac92..e5a55966 100644 --- a/robot/resources/aai/create_tenant.robot +++ b/robot/resources/aai/create_tenant.robot @@ -28,12 +28,24 @@ Inventory Tenant If Not Exists 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 @@ Get Tenants 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 c9fdadd6..5fffa02f 100644 --- a/robot/resources/aai/service_instance.robot +++ b/robot/resources/aai/service_instance.robot @@ -14,6 +14,7 @@ Resource ../json_templater.robot 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 @@ ${SERVCE INSTANCE TEMPLATE} robot/assets/templates/aai/service_subscription.t ${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 @@ VLB Closed Loop Hack ${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 35fdecf1..79670671 100644 --- a/robot/resources/asdc_interface.robot +++ b/robot/resources/asdc_interface.robot @@ -47,8 +47,8 @@ ${ASDC_RESOURCE_INSTANCE_TEMPLATE} robot/assets/templates/asdc/resource_insta *** 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 @@ Upload ASDC Heat Package 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 00000000..92fcafbb --- /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 eb6a9ed0..972c59de 100644 --- a/robot/resources/heatbridge.robot +++ b/robot/resources/heatbridge.robot @@ -8,15 +8,22 @@ Library UUID 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 @@ Execute Heatbridge 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 @@ Run Vserver Query ${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']} + \ 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} ${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} -Execute Server Teardown +Generate Linterface 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} ${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 77635cdd..a88a9436 100644 --- a/robot/resources/openstack/neutron_interface.robot +++ b/robot/resources/openstack/neutron_interface.robot @@ -112,6 +112,12 @@ Get Openstack Ports For Subnet :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 263c5929..e97984d5 100644 --- a/robot/resources/test_templates/model_test_template.robot +++ b/robot/resources/test_templates/model_test_template.robot @@ -23,7 +23,7 @@ ${CATALOG_SERVICE_ID} *** 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 @@ Model Distribution For Directory \ 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 00f15cf8..a149745a 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/create_service_instance.robot 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 @@ ${CUSTOMER_NAME} ${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 @@ Orchestrate VNF 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 @@ Orchestrate VNF 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 Customer For VNF 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 @@ Setup Orchestrate VNF 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 @@ Create VVG Server 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 @@ Get VVG Preload Parameters 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 @@ Teardown VVG Server 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 @@ Teardown Stack 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 50b50518..88408546 100644 --- a/robot/resources/vid/teardown_vid.robot +++ b/robot/resources/vid/teardown_vid.robot @@ -11,20 +11,36 @@ Resource create_service_instance.robot *** 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 @@ Delete VID # 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' - - # At least one more Remove! + Wait Until Element Is Visible xpath=//a/span[@class='glyphicon glyphicon-remove'] timeout=120s - # 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 00000000..5c8f415b --- /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 0a053754..d27c38e5 100644 --- a/robot/testsuites/health-check.robot +++ b/robot/testsuites/health-check.robot @@ -14,12 +14,8 @@ Resource ../resources/appc_interface.robot 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 |