aboutsummaryrefslogtreecommitdiffstats
path: root/robot/resources
diff options
context:
space:
mode:
authorDR695H <dr695h@att.com>2017-02-17 18:44:24 -0500
committerDR695H <dr695h@att.com>2017-02-17 18:44:41 -0500
commitccff30b6e325f359879595998e83bbfe6624c851 (patch)
treec98f950f33baa71d21b091b6b10ca3ffb7700467 /robot/resources
parent234c2226d8cb3368a7af3d280a5ec280782bed63 (diff)
Initial checkin of EopenECOMP testsuite
Change-Id: I64a2b6d8cf66169829866b73b3d26a4ff59b0a42 Signed-off-by: DR695H <dr695h@att.com>
Diffstat (limited to 'robot/resources')
-rw-r--r--robot/resources/aaf_interface.robot29
-rw-r--r--robot/resources/aai/aai_interface.robot58
-rw-r--r--robot/resources/aai/create_customer.robot41
-rw-r--r--robot/resources/aai/create_service.robot75
-rw-r--r--robot/resources/aai/create_tenant.robot79
-rw-r--r--robot/resources/aai/network.robot42
-rw-r--r--robot/resources/aai/service_instance.robot82
-rw-r--r--robot/resources/aai/volume_group.robot31
-rw-r--r--robot/resources/appc_interface.robot54
-rw-r--r--robot/resources/asdc_interface.robot462
-rw-r--r--robot/resources/browser_setup.robot43
-rw-r--r--robot/resources/dcae_interface.robot57
-rw-r--r--robot/resources/global_properties.robot22
-rw-r--r--robot/resources/heatbridge.robot148
-rw-r--r--robot/resources/json_templater.robot21
-rw-r--r--robot/resources/mr_interface.robot28
-rw-r--r--robot/resources/mso_interface.robot54
-rw-r--r--robot/resources/openstack/cinder_interface.robot50
-rw-r--r--robot/resources/openstack/heat_interface.robot93
-rw-r--r--robot/resources/openstack/keystone_interface.robot49
-rw-r--r--robot/resources/openstack/neutron_interface.robot123
-rw-r--r--robot/resources/openstack/nova_interface.robot149
-rw-r--r--robot/resources/openstack/openstack_common.robot50
-rw-r--r--robot/resources/policy_interface.robot58
-rw-r--r--robot/resources/portal_interface.robot28
-rw-r--r--robot/resources/sdngc_interface.robot203
-rw-r--r--robot/resources/ssh/files.robot50
-rw-r--r--robot/resources/ssh/processes.robot74
-rw-r--r--robot/resources/stack_validation/darkstat_interface.robot82
-rw-r--r--robot/resources/stack_validation/packet_generator_interface.robot98
-rw-r--r--robot/resources/stack_validation/policy_check_vfw.robot95
-rw-r--r--robot/resources/stack_validation/validate_common.robot51
-rw-r--r--robot/resources/stack_validation/validate_dns_scaling.robot43
-rw-r--r--robot/resources/stack_validation/validate_vfw.robot94
-rw-r--r--robot/resources/stack_validation/validate_vlb.robot60
-rw-r--r--robot/resources/stack_validation/validate_vvg.robot17
-rw-r--r--robot/resources/test_templates/closedloop_test_template.robot210
-rw-r--r--robot/resources/test_templates/model_test_template.robot57
-rw-r--r--robot/resources/test_templates/vnf_orchestration_test_template.robot183
-rw-r--r--robot/resources/vid/create_service_instance.robot57
-rw-r--r--robot/resources/vid/create_vid_vnf.robot122
-rw-r--r--robot/resources/vid/teardown_vid.robot63
-rw-r--r--robot/resources/vid/vid_interface.robot101
43 files changed, 3586 insertions, 0 deletions
diff --git a/robot/resources/aaf_interface.robot b/robot/resources/aaf_interface.robot
new file mode 100644
index 00000000..57d4aabc
--- /dev/null
+++ b/robot/resources/aaf_interface.robot
@@ -0,0 +1,29 @@
+*** Settings ***
+Documentation The main interface for interacting with AAF. It handles low level stuff like managing the http request library and AAF required fields
+Library RequestsClientCert
+Library RequestsLibrary
+Library UUID
+
+Resource global_properties.robot
+
+*** Variables ***
+${AAF_HEALTH_CHECK_PATH} /authz/nss/org.openecomp
+
+*** Keywords ***
+Run AAF Health Check
+ [Documentation] Runs AAF Health check
+ ${resp}= Run AAF Get Request ${AAF_HEALTH_CHECK_PATH}
+ Should Be Equal As Strings ${resp.status_code} 200
+ Should Contain ${resp.json()} ns
+
+Run AAF Get Request
+ [Documentation] Runs AAF Get request
+ [Arguments] ${data_path}
+ ${auth}= Create List ${GLOBAL_AAF_USERNAME} ${GLOBAL_AAF_PASSWORD}
+ ${session}= Create Session aaf ${GLOBAL_AAF_SERVER} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Get Request aaf ${data_path} headers=${headers}
+ Log Received response from aaf ${resp.text}
+ [Return] ${resp}
+
diff --git a/robot/resources/aai/aai_interface.robot b/robot/resources/aai/aai_interface.robot
new file mode 100644
index 00000000..43451809
--- /dev/null
+++ b/robot/resources/aai/aai_interface.robot
@@ -0,0 +1,58 @@
+*** Settings ***
+Documentation The main interface for interacting with A&AI. It handles low level stuff like managing the http request library and A&AI required fields
+Library RequestsLibrary
+Library UUID
+Resource ../global_properties.robot
+
+*** Variables ***
+${AAI_HEALTH_PATH} /aai/util/echo?action=long
+
+*** Keywords ***
+Run A&AI Health Check
+ [Documentation] Runs an A&AI health check
+ ${resp}= Run A&AI Get Request ${AAI_HEALTH_PATH}
+ Should Be Equal As Strings ${resp.status_code} 200
+
+Run A&AI Get Request
+ [Documentation] Runs an A&AI get request
+ [Arguments] ${data_path}
+ ${auth}= Create List ${GLOBAL_AAI_USERNAME} ${GLOBAL_AAI_PASSWORD}
+ ${session}= Create Session aai ${GLOBAL_AAI_SERVER_URL} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Get Request aai ${data_path} headers=${headers}
+ Log Received response from aai ${resp.text}
+ [Return] ${resp}
+
+Run A&AI Put Request
+ [Documentation] Runs an A&AI put request
+ [Arguments] ${data_path} ${data}
+ ${auth}= Create List ${GLOBAL_AAI_USERNAME} ${GLOBAL_AAI_PASSWORD}
+ ${session}= Create Session aai ${GLOBAL_AAI_SERVER_URL} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Put Request aai ${data_path} data=${data} headers=${headers}
+ Log Received response from aai ${resp.text}
+ [Return] ${resp}
+
+Run A&AI Post Request
+ [Documentation] Runs an A&AI Post request
+ [Arguments] ${data_path} ${data}
+ ${auth}= Create List ${GLOBAL_AAI_USERNAME} ${GLOBAL_AAI_PASSWORD}
+ ${session}= Create Session aai ${GLOBAL_AAI_SERVER_URL} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Post Request aai ${data_path} data=${data} headers=${headers}
+ Log Received response from aai ${resp.text}
+ [Return] ${resp}
+
+Run A&AI Delete Request
+ [Documentation] Runs an A&AI delete request
+ [Arguments] ${data_path} ${resource_version}
+ ${auth}= Create List ${GLOBAL_AAI_USERNAME} ${GLOBAL_AAI_PASSWORD}
+ ${session}= Create Session aai ${GLOBAL_AAI_SERVER_URL} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Delete Request aai ${data_path}?resource-version=${resource_version} headers=${headers}
+ Log Received response from aai ${resp.text}
+ [Return] ${resp} \ No newline at end of file
diff --git a/robot/resources/aai/create_customer.robot b/robot/resources/aai/create_customer.robot
new file mode 100644
index 00000000..7ebda39d
--- /dev/null
+++ b/robot/resources/aai/create_customer.robot
@@ -0,0 +1,41 @@
+*** Settings ***
+Documentation Create A&AI Customer API.
+...
+... Create A&AI Customer API
+
+Resource aai_interface.robot
+Resource ../json_templater.robot
+Library Collections
+Library OperatingSystem
+
+
+*** Variables ***
+${INDEX PATH} /aai/v8
+${ROOT_CUSTOMER_PATH} /business/customers/customer/
+${SYSTEM USER} robot-ete
+${A&AI ADD CUSTOMER BODY} robot/assets/templates/aai/add_customer.template
+
+*** Keywords ***
+Create Customer
+ [Documentation] Creates a customer in A&AI
+ [Arguments] ${customer_name} ${customer_id} ${customer_type} ${service_type} ${clouder_owner} ${cloud_region_id} ${tenant_id}
+ ${data_template}= OperatingSystem.Get File ${A&AI ADD CUSTOMER BODY}
+ ${arguments}= Create Dictionary subscriber_name=${customer_name} global_customer_id=${customer_id} subscriber_type=${customer_type} cloud_owner1=${clouder_owner} cloud_region_id1=${cloud_region_id} tenant_id1=${tenant_id} service1=${service_type}
+ ${data}= Fill JSON Template ${data_template} ${arguments}
+ ${put_resp}= Run A&AI Put Request ${INDEX PATH}${ROOT_CUSTOMER_PATH}${customer_id} ${data}
+ Should Be Equal As Strings ${put_resp.status_code} 201
+ [Return] ${put_resp.status_code}
+
+*** Keywords ***
+Delete Customer
+ [Documentation] Deletes a customer in A&AI
+ [Arguments] ${customer_id}
+ ${get_resp}= Run A&AI Get Request ${INDEX PATH}${ROOT_CUSTOMER_PATH}${customer_id}
+ Run Keyword If '${get_resp.status_code}' == '200' Delete Customer Exists ${customer_id} ${get_resp.json()['resource-version']}
+
+*** Keywords ***
+Delete Customer Exists
+ [Documentation] Deletes a customer in A&AI
+ [Arguments] ${customer_id} ${resource_version_id}
+ ${put_resp}= Run A&AI Delete Request ${INDEX PATH}${ROOT_CUSTOMER_PATH}${customer_id} ${resource_version_id}
+ Should Be Equal As Strings ${put_resp.status_code} 204
diff --git a/robot/resources/aai/create_service.robot b/robot/resources/aai/create_service.robot
new file mode 100644
index 00000000..38aef3f6
--- /dev/null
+++ b/robot/resources/aai/create_service.robot
@@ -0,0 +1,75 @@
+*** Settings ***
+Documentation Create A&AI Customer API.
+...
+... Create A&AI Customer API
+
+Resource ../json_templater.robot
+Resource aai_interface.robot
+Library OperatingSystem
+Library Collections
+Library UUID
+
+
+
+*** Variables ***
+${INDEX PATH} /aai/v8
+${ROOT_SERVICE_PATH} /service-design-and-creation/services
+
+${SYSTEM USER} robot-ete
+${AAI_ADD_SERVICE_BODY}= robot/assets/templates/aai/add_service_body.template
+
+*** Keywords ***
+Create Service If Not Exists
+ [Documentation] Creates a service in A&AI if it doesn't exist
+ [Arguments] ${service_type}
+ ${dict}= Get Services
+ ${status} ${value}= Run Keyword And Ignore Error Dictionary Should Contain Key ${dict} ${service_type}
+ Run Keyword If '${status}' == 'FAIL' Create Service ${service_type}
+
+Create Service
+ [Documentation] Creates a service in A&AI
+ [Arguments] ${service_type}
+ ${uuid}= Generate UUID
+ ${data_template}= OperatingSystem.Get File ${AAI_ADD_SERVICE_BODY}
+ ${arguments}= Create Dictionary service_type=${service_type} UUID=${uuid}
+ ${data}= Fill JSON Template ${data_template} ${arguments}
+ ${fullpath}= Catenate ${INDEX PATH}${ROOT_SERVICE_PATH}/service/${uuid}
+ ${put_resp}= Run A&AI Put Request ${fullpath} ${data}
+ Should Be Equal As Strings ${put_resp.status_code} 201
+ [Return] ${put_resp.status_code}
+
+
+Delete Service If Exists
+ [Documentation] Deletes a service in A&AI if it exists
+ [Arguments] ${service_type}
+ ${dict}= Get Services
+ ${status} ${value}= Run Keyword And Ignore Error Dictionary Should Contain Key ${dict} ${service_type}
+ Run Keyword If '${status}' == 'PASS' Delete Service ${dict['${service_type}']}
+
+Delete Service
+ [Documentation] Delete passed service in A&AI
+ [Arguments] ${dict}
+ ${uuid}= Get From Dictionary ${dict} service-id
+ ${resource_version}= Get From Dictionary ${dict} resource-version
+ ${fullpath}= Catenate ${INDEX PATH}${ROOT_SERVICE_PATH}/service/${uuid}
+ ${resp}= Run A&AI Delete Request ${fullpath} ${resource_version}
+ Should Be Equal As Strings ${resp.status_code} 204
+
+
+Get Services
+ [Documentation] Creates a service in A&AI
+ ${resp}= Run A&AI Get Request ${INDEX PATH}${ROOT_SERVICE_PATH}
+ ${dict}= Create Dictionary
+ ${status} ${value}= Run Keyword And Ignore Error Should Be Equal As Strings ${resp.status_code} 200
+ Run Keyword If '${status}' == 'PASS' Update Service Dictionary ${dict} ${resp.json()}
+ [Return] ${dict}
+
+Update Service Dictionary
+ [Arguments] ${dict} ${json}
+ ${list}= Evaluate ${json}['service']
+ :for ${map} in @{list}
+ \ ${status} ${service_type}= Run Keyword And Ignore Error Get From Dictionary ${map} service-description
+ \ Run Keyword If '${status}' == 'PASS' Set To Dictionary ${dict} ${service_type}=${map}
+ Log ${dict}
+
+
diff --git a/robot/resources/aai/create_tenant.robot b/robot/resources/aai/create_tenant.robot
new file mode 100644
index 00000000..da21ac92
--- /dev/null
+++ b/robot/resources/aai/create_tenant.robot
@@ -0,0 +1,79 @@
+*** Settings ***
+Documentation Create A&AI Customer API.
+...
+... Create A&AI Customer API
+
+Resource ../json_templater.robot
+Resource aai_interface.robot
+Library OperatingSystem
+Library Collections
+
+
+
+*** Variables ***
+${INDEX PATH} /aai/v8
+${ROOT_TENANT_PATH} /cloud-infrastructure/cloud-regions/cloud-region/
+
+${SYSTEM USER} robot-ete
+${AAI_ADD_TENANT_BODY}= robot/assets/templates/aai/add_tenant_body.template
+
+*** Keywords ***
+Inventory Tenant If Not 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} ${tenant_id} ${tenant_name}
+ ${dict}= Get Tenants ${cloud_owner} ${cloud_region_id}
+ ${status} ${value}= Run Keyword And Ignore Error Dictionary Should Contain Key ${dict} ${tenant_id}
+ Run Keyword If '${status}' == 'FAIL' Inventory Tenant ${cloud_owner} ${cloud_region_id} ${cloud_type} ${owner_defined_type} ${cloud_region_version} ${cloud_zone} ${tenant_id} ${tenant_name}
+
+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}
+ ${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}
+ ${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}
+
+Delete Tenant
+ [Documentation] Removes both Tenant
+ [Arguments] ${tenant_id} ${cloud_owner} ${cloud_region_id}
+ ${get_resp}= Run A&AI Get Request ${INDEX PATH}${ROOT_TENANT_PATH}${cloud_owner}/${cloud_region_id}/tenants/tenant/${tenant_id}
+ Run Keyword If '${get_resp.status_code}' == '200' Delete Tenant Exists ${tenant_id} ${cloud_owner} ${cloud_region_id} ${get_resp.json()['resource-version']}
+
+Delete Tenant Exists
+ [Arguments] ${tenant_id} ${cloud_owner} ${cloud_region_id} ${resource_version}
+ ${put_resp}= Run A&AI Delete Request ${INDEX PATH}${ROOT_TENANT_PATH}${cloud_owner}/${cloud_region_id}/tenants/tenant/${tenant_id} ${resource_version}
+ Should Be Equal As Strings ${put_resp.status_code} 204
+
+Delete Cloud Region
+ [Documentation] Removes both Tenant and Cloud Region in A&AI
+ [Arguments] ${tenant_id} ${cloud_owner} ${cloud_region_id}
+ ${get_resp}= Run A&AI Get Request ${INDEX PATH}${ROOT_TENANT_PATH}${cloud_owner}/${cloud_region_id}
+ Run Keyword If '${get_resp.status_code}' == '200' Delete Cloud Region Exists ${tenant_id} ${cloud_owner} ${cloud_region_id} ${get_resp.json()['resource-version']}
+
+Delete Cloud Region Exists
+ [Arguments] ${tenant_id} ${cloud_owner} ${cloud_region_id} ${resource_version}
+ ${put_resp}= Run A&AI Delete Request ${INDEX PATH}${ROOT_TENANT_PATH}${cloud_owner}/${cloud_region_id} ${resource_version}
+ Should Be Equal As Strings ${put_resp.status_code} 204
+
+Get Tenants
+ [Documentation] Return list of tenants for this cloud owner/region
+ [Arguments] ${cloud_owner} ${cloud_region_id}
+ ${resp}= Run A&AI Get Request ${INDEX PATH}${ROOT_TENANT_PATH}${cloud_owner}/${cloud_region_id}/tenants
+ ${dict}= Create Dictionary
+ ${status} ${value}= Run Keyword And Ignore Error Should Be Equal As Strings ${resp.status_code} 200
+ Run Keyword If '${status}' == 'PASS' Update Tenant Dictionary ${dict} ${resp.json()}
+ [Return] ${dict}
+
+Update Tenant Dictionary
+ [Arguments] ${dict} ${json}
+ ${list}= Evaluate ${json}['tenant']
+ :for ${map} in @{list}
+ \ ${status} ${tenant_id}= Run Keyword And Ignore Error Get From Dictionary ${map} tenant-id
+ \ Run Keyword If '${status}' == 'PASS' Set To Dictionary ${dict} ${tenant_id}=${map}
+ Log ${dict}
+
+
+
+ \ No newline at end of file
diff --git a/robot/resources/aai/network.robot b/robot/resources/aai/network.robot
new file mode 100644
index 00000000..a42461e2
--- /dev/null
+++ b/robot/resources/aai/network.robot
@@ -0,0 +1,42 @@
+*** Settings ***
+Documentation Validate A&AI Serivce Instance
+...
+... Validate A&AI Serivce Instance
+
+Resource aai_interface.robot
+Library Collections
+Library OperatingSystem
+Library RequestsLibrary
+Library JSONUtils
+Library HttpLibrary.HTTP
+
+Resource ../json_templater.robot
+
+*** Variables ***
+${INDEX PATH} /aai/v8
+${GENERIC_QUERY_PATH} /search/generic-query?
+${SYSTEM USER} robot-ete
+${CUSTOMER SPEC PATH} /business/customers/customer/
+${SERVICE SUBSCRIPTIONS} /service-subscriptions/service-subscription/
+${SERVICE INSTANCE} /service-instances?service-instance-name=
+${SERVCE INSTANCE TEMPLATE} robot/assets/templates/aai/service_subscription.template
+
+*** Keywords ***
+Validate Network
+ [Documentation] Query and Validates A&AI Service Instance
+ [Arguments] ${service_instance_name} ${service_type} ${customer_id}
+ ${resp}= Run A&AI Get Request ${INDEX PATH}${CUSTOMER SPEC PATH}${CUSTOMER ID}${SERVICE SUBSCRIPTIONS}${service_type}${SERVICE INSTANCE}${service_instance_name}
+ Dictionary Should Contain Value ${resp.json()['service-instance'][0]} ${service_instance_name}
+
+
+
+*** Keywords ***
+Create Network
+ [Documentation] Query and Validates A&AI Service Instance
+ [Arguments] ${CUSTOMER ID}
+ ${json_string}= Catenate { "service-type": "VDNS" , "service-subscriptions":[{"service-instance-id":"instanceid123","service-instance-name":"VDNS"}]}
+ ${put_resp}= Run A&AI Put Request ${INDEX PATH}${CUSTOMER SPEC PATH}${CUSTOMER ID}${SERVICE SUBSCRIPTIONS}/VDNS ${json_string}
+ Should Be Equal As Strings ${put_resp.status_code} 201
+ [Return] ${put_resp.status_code}
+
+ \ No newline at end of file
diff --git a/robot/resources/aai/service_instance.robot b/robot/resources/aai/service_instance.robot
new file mode 100644
index 00000000..c9fdadd6
--- /dev/null
+++ b/robot/resources/aai/service_instance.robot
@@ -0,0 +1,82 @@
+*** Settings ***
+Documentation Validate A&AI Serivce Instance
+...
+... Validate A&AI Serivce Instance
+
+Resource aai_interface.robot
+Library Collections
+Library OperatingSystem
+Library RequestsLibrary
+Library JSONUtils
+Library HttpLibrary.HTTP
+Library StringTemplater
+Resource ../json_templater.robot
+Resource ../stack_validation/validate_vlb.robot
+Resource ../stack_validation/validate_vfw.robot
+Resource ../stack_validation/validate_vvg.robot
+
+*** Variables ***
+${INDEX PATH} /aai/v8
+${GENERIC_QUERY_PATH} /search/generic-query?
+${SYSTEM USER} robot-ete
+${CUSTOMER SPEC PATH} /business/customers/customer/
+${SERVICE SUBSCRIPTIONS} /service-subscriptions/service-subscription/
+${SERVICE INSTANCE} /service-instances?service-instance-id=
+${SERVCE INSTANCE TEMPLATE} robot/assets/templates/aai/service_subscription.template
+
+${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
+
+*** Keywords ***
+Validate Service Instance
+ [Documentation] Query and Validates A&AI Service Instance
+ [Arguments] ${service_instance_name} ${service_type} ${customer_name}
+ ${cust_resp}= Run A&AI Get Request ${INDEX PATH}/business/customers?subscriber-name=${customer_name}
+ ${resp}= Run A&AI Get Request ${INDEX PATH}${CUSTOMER SPEC PATH}${cust_resp.json()['customer'][0]['global-customer-id']}${SERVICE SUBSCRIPTIONS}${service_type}${SERVICE INSTANCE}${service_instance_name}
+ Dictionary Should Contain Value ${resp.json()['service-instance'][0]} ${service_instance_name}
+ Dictionary Should Contain Key ${resp.json()['service-instance'][0]} persona-model-id
+ Dictionary Should Contain Key ${resp.json()['service-instance'][0]} persona-model-version
+
+Validate Generic VNF
+ [Documentation] Query and Validates A&AI Service Instance
+ [Arguments] ${vnf_name} ${vnf_type} ${service_instance_id}
+ ${generic_vnf}= Run A&AI Get Request ${INDEX PATH}/network/generic-vnfs/generic-vnf?vnf-name=${vnf_name}
+ Dictionary Should Contain Value ${generic_vnf.json()} ${vnf_name}
+ ${returned_vnf_type}= Get From Dictionary ${generic_vnf.json()} vnf-type
+ Should Contain ${returned_vnf_type} ${vnf_type}
+ [Return] ${generic_vnf.json()}
+
+VLB Closed Loop Hack
+ [Arguments] ${service} ${generic_vnf} ${closedloop_vf_module}
+ Return From Keyword If '${service}' != 'vLB'
+ ${vnf_id}= Get From Dictionary ${generic_vnf} vnf-id
+ ${vf_modules}= Get From Dictionary ${generic_vnf} vf-modules
+ ${list}= Get From Dictionary ${vf_modules} vf-module
+ ${vfmodule}= Get From List ${list} 0
+ ${persona_model_id}= Get From Dictionary ${closedloop_vf_module} invariantUUID
+ ${persona_model_version}= Get From Dictionary ${closedloop_vf_module} version
+ ${dict}= Create Dictionary vnf_id=${vnf_id} vf_module_id=dummy persona_model_id=${persona_model_id} persona_model_version=${persona_model_version}
+ ${datapath}= Template String ${GENERIC_VNF_PATH_TEMPLATE} ${dict}
+ ${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)$
+
+
+Validate VF Module
+ [Documentation] Query and Validates A&AI Service Instance
+ [Arguments] ${vf_module_name} ${stack_type}
+ Run Keyword If '${stack_type}'=='vLB' Validate vLB Stack ${vf_module_name}
+ Run Keyword If '${stack_type}'=='vFW' Validate Firewall Stack ${vf_module_name}
+ Run Keyword If '${stack_type}'=='vVG' Validate vVG Stack ${vf_module_name}
+
+*** Keywords ***
+Create AAI Service Instance
+ [Documentation] Query and Validates A&AI Service Instance
+ [Arguments] ${customer_id} ${service_type} ${service_instance_id} ${service_instance_name}
+ ${json_string}= Catenate { "service-type": "VDNS" , "service-subscriptions":[{"service-instance-id":"instanceid123","service-instance-name":"VDNS"}]}
+ ${put_resp}= Run A&AI Put Request ${INDEX PATH}${CUSTOMER SPEC PATH}${CUSTOMER ID}${SERVICE SUBSCRIPTIONS}/{service_type} ${json_string}
+ Should Be Equal As Strings ${put_resp.status_code} 201
+ [Return] ${put_resp.status_code}
+
+ \ No newline at end of file
diff --git a/robot/resources/aai/volume_group.robot b/robot/resources/aai/volume_group.robot
new file mode 100644
index 00000000..95822011
--- /dev/null
+++ b/robot/resources/aai/volume_group.robot
@@ -0,0 +1,31 @@
+*** Settings ***
+Documentation Validate A&AI Serivce Instance
+...
+... Validate A&AI Serivce Instance
+
+Resource aai_interface.robot
+Library Collections
+Library OperatingSystem
+Library RequestsLibrary
+Library JSONUtils
+Library HttpLibrary.HTTP
+
+Resource ../json_templater.robot
+
+*** Variables ***
+${INDEX PATH} /aai/v8
+${GENERIC_QUERY_PATH} /search/generic-query?
+${SYSTEM USER} robot-ete
+${CUSTOMER SPEC PATH} /business/customers/customer/
+${SERVICE SUBSCRIPTIONS} /service-subscriptions/service-subscription/
+${SERVICE INSTANCE} /service-instances?service-instance-name=
+${SERVCE INSTANCE TEMPLATE} robot/assets/templates/aai/service_subscription.template
+
+*** Keywords ***
+Validate Volume Group
+ [Arguments] ${service_instance_name} ${service_type} ${customer_id}
+ ${resp}= Run A&AI Get Request ${INDEX PATH}${CUSTOMER SPEC PATH}${CUSTOMER ID}${SERVICE SUBSCRIPTIONS}${service_type}${SERVICE INSTANCE}${service_instance_name}
+ Dictionary Should Contain Value ${resp.json()['service-instance'][0]} ${service_instance_name}
+
+
+ \ No newline at end of file
diff --git a/robot/resources/appc_interface.robot b/robot/resources/appc_interface.robot
new file mode 100644
index 00000000..2dbd979b
--- /dev/null
+++ b/robot/resources/appc_interface.robot
@@ -0,0 +1,54 @@
+*** Settings ***
+Documentation The main interface for interacting with APP-C. It handles low level stuff like managing the http request library and APP-C required fields
+Library RequestsLibrary
+Library UUID
+Library OperatingSystem
+Library StringTemplater
+Resource global_properties.robot
+
+*** Variables ***
+${APPC_INDEX_PATH} /restconf
+${APPC_HEALTHCHECK_OPERATION_PATH} /operations/SLI-API:healthcheck
+${APPC_CREATE_MOUNTPOINT_PATH} /config/network-topology:network-topology/topology/topology-netconf/node/
+${APPC_MOUNT_XML} robot/assets/templates/appc/vnf_mount.template
+
+*** Keywords ***
+Run APPC Health Check
+ [Documentation] Runs an APPC healthcheck
+ ${resp}= Run APPC Post Request ${APPC_INDEX PATH}${APPC_HEALTHCHECK_OPERATION_PATH} ${None}
+ Should Be Equal As Strings ${resp.status_code} 200
+ Should Be Equal As Strings ${resp.json()['output']['response-code']} 200
+
+Run APPC Post Request
+ [Documentation] Runs an APPC post request
+ [Arguments] ${data_path} ${data} ${content}=json
+ ${auth}= Create List ${GLOBAL_APPC_USERNAME} ${GLOBAL_APPC_PASSWORD}
+ Log Creating session ${GLOBAL_APPC_SERVER}
+ ${session}= Create Session appc ${GLOBAL_APPC_SERVER} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/${content} Content-Type=application/${content} X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Post Request appc ${data_path} data=${data} headers=${headers}
+ Log Received response from appc ${resp.text}
+ [Return] ${resp}
+
+Run APPC Put Request
+ [Documentation] Runs an APPC post request
+ [Arguments] ${data_path} ${data} ${content}=xml
+ ${auth}= Create List ${GLOBAL_APPC_USERNAME} ${GLOBAL_APPC_PASSWORD}
+ Log Creating session ${GLOBAL_APPC_SERVER}
+ ${session}= Create Session appc ${GLOBAL_APPC_SERVER} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/${content} Content-Type=application/${content} X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Put Request appc ${data_path} data=${data} headers=${headers}
+ Log Received response from appc ${resp.text}
+ [Return] ${resp}
+
+Create Mount Point In APPC
+ [Documentation] Go tell APPC about the PGN we just spun up...
+ [Arguments] ${nodeid} ${host} ${port}=${GLOBAL_PGN_PORT} ${username}=admin ${password}=admin
+ ${dict}= Create Dictionary nodeid=${nodeid} host=${host} port=${port} username=${username} password=${password}
+ ${template}= OperatingSystem.Get File ${APPC_MOUNT_XML}
+ ${data}= Template String ${template} ${dict}
+ ${resp}= Run APPC Put Request ${APPC_INDEX PATH}${APPC_CREATE_MOUNTPOINT_PATH}${nodeid} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp} \ No newline at end of file
diff --git a/robot/resources/asdc_interface.robot b/robot/resources/asdc_interface.robot
new file mode 100644
index 00000000..35fdecf1
--- /dev/null
+++ b/robot/resources/asdc_interface.robot
@@ -0,0 +1,462 @@
+*** Settings ***
+Documentation The main interface for interacting with ASDC. It handles low level stuff like managing the http request library and DCAE required fields
+Library RequestsLibrary
+Library UUID
+Library JSONUtils
+Library OperatingSystem
+Library Collections
+Library ExtendedSelenium2Library
+Resource global_properties.robot
+Resource browser_setup.robot
+Resource json_templater.robot
+*** Variables ***
+${ASDC_DESIGNER_USER_ID} cs0008
+${ASDC_TESTER_USER_ID} jm0007
+${ASDC_GOVERNOR_USER_ID} gv0001
+${ASDC_OPS_USER_ID} op0001
+${ASDC_HEALTH_CHECK_PATH} /sdc1/rest/healthCheck
+${ASDC_VENDOR_LICENSE_MODEL_PATH} /onboarding-api/v1.0/vendor-license-models
+${ASDC_VENDOR_SOFTWARE_PRODUCT_PATH} /onboarding-api/v1.0/vendor-software-products
+${ASDC_VENDOR_KEY_GROUP_PATH} /license-key-groups
+${ASDC_VENDOR_ENTITLEMENT_POOL_PATH} /entitlement-pools
+${ASDC_VENDOR_FEATURE_GROUP_PATH} /feature-groups
+${ASDC_VENDOR_LICENSE_AGREEMENT_PATH} /license-agreements
+${ASDC_VENDOR_ACTIONS_PATH} /actions
+${ASDC_VENDOR_SOFTWARE_UPLOAD_PATH} /upload
+${ASDC_CATALOG_RESOURCES_PATH} /sdc2/rest/v1/catalog/resources
+${ASDC_CATALOG_SERVICES_PATH} /sdc2/rest/v1/catalog/services
+${ASDC_CATALOG_INACTIVE_RESOURCES_PATH} /sdc2/rest/v1/inactiveComponents/resource
+${ASDC_CATALOG_INACTIVE_SERVICES_PATH} /sdc2/rest/v1/inactiveComponents/service
+${ASDC_CATALOG_LIFECYCLE_PATH} /lifecycleState
+${ASDC_CATALOG_SERVICE_RESOURCE_INSTANCE_PATH} /resourceInstance
+${ASDC_CATALOG_SERVICE_DISTRIBUTION_STATE_PATH} /distribution-state
+${ASDC_CATALOG_SERVICE_DISTRIBUTION_PATH} /distribution
+${ASDC_DISTRIBUTION_STATE_APPROVE_PATH} /approve
+${ASDC_CATALOG_SERVICE_DISTRIBUTION_ACTIVATE_PATH} /distribution/PROD/activate
+${ASDC_LICENSE_MODEL_TEMPLATE} robot/assets/templates/asdc/license_model.template
+${ASDC_KEY_GROUP_TEMPLATE} robot/assets/templates/asdc/key_group.template
+${ASDC_ENTITLEMENT_POOL_TEMPLATE} robot/assets/templates/asdc/entitlement_pool.template
+${ASDC_FEATURE_GROUP_TEMPLATE} robot/assets/templates/asdc/feature_group.template
+${ASDC_LICENSE_AGREEMENT_TEMPLATE} robot/assets/templates/asdc/license_agreement.template
+${ASDC_ACTION_TEMPLATE} robot/assets/templates/asdc/action.template
+${ASDC_SOFTWARE_PRODUCT_TEMPLATE} robot/assets/templates/asdc/software_product.template
+${ASDC_CATALOG_RESOURCE_TEMPLATE} robot/assets/templates/asdc/catalog_resource.template
+${ASDC_USER_REMARKS_TEMPLATE} robot/assets/templates/asdc/user_remarks.template
+${ASDC_CATALOG_SERVICE_TEMPLATE} robot/assets/templates/asdc/catalog_service.template
+${ASDC_RESOURCE_INSTANCE_TEMPLATE} robot/assets/templates/asdc/resource_instance.template
+*** 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
+ ${catalog_resource_ids}= Create List
+ : FOR ${zip} IN @{model_zip_path}
+ \ ${loop_catalog_resource_id}= Setup ASDC Catalog Resource ${zip}
+ \ Append To List ${catalog_resource_ids} ${loop_catalog_resource_id}
+ \ ${loop_catalog_resource_resp}= Get ASDC Catalog Resource ${loop_catalog_resource_id}
+ \ Add ASDC Resource Instance ${catalog_service_id} ${loop_catalog_resource_id} ${loop_catalog_resource_resp['name']}
+ ${catalog_service_resp}= Get ASDC Catalog Service ${catalog_service_id}
+ Checkin ASDC Catalog Service ${catalog_service_id}
+ Request Certify ASDC Catalog Service ${catalog_service_id}
+ Start Certify ASDC Catalog Service ${catalog_service_id}
+ # on certify it gets a new id
+ ${catalog_service_id}= Certify ASDC Catalog Service ${catalog_service_id}
+ Approve ASDC Catalog Service ${catalog_service_id}
+ Distribute ASDC Catalog Service ${catalog_service_id}
+ ${catalog_service_resp}= Get ASDC Catalog Service ${catalog_service_id}
+ ${vf_module}= Find Element In Array ${loop_catalog_resource_resp['groups']} type org.openecomp.groups.VfModule
+ [Return] ${catalog_service_resp['name']} ${loop_catalog_resource_resp['name']} ${vf_module} ${catalog_resource_ids} ${catalog_service_id}
+ Check Catalog Service Distributed ${catalog_service_resp['uuid']}
+Setup ASDC Catalog Resource
+ [Documentation] Creates all the steps a vf needs for an asdc catalog resource and returns the id
+ [Arguments] ${model_zip_path}
+ ${license_model_id}= Add ASDC License Model
+ ${key_group_id}= Add ASDC License Group ${license_model_id}
+ ${pool_id}= Add ASDC Entitlement Pool ${license_model_id}
+ ${feature_group_id}= Add ASDC Feature Group ${license_model_id} ${key_group_id} ${pool_id}
+ ${license_agreement_id}= Add ASDC License Agreement ${license_model_id} ${feature_group_id}
+ Checkin ASDC License Model ${license_model_id}
+ Submit ASDC License Model ${license_model_id}
+ ${license_model_resp}= Get ASDC License Model ${license_model_id}
+ ${software_product_id}= Add ASDC Software Product ${license_agreement_id} ${feature_group_id} ${license_model_resp['vendorName']} ${license_model_id}
+ Upload ASDC Heat Package ${software_product_id} ${model_zip_path}
+ Checkin ASDC Software Product ${software_product_id}
+ Submit ASDC Software Product ${software_product_id}
+ Package ASDC Software Product ${software_product_id}
+ ${software_product_resp}= Get ASDC Software Product ${software_product_id}
+ ${catalog_resource_id}= Add ASDC Catalog Resource ${license_agreement_id} ${software_product_resp['name']} ${license_model_resp['vendorName']} ${software_product_id}
+ Checkin ASDC Catalog Resource ${catalog_resource_id}
+ Request Certify ASDC Catalog Resource ${catalog_resource_id}
+ Start Certify ASDC Catalog Resource ${catalog_resource_id}
+ # on certify it gets a new id
+ [Return] ${catalog_resource_id}
+ ${catalog_resource_id}= Certify ASDC Catalog Resource ${catalog_resource_id}
+Add ASDC License Model
+ [Documentation] Creates an asdc license model and returns its id
+ ${uuid}= Generate UUID
+ ${shortened_uuid}= Evaluate str("${uuid}")[:23]
+ ${map}= Create Dictionary vendor_name=${shortened_uuid}
+ ${data}= Fill JSON Template File ${ASDC_LICENSE_MODEL_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_VENDOR_LICENSE_MODEL_PATH} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()['value']}
+Get ASDC License Model
+ [Documentation] gets an asdc license model by its id
+ [Arguments] ${id}
+ ${resp}= Run ASDC Get Request ${ASDC_VENDOR_LICENSE_MODEL_PATH}/${id}
+ [Return] ${resp.json()}
+Checkin ASDC License Model
+ [Documentation] checksin an asdc license model by its id
+ [Arguments] ${id}
+ ${map}= Create Dictionary action=Checkin
+ ${data}= Fill JSON Template File ${ASDC_ACTION_TEMPLATE} ${map}
+ ${resp}= Run ASDC Put Request ${ASDC_VENDOR_LICENSE_MODEL_PATH}/${id}${ASDC_VENDOR_ACTIONS_PATH} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Submit ASDC License Model
+ [Documentation] submits an asdc license model by its id
+ [Arguments] ${id}
+ ${map}= Create Dictionary action=Submit
+ ${data}= Fill JSON Template File ${ASDC_ACTION_TEMPLATE} ${map}
+ ${resp}= Run ASDC Put Request ${ASDC_VENDOR_LICENSE_MODEL_PATH}/${id}${ASDC_VENDOR_ACTIONS_PATH} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Checkin ASDC Software Product
+ [Documentation] checksin an asdc Software Product by its id
+ [Arguments] ${id}
+ ${map}= Create Dictionary action=Checkin
+ ${data}= Fill JSON Template File ${ASDC_ACTION_TEMPLATE} ${map}
+ ${resp}= Run ASDC Put Request ${ASDC_VENDOR_SOFTWARE_PRODUCT_PATH}/${id}${ASDC_VENDOR_ACTIONS_PATH} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Submit ASDC Software Product
+ [Documentation] submits an asdc Software Product by its id
+ [Arguments] ${id}
+ ${map}= Create Dictionary action=Submit
+ ${data}= Fill JSON Template File ${ASDC_ACTION_TEMPLATE} ${map}
+ ${resp}= Run ASDC Put Request ${ASDC_VENDOR_SOFTWARE_PRODUCT_PATH}/${id}${ASDC_VENDOR_ACTIONS_PATH} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Package ASDC Software Product
+ [Documentation] creates_package on an asdc Software Product by its id
+ [Arguments] ${id}
+ ${map}= Create Dictionary action=Create_Package
+ ${data}= Fill JSON Template File ${ASDC_ACTION_TEMPLATE} ${map}
+ ${resp}= Run ASDC Put Request ${ASDC_VENDOR_SOFTWARE_PRODUCT_PATH}/${id}${ASDC_VENDOR_ACTIONS_PATH} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Add ASDC Entitlement Pool
+ [Documentation] Creates an asdc Entitlement Pool and returns its id
+ [Arguments] ${license_model_id}
+ ${uuid}= Generate UUID
+ ${shortened_uuid}= Evaluate str("${uuid}")[:23]
+ ${map}= Create Dictionary entitlement_pool_name=${shortened_uuid}
+ ${data}= Fill JSON Template File ${ASDC_ENTITLEMENT_POOL_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_VENDOR_LICENSE_MODEL_PATH}/${license_model_id}${ASDC_VENDOR_ENTITLEMENT_POOL_PATH} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()['value']}
+Get ASDC Entitlement Pool
+ [Documentation] gets an asdc Entitlement Pool by its id
+ [Arguments] ${license_model_id} ${pool_id}
+ ${resp}= Run ASDC Get Request ${ASDC_VENDOR_LICENSE_MODEL_PATH}/${license_model_id}${ASDC_VENDOR_ENTITLEMENT_POOL_PATH}/${pool_id}
+ [Return] ${resp.json()}
+Add ASDC License Group
+ [Documentation] Creates an asdc license group and returns its id
+ [Arguments] ${license_model_id}
+ ${uuid}= Generate UUID
+ ${shortened_uuid}= Evaluate str("${uuid}")[:23]
+ ${map}= Create Dictionary key_group_name=${shortened_uuid}
+ ${data}= Fill JSON Template File ${ASDC_KEY_GROUP_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_VENDOR_LICENSE_MODEL_PATH}/${license_model_id}${ASDC_VENDOR_KEY_GROUP_PATH} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()['value']}
+Get ASDC License Group
+ [Documentation] gets an asdc license group by its id
+ [Arguments] ${license_model_id} ${group_id}
+ ${resp}= Run ASDC Get Request ${ASDC_VENDOR_LICENSE_MODEL_PATH}/${license_model_id}${ASDC_VENDOR_KEY_GROUP_PATH}/${group_id}
+ [Return] ${resp.json()}
+Add ASDC Feature Group
+ [Documentation] Creates an asdc Feature Group and returns its id
+ [Arguments] ${license_model_id} ${key_group_id} ${entitlement_pool_id}
+ ${uuid}= Generate UUID
+ ${shortened_uuid}= Evaluate str("${uuid}")[:23]
+ ${map}= Create Dictionary feature_group_name=${shortened_uuid} key_group_id=${key_group_id} entitlement_pool_id=${entitlement_pool_id}
+ ${data}= Fill JSON Template File ${ASDC_FEATURE_GROUP_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_VENDOR_LICENSE_MODEL_PATH}/${license_model_id}${ASDC_VENDOR_FEATURE_GROUP_PATH} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()['value']}
+Get ASDC Feature Group
+ [Documentation] gets an asdc Feature Group by its id
+ [Arguments] ${license_model_id} ${group_id}
+ ${resp}= Run ASDC Get Request ${ASDC_VENDOR_LICENSE_MODEL_PATH}/${license_model_id}${ASDC_VENDOR_FEATURE_GROUP_PATH}/${group_id}
+ [Return] ${resp.json()}
+Add ASDC License Agreement
+ [Documentation] Creates an asdc License Agreement and returns its id
+ [Arguments] ${license_model_id} ${feature_group_id}
+ ${uuid}= Generate UUID
+ ${shortened_uuid}= Evaluate str("${uuid}")[:23]
+ ${map}= Create Dictionary license_agreement_name=${shortened_uuid} feature_group_id=${feature_group_id}
+ ${data}= Fill JSON Template File ${ASDC_LICENSE_AGREEMENT_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_VENDOR_LICENSE_MODEL_PATH}/${license_model_id}${ASDC_VENDOR_LICENSE_AGREEMENT_PATH} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()['value']}
+Get ASDC License Agreement
+ [Documentation] gets an asdc License Agreement by its id
+ [Arguments] ${license_model_id} ${agreement_id}
+ ${resp}= Run ASDC Get Request ${ASDC_VENDOR_LICENSE_MODEL_PATH}/${license_model_id}${ASDC_VENDOR_LICENSE_AGREEMENT_PATH}/${agreement_id}
+ [Return] ${resp.json()}
+Add ASDC Software Product
+ [Documentation] Creates an asdc Software Product and returns its id
+ [Arguments] ${license_agreement_id} ${feature_group_id} ${license_model_name} ${license_model_id}
+ ${uuid}= Generate UUID
+ ${shortened_uuid}= Evaluate str("${uuid}")[:23]
+ ${map}= Create Dictionary software_product_name=${shortened_uuid} feature_group_id=${feature_group_id} license_agreement_id=${license_agreement_id} vendor_name=${license_model_name} vendor_id=${license_model_id}
+ ${data}= Fill JSON Template File ${ASDC_SOFTWARE_PRODUCT_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_VENDOR_SOFTWARE_PRODUCT_PATH} ${data}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()['vspId']}
+Get ASDC Software Product
+ [Documentation] gets an asdc Software Product by its id
+ [Arguments] ${software_product_id}
+ ${resp}= Run ASDC Get Request ${ASDC_VENDOR_SOFTWARE_PRODUCT_PATH}/${software_product_id}
+ [Return] ${resp.json()}
+Add ASDC Catalog Resource
+ [Documentation] Creates an asdc Catalog Resource and returns its id
+ [Arguments] ${license_agreement_id} ${software_product_name} ${license_model_name} ${software_product_id}
+ ${map}= Create Dictionary software_product_id=${software_product_id} software_product_name=${software_product_name} license_agreement_id=${license_agreement_id} vendor_name=${license_model_name}
+ ${data}= Fill JSON Template File ${ASDC_CATALOG_RESOURCE_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_RESOURCES_PATH} ${data} ${ASDC_DESIGNER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 201
+ [Return] ${resp.json()['uniqueId']}
+Mark ASDC Catalog Resource Inactive
+ [Documentation] deletes an asdc Catalog Resource
+ [Arguments] ${catalog_resource_id}
+ ${resp}= Run ASDC Delete Request ${ASDC_CATALOG_RESOURCES_PATH}/${catalog_resource_id} ${ASDC_DESIGNER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 204
+ [Return] ${resp}
+Delete Inactive ASDC Catalog Resources
+ [Documentation] delete all asdc Catalog Resources that are inactive
+ ${resp}= Run ASDC Delete Request ${ASDC_CATALOG_INACTIVE_RESOURCES_PATH} ${ASDC_DESIGNER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Get ASDC Catalog Resource
+ [Documentation] gets an asdc Catalog Resource by its id
+ [Arguments] ${catalog_resource_id}
+ ${resp}= Run ASDC Get Request ${ASDC_CATALOG_RESOURCES_PATH}/${catalog_resource_id} ${ASDC_DESIGNER_USER_ID}
+ [Return] ${resp.json()}
+Checkin ASDC Catalog Resource
+ [Documentation] checksin an asdc Catalog Resource by its id
+ [Arguments] ${catalog_resource_id}
+ ${map}= Create Dictionary user_remarks=Robot remarks
+ ${data}= Fill JSON Template File ${ASDC_USER_REMARKS_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_RESOURCES_PATH}/${catalog_resource_id}${ASDC_CATALOG_LIFECYCLE_PATH}/checkin ${data} ${ASDC_DESIGNER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Request Certify ASDC Catalog Resource
+ [Documentation] requests certify on an asdc Catalog Resource by its id
+ [Arguments] ${catalog_resource_id}
+ ${map}= Create Dictionary user_remarks=Robot remarks
+ ${data}= Fill JSON Template File ${ASDC_USER_REMARKS_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_RESOURCES_PATH}/${catalog_resource_id}${ASDC_CATALOG_LIFECYCLE_PATH}/certificationRequest ${data} ${ASDC_DESIGNER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Start Certify ASDC Catalog Resource
+ [Documentation] start certify an asdc Catalog Resource by its id
+ [Arguments] ${catalog_resource_id}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_RESOURCES_PATH}/${catalog_resource_id}${ASDC_CATALOG_LIFECYCLE_PATH}/startCertification ${None} ${ASDC_TESTER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Certify ASDC Catalog Resource
+ [Documentation] start certify an asdc Catalog Resource by its id and returns the new id
+ [Arguments] ${catalog_resource_id}
+ ${map}= Create Dictionary user_remarks=Robot remarks
+ ${data}= Fill JSON Template File ${ASDC_USER_REMARKS_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_RESOURCES_PATH}/${catalog_resource_id}${ASDC_CATALOG_LIFECYCLE_PATH}/certify ${data} ${ASDC_TESTER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()['uniqueId']}
+Upload ASDC Heat Package
+ [Documentation] Creates an asdc Software Product and returns its id
+ [Arguments] ${software_product_id} ${file_path}
+ ${file}= Get Binary File ${file_path}
+ ${files}= Create Dictionary upload=${file}
+ ${resp}= Run ASDC Post Files Request ${ASDC_VENDOR_SOFTWARE_PRODUCT_PATH}/${software_product_id}${ASDC_VENDOR_SOFTWARE_UPLOAD_PATH} ${files} ${ASDC_DESIGNER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+Add ASDC Catalog Service
+ [Documentation] Creates an asdc Catalog Service and returns its id
+ ${uuid}= Generate UUID
+ ${shortened_uuid}= Evaluate str("${uuid}")[:23]
+ ${map}= Create Dictionary service_name=${shortened_uuid}
+ ${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
+ [Return] ${resp.json()['uniqueId']}
+Mark ASDC Catalog Service Inactive
+ [Documentation] Deletes an asdc Catalog Service
+ [Arguments] ${catalog_service_id}
+ ${resp}= Run ASDC Delete Request ${ASDC_CATALOG_SERVICES_PATH}/${catalog_service_id} ${ASDC_DESIGNER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 204
+ [Return] ${resp}
+Delete Inactive ASDC Catalog Services
+ [Documentation] delete all asdc Catalog Serivces that are inactive
+ ${resp}= Run ASDC Delete Request ${ASDC_CATALOG_INACTIVE_SERVICES_PATH} ${ASDC_DESIGNER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Get ASDC Catalog Service
+ [Documentation] gets an asdc Catalog Service by its id
+ [Arguments] ${catalog_service_id}
+ ${resp}= Run ASDC Get Request ${ASDC_CATALOG_SERVICES_PATH}/${catalog_service_id} ${ASDC_DESIGNER_USER_ID}
+ [Return] ${resp.json()}
+Checkin ASDC Catalog Service
+ [Documentation] checksin an asdc Catalog Service by its id
+ [Arguments] ${catalog_service_id}
+ ${map}= Create Dictionary user_remarks=Robot remarks
+ ${data}= Fill JSON Template File ${ASDC_USER_REMARKS_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_SERVICES_PATH}/${catalog_service_id}${ASDC_CATALOG_LIFECYCLE_PATH}/checkin ${data} ${ASDC_DESIGNER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Request Certify ASDC Catalog Service
+ [Documentation] requests certify on an asdc Catalog Service by its id
+ [Arguments] ${catalog_service_id}
+ ${map}= Create Dictionary user_remarks=Robot remarks
+ ${data}= Fill JSON Template File ${ASDC_USER_REMARKS_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_SERVICES_PATH}/${catalog_service_id}${ASDC_CATALOG_LIFECYCLE_PATH}/certificationRequest ${data} ${ASDC_DESIGNER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Start Certify ASDC Catalog Service
+ [Documentation] start certify an asdc Catalog Service by its id
+ [Arguments] ${catalog_service_id}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_SERVICES_PATH}/${catalog_service_id}${ASDC_CATALOG_LIFECYCLE_PATH}/startCertification ${None} ${ASDC_TESTER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Certify ASDC Catalog Service
+ [Documentation] start certify an asdc Catalog Service by its id and returns the new id
+ [Arguments] ${catalog_service_id}
+ ${map}= Create Dictionary user_remarks=Robot remarks
+ ${data}= Fill JSON Template File ${ASDC_USER_REMARKS_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_SERVICES_PATH}/${catalog_service_id}${ASDC_CATALOG_LIFECYCLE_PATH}/certify ${data} ${ASDC_TESTER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()['uniqueId']}
+Approve ASDC Catalog Service
+ [Documentation] approve an asdc Catalog Service by its id
+ [Arguments] ${catalog_service_id}
+ ${map}= Create Dictionary user_remarks=Robot remarks
+ ${data}= Fill JSON Template File ${ASDC_USER_REMARKS_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_SERVICES_PATH}/${catalog_service_id}${ASDC_CATALOG_SERVICE_DISTRIBUTION_STATE_PATH}${ASDC_DISTRIBUTION_STATE_APPROVE_PATH} ${data} ${ASDC_GOVERNOR_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Distribute ASDC Catalog Service
+ [Documentation] distribute an asdc Catalog Service by its id
+ [Arguments] ${catalog_service_id}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_SERVICES_PATH}/${catalog_service_id}${ASDC_CATALOG_SERVICE_DISTRIBUTION_ACTIVATE_PATH} ${None} ${ASDC_OPS_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Add ASDC Resource Instance
+ [Documentation] Creates an asdc Resource Instance and returns its id
+ [Arguments] ${catalog_service_id} ${catalog_resource_id} ${catalog_resource_name}
+ ${milli_timestamp}= Generate MilliTimestamp UUID
+ ${map}= Create Dictionary catalog_resource_id=${catalog_resource_id} catalog_resource_name=${catalog_resource_name} milli_timestamp=${milli_timestamp}
+ ${data}= Fill JSON Template File ${ASDC_RESOURCE_INSTANCE_TEMPLATE} ${map}
+ ${resp}= Run ASDC Post Request ${ASDC_CATALOG_SERVICES_PATH}/${catalog_service_id}${ASDC_CATALOG_SERVICE_RESOURCE_INSTANCE_PATH} ${data} ${ASDC_DESIGNER_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 201
+ [Return] ${resp.json()['uniqueId']}
+Get Catalog Service Distribution
+ [Documentation] gets an asdc catalog Service distrbution
+ [Arguments] ${catalog_service_uuid}
+ ${resp}= Run ASDC Get Request ${ASDC_CATALOG_SERVICES_PATH}/${catalog_service_uuid}${ASDC_CATALOG_SERVICE_DISTRIBUTION_PATH} ${ASDC_OPS_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Check Catalog Service Distributed
+ [Documentation] gets an asdc catalog Service distrbution
+ [Arguments] ${catalog_service_uuid}
+ ${dist_resp}= Get Catalog Service Distribution ${catalog_service_uuid}
+ Should Be Equal As Strings ${dist_resp['distributionStatusOfServiceList'][0]['deployementStatus']} Distributed
+ ${det_resp}= Get Catalog Service Distribution Details ${dist_resp['distributionStatusOfServiceList'][0]['distributionID']}
+ @{ITEMS}= Copy List ${det_resp['distributionStatusList']}
+ :FOR ${ELEMENT} IN @{ITEMS}
+ \ Log ${ELEMENT['status']}
+ \ Should Match Regexp ${ELEMENT['status']} ^(DEPLOY_OK|NOTIFIED|DOWNLOAD_OK|NOT_NOTIFIED)$
+Get Catalog Service Distribution Details
+ [Documentation] gets an asdc catalog Service distrbution details
+ [Arguments] ${catalog_service_distribution_id}
+ ${resp}= Run ASDC Get Request ${ASDC_CATALOG_SERVICES_PATH}${ASDC_CATALOG_SERVICE_DISTRIBUTION_PATH}/${catalog_service_distribution_id} ${ASDC_OPS_USER_ID}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+Run ASDC Health Check
+ [Documentation] Runs a ASDC health check
+ ${session}= Create Session asdc ${GLOBAL_ASDC_SERVER}:${GLOBAL_ASDC_FE_PORT}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Get Request asdc ${ASDC_HEALTH_CHECK_PATH} headers=${headers}
+ Should Be Equal As Strings ${resp.status_code} 200
+ @{ITEMS}= Copy List ${resp.json()['componentsInfo']}
+ :FOR ${ELEMENT} IN @{ITEMS}
+ \ Log ${ELEMENT['healthCheckStatus']}
+ \ Should Be Equal As Strings ${ELEMENT['healthCheckStatus']} UP
+Run ASDC Get Request
+ [Documentation] Runs an ASDC get request
+ [Arguments] ${data_path} ${user}=${ASDC_DESIGNER_USER_ID}
+ ${auth}= Create List ${GLOBAL_ASDC_BE_USERNAME} ${GLOBAL_ASDC_BE_PASSWORD}
+ Log Creating session ${GLOBAL_ASDC_SERVER}
+ ${session}= Create Session asdc ${GLOBAL_ASDC_SERVER}:${GLOBAL_ASDC_BE_PORT} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json USER_ID=${user} X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Get Request asdc ${data_path} headers=${headers}
+ Log Received response from asdc ${resp.text}
+ [Return] ${resp}
+Run ASDC Put Request
+ [Documentation] Runs an ASDC put request
+ [Arguments] ${data_path} ${data} ${user}=${ASDC_DESIGNER_USER_ID}
+ ${auth}= Create List ${GLOBAL_ASDC_BE_USERNAME} ${GLOBAL_ASDC_BE_PASSWORD}
+ Log Creating session ${GLOBAL_ASDC_SERVER}
+ ${session}= Create Session asdc ${GLOBAL_ASDC_SERVER}:${GLOBAL_ASDC_BE_PORT} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json USER_ID=${user} X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Put Request asdc ${data_path} data=${data} headers=${headers}
+ Log Received response from asdc ${resp.text}
+ [Return] ${resp}
+Run ASDC Post Files Request
+ [Documentation] Runs an ASDC post request
+ [Arguments] ${data_path} ${files} ${user}=${ASDC_DESIGNER_USER_ID}
+ ${auth}= Create List ${GLOBAL_ASDC_BE_USERNAME} ${GLOBAL_ASDC_BE_PASSWORD}
+ Log Creating session ${GLOBAL_ASDC_SERVER}
+ ${session}= Create Session asdc ${GLOBAL_ASDC_SERVER}:${GLOBAL_ASDC_BE_PORT} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=multipart/form-data USER_ID=${user} X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Post Request asdc ${data_path} files=${files} headers=${headers}
+ Log Received response from asdc ${resp.text}
+ [Return] ${resp}
+Run ASDC Post Request
+ [Documentation] Runs an ASDC post request
+ [Arguments] ${data_path} ${data} ${user}=${ASDC_DESIGNER_USER_ID}
+ ${auth}= Create List ${GLOBAL_ASDC_BE_USERNAME} ${GLOBAL_ASDC_BE_PASSWORD}
+ Log Creating session ${GLOBAL_ASDC_SERVER}
+ ${session}= Create Session asdc ${GLOBAL_ASDC_SERVER}:${GLOBAL_ASDC_BE_PORT} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json USER_ID=${user} X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Post Request asdc ${data_path} data=${data} headers=${headers}
+ Log Received response from asdc ${resp.text}
+ [Return] ${resp}
+Run ASDC Delete Request
+ [Documentation] Runs an ASDC delete request
+ [Arguments] ${data_path} ${user}=${ASDC_DESIGNER_USER_ID}
+ ${auth}= Create List ${GLOBAL_ASDC_BE_USERNAME} ${GLOBAL_ASDC_BE_PASSWORD}
+ Log Creating session ${GLOBAL_ASDC_SERVER}
+ ${session}= Create Session asdc ${GLOBAL_ASDC_SERVER}:${GLOBAL_ASDC_BE_PORT} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json USER_ID=${user} X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Delete Request asdc ${data_path} headers=${headers}
+ Log Received response from asdc ${resp.text}
+ [Return] ${resp}
+Open ASDC GUI
+ [Documentation] Logs in to ASDC GUI
+ [Arguments] ${PATH}
+ ## Setup Browever now being managed by the test case
+ ##Setup Browser
+ Go To ${GLOBAL_ASDC_SERVER}${PATH}
+ Maximize Browser Window
+ Set Selenium Speed ${GLOBAL_SELENIUM_DELAY}
+ Set Browser Implicit Wait ${GLOBAL_SELENIUM_BROWSER_IMPLICIT_WAIT}
+ Log Logging in to ${GLOBAL_ASDC_SERVER}${PATH}
+ Title Should Be ASDC
+ Wait Until Page Contains Element xpath=//div/a[text()='SDC'] ${GLOBAL_SELENIUM_BROWSER_WAIT_TIMEOUT}
+ Log Logged in to ${GLOBAL_PORTAL_SERVER}${PATH}
diff --git a/robot/resources/browser_setup.robot b/robot/resources/browser_setup.robot
new file mode 100644
index 00000000..6ef4f726
--- /dev/null
+++ b/robot/resources/browser_setup.robot
@@ -0,0 +1,43 @@
+*** Settings ***
+Documentation The main interface for interacting with VID. It handles low level stuff like managing the selenium request library and VID required steps
+Library Collections
+Library OSUtils
+Library OperatingSystem
+Library ExtendedSelenium2Library
+Resource global_properties.robot
+
+*** Variables ***
+
+*** Keywords ***
+Setup Browser
+ [Documentation] Sets up browser based upon the value of ${GLOBAL_SELENIUM_BROWSER}
+ Run Keyword If '${GLOBAL_SELENIUM_BROWSER}' == 'firefox' Setup Browser Firefox
+ Run Keyword If '${GLOBAL_SELENIUM_BROWSER}' == 'chrome' Setup Browser Chrome
+ Log Running with ${GLOBAL_SELENIUM_BROWSER}
+
+Setup Browser Firefox
+ ${dc} Evaluate sys.modules['selenium.webdriver'].DesiredCapabilities.FIREFOX sys, selenium.webdriver
+ Set To Dictionary ${dc} elementScrollBehavior 1
+ Create Webdriver Firefox desired_capabilities=${dc}
+ Set Global Variable ${GLOBAL_SELENIUM_BROWSER_CAPABILITIES} ${dc}
+
+ Setup Browser Chrome
+ ${os}= Get Normalized Os
+ Log Normalized OS=${os}
+ ${chrome options}= Evaluate sys.modules['selenium.webdriver'].ChromeOptions() sys
+ Call Method ${chrome options} add_argument no-sandbox
+ ${dc} Evaluate sys.modules['selenium.webdriver'].DesiredCapabilities.CHROME sys, selenium.webdriver
+ Set To Dictionary ${dc} elementScrollBehavior 1
+ Create Webdriver Chrome chrome_options=${chrome_options} desired_capabilities=${dc}
+ Set Global Variable ${GLOBAL_SELENIUM_BROWSER_CAPABILITIES} ${dc}
+
+Handle Proxy Warning
+ [Documentation] Handle Intermediate Warnings from Proxies
+ ${status} ${data}= Run Keyword And Ignore Error Variable Should Exist \${GLOBAL_PROXY_WARNING_TITLE}
+ Return From Keyword if '${status}' != 'PASS'
+ ${status} ${data}= Run Keyword And Ignore Error Variable Should Exist \${GLOBAL_PROXY_WARNING_CONTINUE_XPATH}
+ Return From Keyword if '${status}' != 'PASS'
+ Return From Keyword if "${GLOBAL_PROXY_WARNING_TITLE}" == ''
+ Return From Keyword if "${GLOBAL_PROXY_WARNING_CONTINUE_XPATH}" == ''
+ ${test} ${value}= Run keyword and ignore error Title Should Be ${GLOBAL_PROXY_WARNING_TITLE}
+ Run keyword If '${test}' == 'PASS' Click Element xpath=${GLOBAL_PROXY_WARNING_CONTINUE_XPATH} \ No newline at end of file
diff --git a/robot/resources/dcae_interface.robot b/robot/resources/dcae_interface.robot
new file mode 100644
index 00000000..1c1ba44a
--- /dev/null
+++ b/robot/resources/dcae_interface.robot
@@ -0,0 +1,57 @@
+*** Settings ***
+Documentation The main interface for interacting with DCAE. It handles low level stuff like managing the http request library and DCAE required fields
+Library RequestsLibrary
+Library UUID
+Library OperatingSystem
+Library Collections
+Resource global_properties.robot
+
+*** Variables ***
+${DCAE_HEALTH_CHECK_BODY} robot/assets/dcae/dcae_healthcheck.json
+${DCAE_HEALTH_CHECK_PATH} /gui
+
+*** Keywords ***
+Run DCAE Health Check
+ [Documentation] Runs a DCAE health check
+ ${auth}= Create List ${GLOBAL_DCAE_USERNAME} ${GLOBAL_DCAE_PASSWORD}
+ Log Creating session ${GLOBAL_DCAE_SERVER}
+ ${session}= Create Session dcae ${GLOBAL_DCAE_SERVER} auth=${auth}
+ ${uuid}= Generate UUID
+ ${data}= OperatingSystem.Get File ${DCAE_HEALTH_CHECK_BODY}
+ ${headers}= Create Dictionary action=getTable Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Put Request dcae ${DCAE_HEALTH_CHECK_PATH} data=${data} headers=${headers}
+ Log Received response from dcae ${resp.json()}
+ Should Be Equal As Strings ${resp.status_code} 200
+ Check DCAE Results ${resp.json()}
+
+Check DCAE Results
+ [Documentation] Parse DCAE JSON response and make sure all rows have healthTestStatus=GREEN
+ [Arguments] ${json}
+ @{rows}= Get From Dictionary ${json['returns']} rows
+ @{headers}= Get From Dictionary ${json['returns']} columns
+
+ # Retrieve column names from headers
+ ${columns}= Create List
+ :for ${header} in @{headers}
+ \ ${colName}= Get From Dictionary ${header} colName
+ \ Append To List ${columns} ${colName}
+
+ # Process each row making sure status=GREEN
+ :for ${row} in @{rows}
+ \ ${cells}= Get From Dictionary ${row} cells
+ \ ${dict}= Make A Dictionary ${cells} ${columns}
+ \ Dictionary Should Contain Item ${dict} healthTestStatus GREEN
+
+
+Make A Dictionary
+ [Documentation] Given a list of column names and a list of dictionaries, map columname=value
+ [Arguments] ${columns} ${names} ${valuename}=value
+ ${dict}= Create Dictionary
+ ${collength}= Get Length ${columns}
+ ${namelength}= Get Length ${names}
+ :for ${index} in range 0 ${collength}
+ \ ${name}= Evaluate ${names}[${index}]
+ \ ${valued}= Evaluate ${columns}[${index}]
+ \ ${value}= Get From Dictionary ${valued} ${valueName}
+ \ Set To Dictionary ${dict} ${name} ${value}
+ [Return] ${dict} \ No newline at end of file
diff --git a/robot/resources/global_properties.robot b/robot/resources/global_properties.robot
new file mode 100644
index 00000000..819f56a4
--- /dev/null
+++ b/robot/resources/global_properties.robot
@@ -0,0 +1,22 @@
+*** Settings ***
+Documentation store all properties that can change or are used in multiple places here
+... format is all caps with underscores between words and prepended with GLOBAL
+... make sure you prepend them with GLOBAL so that other files can easily see it is from this file.
+
+
+*** Variables ***
+${GLOBAL_APPLICATION_ID} robot-ete
+${GLOBAL_MSO_STATUS_PATH} /ecomp/mso/infra/orchestrationRequests/v2/
+${GLOBAL_SELENIUM_BROWSER} chrome
+${GLOBAL_SELENIUM_BROWSER_CAPABILITIES} Create Dictionary
+${GLOBAL_SELENIUM_DELAY} 0
+${GLOBAL_SELENIUM_BROWSER_IMPLICIT_WAIT} 5
+${GLOBAL_SELENIUM_BROWSER_WAIT_TIMEOUT} 15
+${GLOBAL_OPENSTACK_HEAT_SERVICE_TYPE} orchestration
+${GLOBAL_OPENSTACK_CINDER_SERVICE_TYPE} volume
+${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} compute
+${GLOBAL_OPENSTACK_NEUTRON_SERVICE_TYPE} network
+${GLOBAL_OPENSTACK_GLANCE_SERVICE_TYPE} image
+${GLOBAL_OPENSTACK_KEYSTONE_SERVICE_TYPE} identity
+${GLOBAL_AAI_CLOUD_OWNER} Rackspace
+${GLOBAL_BUILD_NUMBER} 0 \ No newline at end of file
diff --git a/robot/resources/heatbridge.robot b/robot/resources/heatbridge.robot
new file mode 100644
index 00000000..eb6a9ed0
--- /dev/null
+++ b/robot/resources/heatbridge.robot
@@ -0,0 +1,148 @@
+*** Settings ***
+Library HeatBridge
+Library Collections
+Library StringTemplater
+Library OperatingSystem
+Library UUID
+
+Resource openstack/keystone_interface.robot
+Resource openstack/heat_interface.robot
+Resource openstack/nova_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}
+
+
+*** Keywords ***
+Execute Heatbridge
+ [Documentation] Run the Heatbridge against the stack to generate the bulkadd message
+ ... Execute the build add
+ ... Validate the add results by running the named query
+ [Arguments] ${stack_name} ${service_instance_id} ${service}
+ Return From Keyword If '${service}' == 'vVG'
+ Run Openstack Auth Request auth
+ ${stack_info}= Wait for Stack to Be Deployed auth ${stack_name}
+ ${stack_id}= Get From Dictionary ${stack_info} id
+ ${tenant_id}= Get From Dictionary ${stack_info} OS::project_id
+ ${vnf_id}= Get From Dictionary ${stack_info} vnf_id
+ ${openstack_identity_url}= Catenate ${GLOBAL_OPENSTACK_KEYSTONE_SERVER}/v2.0
+ 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}
+ Should Be Equal As Strings ${resp.status_code} 200
+ Generate Reverse Heatbridge ${request}
+ Run Validation Query ${stack_info} ${service}
+
+Run Validation Query
+ [Documentation] Run A&AI query to validate the bulk add
+ [Arguments] ${stack_info} ${service}
+ Return from Keyword If '${service}' == ''
+ ${server_name_parameter}= Get From Dictionary ${GLOBAL_VALIDATE_NAME_MAPPING} ${service}
+ ${vserver_name}= Get From Dictionary ${stack_info} ${server_name_parameter}
+ Run Vserver Query ${vserver_name}
+
+Run Vserver Query
+ [Documentation] Run A&AI query to validate the bulk add
+ [Arguments] ${vserver_name}
+ ${dict}= Create Dictionary vserver_name=${vserver_name}
+ ${request}= OperatingSystem.Get File ${NAMED_QUERY_TEMPLATE}
+ ${request}= Template String ${request} ${dict}
+ ${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
+
+
+Execute Heatbridge Teardown
+ [Documentation] Run teardown against the stack to generate a bulkadd message that removes it
+ [Arguments] ${stack_name}
+ Run Openstack Auth Request auth
+ ${stack_info}= Wait for Stack to Be Deployed auth ${stack_name}
+ ${stack_id}= Get From Dictionary ${stack_info} id
+ ${tenant_id}= Get From Dictionary ${stack_info} OS::project_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
+ [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
diff --git a/robot/resources/json_templater.robot b/robot/resources/json_templater.robot
new file mode 100644
index 00000000..6a5ca171
--- /dev/null
+++ b/robot/resources/json_templater.robot
@@ -0,0 +1,21 @@
+*** Settings ***
+Documentation This resource is filling out json string templates and returning the json back
+Library RequestsLibrary
+Library StringTemplater
+Library OperatingSystem
+Resource global_properties.robot
+
+*** Keywords ***
+Fill JSON Template
+ [Documentation] Runs substitution on template to return a filled in json
+ [Arguments] ${json} ${arguments}
+ ${returned_string}= Template String ${json} ${arguments}
+ ${returned_json}= To Json ${returned_string}
+ [Return] ${returned_json}
+
+Fill JSON Template File
+ [Documentation] Runs substitution on template to return a filled in json
+ [Arguments] ${json_file} ${arguments}
+ ${json}= OperatingSystem.Get File ${json_file}
+ ${returned_json}= Fill JSON Template ${json} ${arguments}
+ [Return] ${returned_json} \ No newline at end of file
diff --git a/robot/resources/mr_interface.robot b/robot/resources/mr_interface.robot
new file mode 100644
index 00000000..11c9348f
--- /dev/null
+++ b/robot/resources/mr_interface.robot
@@ -0,0 +1,28 @@
+*** Settings ***
+Documentation The main interface for interacting with Message router. It handles low level stuff like managing the http request library and message router required fields
+Library RequestsClientCert
+Library RequestsLibrary
+Library UUID
+
+Resource global_properties.robot
+
+*** Variables ***
+${MR_HEALTH_CHECK_PATH} /topics
+
+*** Keywords ***
+Run MR Health Check
+ [Documentation] Runs MR Health check
+ ${resp}= Run MR Get Request ${MR_HEALTH_CHECK_PATH}
+ Should Be Equal As Strings ${resp.status_code} 200
+ Should Contain ${resp.json()} topics
+
+Run MR Get Request
+ [Documentation] Runs MR Get request
+ [Arguments] ${data_path}
+ ${session}= Create Session mr ${GLOBAL_MR_SERVER}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Get Request mr ${data_path} headers=${headers}
+ Log Received response from message router ${resp.text}
+ [Return] ${resp}
+
diff --git a/robot/resources/mso_interface.robot b/robot/resources/mso_interface.robot
new file mode 100644
index 00000000..b6a53b40
--- /dev/null
+++ b/robot/resources/mso_interface.robot
@@ -0,0 +1,54 @@
+*** Settings ***
+Documentation The main interface for interacting with MSO. It handles low level stuff like managing the http request library and MSO required fields
+Library RequestsLibrary
+Library UUID
+Library OperatingSystem
+Library Collections
+Resource global_properties.robot
+Resource ../resources/json_templater.robot
+*** Variables ***
+${MSO_HEALTH_CHECK_PATH} /ecomp/mso/infra/globalhealthcheck
+
+*** Keywords ***
+Run MSO Health Check
+ [Documentation] Runs an MSO global health check
+ ${auth}= Create List ${GLOBAL_MSO_USERNAME} ${GLOBAL_MSO_PASSWORD}
+ ${session}= Create Session mso ${GLOBAL_MSO_SERVER}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=text/html Content-Type=text/html X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Get Request mso ${MSO_HEALTH_CHECK_PATH} headers=${headers}
+ Should Be Equal As Strings ${resp.status_code} 200
+
+Run MSO Get Request
+ [Documentation] Runs an MSO get request
+ [Arguments] ${data_path} ${accept}=application/json
+ ${auth}= Create List ${GLOBAL_MSO_USERNAME} ${GLOBAL_MSO_PASSWORD}
+ Log Creating session ${GLOBAL_MSO_SERVER}
+ ${session}= Create Session mso ${GLOBAL_MSO_SERVER} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=${accept} Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Get Request mso ${data_path} headers=${headers}
+ Log Received response from mso ${resp.text}
+ [Return] ${resp}
+
+Poll MSO Get Request
+ [Documentation] Runs an MSO get request until a certain status is received. valid values are COMPLETE
+ [Arguments] ${data_path} ${status}
+ ${auth}= Create List ${GLOBAL_MSO_USERNAME} ${GLOBAL_MSO_PASSWORD}
+ Log Creating session ${GLOBAL_MSO_SERVER}
+ ${session}= Create Session mso ${GLOBAL_MSO_SERVER} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ #do this until it is done
+ :FOR ${i} IN RANGE 20
+ \ ${resp}= Get Request mso ${data_path} headers=${headers}
+ \ Should Not Contain ${resp.text} FAILED
+ \ Log ${resp.json()['request']['requestStatus']['requestState']}
+ \ ${exit_loop}= Evaluate "${resp.json()['request']['requestStatus']['requestState']}" == "${status}"
+ \ Exit For Loop If ${exit_loop}
+ \ Sleep 15s
+ Log Received response from mso ${resp.text}
+ [Return] ${resp}
+
+
+
diff --git a/robot/resources/openstack/cinder_interface.robot b/robot/resources/openstack/cinder_interface.robot
new file mode 100644
index 00000000..ee1a253b
--- /dev/null
+++ b/robot/resources/openstack/cinder_interface.robot
@@ -0,0 +1,50 @@
+*** Settings ***
+Documentation The main interface for interacting with Openstack. It handles low level stuff like managing the authtoken and Openstack required fields
+Library OpenstackLibrary
+Library RequestsLibrary
+Library UUID
+Library OperatingSystem
+Resource ../global_properties.robot
+Resource ../json_templater.robot
+Resource openstack_common.robot
+
+
+*** Variables ***
+${OPENSTACK_CINDER_API_VERSION} /v1
+${OPENSTACK_CINDER_TYPES_PATH} /types
+${OPENSTACK_CINDER_VOLUMES_PATH} /volumes
+${OPENSTACK_CINDER_VOLUMES_ADD_BODY_FILE} robot/assets/templates/cinder_add_volume.template
+${OPENSTACK_CINDER_VOLUMES_TYPE} SSD
+${OPENSTACK_CINDER_AVAILABILITY_ZONE} nova
+
+*** Keywords ***
+Get Openstack Volume Types
+ [Documentation] Returns the openstack volume types information
+ [Arguments] ${alias}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_CINDER_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_CINDER_TYPES_PATH}
+ [Return] ${resp.json()}
+
+Get Openstack Volume
+ [Documentation] Returns the openstack volume information for the passed in volume id
+ [Arguments] ${alias} ${volume_id}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_CINDER_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_CINDER_VOLUMES_PATH} /${volume_id}
+ [Return] ${resp.json()}
+
+Add Openstack Volume
+ [Documentation] Runs an Openstack Request to add a volume and returns that volume id of the created volume
+ [Arguments] ${alias} ${name} ${size}
+ ${data_template}= OperatingSystem.Get File ${OPENSTACK_CINDER_VOLUMES_ADD_BODY_FILE}
+ ${uuid}= Generate UUID
+ ${arguments}= Create Dictionary name=${name} description=${GLOBAL_APPLICATION_ID}${uuid} size=${size} type=${OPENSTACK_CINDER_VOLUMES_TYPE} availability_zone=${OPENSTACK_CINDER_AVAILABILITY_ZONE}
+ ${data}= Fill JSON Template ${data_template} ${arguments}
+ ${resp}= Internal Post Openstack ${alias} ${GLOBAL_OPENSTACK_CINDER_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_CINDER_VOLUMES_PATH} data_path= data=${data}
+ Should Be Equal As Strings 200 ${resp.status_code}
+ [Return] ${resp.json()['volume']['id']}
+
+Delete Openstack Volume
+ [Documentation] Runs an Openstack Request to delete a volume
+ [Arguments] ${alias} ${volume_id}
+ ${resp}= Internal Delete Openstack ${alias} ${GLOBAL_OPENSTACK_CINDER_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_CINDER_VOLUMES_PATH} /${volume_id}
+ ${status_string}= Convert To String ${resp.status_code}
+ Should Match Regexp ${status_string} ^(204|200|404)$
+ [Return] ${resp.text} \ No newline at end of file
diff --git a/robot/resources/openstack/heat_interface.robot b/robot/resources/openstack/heat_interface.robot
new file mode 100644
index 00000000..74c7aac8
--- /dev/null
+++ b/robot/resources/openstack/heat_interface.robot
@@ -0,0 +1,93 @@
+*** Settings ***
+Documentation The interface for interacting with Openstack Heat API.
+Library OpenstackLibrary
+Library RequestsLibrary
+Library UUID
+Library OperatingSystem
+Library HEATUtils
+Library StringTemplater
+Library Collections
+Resource ../global_properties.robot
+Resource ../json_templater.robot
+Resource openstack_common.robot
+
+*** Variables ***
+${OPENSTACK_HEAT_API_VERSION} /v1
+${OPENSTACK_HEAT_STACK_PATH} /stacks
+${OPENSTACK_HEAT_ADD_STACK_TEMPLATE} robot/assets/templates/heat_add_stack.template
+
+
+*** Keywords ***
+Get Openstack Stacks
+ [Documentation] Returns the openstack stacks info
+ [Arguments] ${alias}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_HEAT_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_HEAT_STACK_PATH}
+ [Return] ${resp.json()}
+
+Get Openstack Stack
+ [Documentation] Returns the openstack stacks info for the given stack name
+ [Arguments] ${alias} ${stack_name}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_HEAT_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_HEAT_STACK_PATH} /${stack_name}
+ [Return] ${resp.json()}
+
+Create Openstack Stack
+ [Documentation] Takes an openstack heat yaml and returns the created stack
+ [Arguments] ${alias} ${request}
+ ${resp}= Internal Post Openstack ${alias} ${GLOBAL_OPENSTACK_HEAT_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_HEAT_STACK_PATH} data_path= data=${request}
+ [Return] ${resp.json()}
+
+Make Add Stack Request
+ [Documentation] Makes a JSON Add Stack Request from YAML template and env files
+ [Arguments] ${name} ${template} ${env}
+ ${templatedata}= Template Yaml To Json ${template}
+ ${envdata}= Env Yaml To Json ${env}
+ ${dict}= Create Dictionary template=${templatedata} parameters=${envdata} stack_name=${name}
+ ${resp}= OperatingSystem.Get File ${OPENSTACK_HEAT_ADD_STACK_TEMPLATE}
+ ${request}= Template String ${resp} ${dict}
+ Log $request
+ [Return] ${request}
+
+Delete Openstack Stack
+ [Documentation] Deletes and Openstack Stack for the passed name and id
+ [Arguments] ${alias} ${stack_name} ${stack_id}
+ ${data_path}= Catenate /${stack_name}/${stack_id}
+ ${resp}= Internal Delete Openstack ${alias} ${GLOBAL_OPENSTACK_HEAT_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_HEAT_STACK_PATH} data_path=${data_path}
+ Should Be Equal As Strings 204 ${resp.status_code}
+ [Return] ${resp}
+
+Get Stack Details
+ [Documentation] Gets all of the information necessary for tearing down an existing Openstack Stack
+ [Arguments] ${alias} ${stack_name}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_HEAT_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_HEAT_STACK_PATH} /${stack_name}
+ ${result}= Stack Info Parse ${resp.json()}
+ [Return] ${result}
+
+Get Stack Template
+ [Documentation] Gets all of the template information of an existing Openstack Stack
+ [Arguments] ${alias} ${stack_name} ${stack_id}
+ ${data_path}= Catenate /${stack_name}/${stack_id}/template
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_HEAT_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_HEAT_STACK_PATH} ${data_path}
+ ${template}= Catenate ${resp.json()}
+ [Return] ${template}
+
+Get Stack Resources
+ [Documentation] Gets all of the resources of an existing Openstack Stack
+ [Arguments] ${alias} ${stack_name} ${stack_id}
+ ${data_path}= Catenate /${stack_name}/${stack_id}/resources
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_HEAT_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_HEAT_STACK_PATH} ${data_path}
+ [Return] ${resp.json()}
+
+Wait for Stack to Be Deployed
+ [Arguments] ${alias} ${stack_name} ${timeout}=600s
+ ${stack_info}= Wait Until Keyword Succeeds ${timeout} 30 sec Get Deployed Stack ${alias} ${stack_name}
+ ${status}= Get From Dictionary ${stack_info} stack_status
+ Should Be Equal ${status} CREATE_COMPLETE
+ [Return] ${stack_info}
+
+Get Deployed Stack
+ [Arguments] ${alias} ${stack_name}
+ ${stack_info}= Get Stack Details ${alias} ${stack_name}
+ ${status}= Get From Dictionary ${stack_info} stack_status
+ Should Not Be Equal ${status} CREATE_IN_PROGRESS
+ [Return] ${stack_info}
+ \ No newline at end of file
diff --git a/robot/resources/openstack/keystone_interface.robot b/robot/resources/openstack/keystone_interface.robot
new file mode 100644
index 00000000..928efbdd
--- /dev/null
+++ b/robot/resources/openstack/keystone_interface.robot
@@ -0,0 +1,49 @@
+*** Settings ***
+Documentation The main interface for interacting with Openstack Keystone API. It handles low level stuff like managing the authtoken and Openstack required fields
+Library OpenstackLibrary
+Library RequestsLibrary
+Library UUID
+Library OperatingSystem
+Resource ../global_properties.robot
+Resource ../json_templater.robot
+Resource openstack_common.robot
+
+*** Variables ***
+${OPENSTACK_KEYSTONE_API_VERSION} /v2.0
+${OPENSTACK_KEYSTONE_AUTH_PATH} /tokens
+${OPENSTACK_KEYSTONE_AUTH_BODY_FILE} robot/assets/templates/keystone_get_auth.template
+${OPENSTACK_KEYSTONE_TENANT_PATH} /tenants
+
+*** Keywords ***
+Run Openstack Auth Request
+ [Documentation] Runs an Openstack Auth Request and returns the token and service catalog. you need to include the token in future request's x-auth-token headers. Service catalog describes what can be called
+ [Arguments] ${alias} ${username}= ${password}=
+ ${username} ${password}= Set Openstack Credentials ${username} ${password}
+ ${session}= Create Session keystone ${GLOBAL_OPENSTACK_KEYSTONE_SERVER} verify=True
+ ${uuid}= Generate UUID
+ ${data_template}= OperatingSystem.Get File ${OPENSTACK_KEYSTONE_AUTH_BODY_FILE}
+ ${arguments}= Create Dictionary username=${username} password=${password}
+ ${data}= Fill JSON Template ${data_template} ${arguments}
+ ${data_path}= Catenate ${OPENSTACK_KEYSTONE_API_VERSION}${OPENSTACK_KEYSTONE_AUTH_PATH}
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ Log Sending authenticate post request ${data_path} with headers ${headers} and data ${data}
+ ${resp}= Post Request keystone ${data_path} data=${data} headers=${headers}
+ Save Openstack Auth ${alias} ${resp.text}
+ Log Received response from keystone ${resp.text}
+
+Get Openstack Tenants
+ [Documentation] Returns all the openstack tenant info
+ [Arguments] ${alias}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_KEYSTONE_SERVICE_TYPE} region= url_ext=${OPENSTACK_KEYSTONE_TENANT_PATH} data_path=
+ [Return] ${resp.json()}
+
+Get Openstack Tenant
+ [Documentation] Returns the openstack tenant info for the specified tenantid
+ [Arguments] ${alias} ${tenant_id}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_KEYSTONE_SERVICE_TYPE} region= url_ext=${OPENSTACK_KEYSTONE_TENANT_PATH} data_path=/${tenant_id}
+ [Return] ${resp.json()}
+
+Set Openstack Credentials
+ [Arguments] ${username} ${password}
+ Return From Keyword If '${username}' != '' ${username} ${password}
+ [Return] ${GLOBAL_VM_PROPERTIES['openstack_username']} ${GLOBAL_VM_PROPERTIES['openstack_password']} \ No newline at end of file
diff --git a/robot/resources/openstack/neutron_interface.robot b/robot/resources/openstack/neutron_interface.robot
new file mode 100644
index 00000000..77635cdd
--- /dev/null
+++ b/robot/resources/openstack/neutron_interface.robot
@@ -0,0 +1,123 @@
+*** Settings ***
+Documentation The main interface for interacting with Openstack. It handles low level stuff like managing the authtoken and Openstack required fields
+Library OpenstackLibrary
+Library RequestsLibrary
+Library UUID
+Library OperatingSystem
+Library Collections
+Resource ../global_properties.robot
+Resource ../json_templater.robot
+Resource openstack_common.robot
+
+*** Variables ***
+${OPENSTACK_NEUTRON_API_VERSION} /v2.0
+${OPENSTACK_NEUTRON_NETWORK_PATH} /networks
+${OPENSTACK_NEUTRON_NETWORK_ADD_BODY_FILE} robot/assets/templates/neutron_add_network.template
+${OPENSTACK_NEUTRON_SUBNET_PATH} /subnets
+${OPENSTACK_NEUTRON_SUBNET_ADD_BODY_FILE} robot/assets/templates/neutron_add_subnet.template
+${OPENSTACK_NEUTRON_PORT_PATH} /ports
+
+*** Keywords ***
+Get Openstack Network
+ [Documentation] Runs an Openstack Request and returns the network info
+ [Arguments] ${alias} ${network_id}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_NEUTRON_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NEUTRON_NETWORK_PATH} /${network_id}
+ [Return] ${resp.json()}
+
+Get Openstack Networks
+ [Documentation] Runs an Openstack Request and returns the network info
+ [Arguments] ${alias}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_NEUTRON_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NEUTRON_NETWORK_PATH}
+ [Return] ${resp.json()}
+
+Get Openstack Subnets
+ [Documentation] Runs an Openstack Request and returns the network info
+ [Arguments] ${alias}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_NEUTRON_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NEUTRON_SUBNET_PATH}
+ [Return] ${resp.json()}
+
+Get Openstack Ports
+ [Documentation] Runs an Openstack Request and returns the network info
+ [Arguments] ${alias}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_NEUTRON_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NEUTRON_PORT_PATH}
+ [Return] ${resp.json()}
+
+Add Openstack Network
+ [Documentation] Runs an Openstack Request to add a network and returns that network id of the created network
+ [Arguments] ${alias} ${name}
+ ${data_template}= OperatingSystem.Get File ${OPENSTACK_NEUTRON_NETWORK_ADD_BODY_FILE}
+ ${arguments}= Create Dictionary name=${name}
+ ${data}= Fill JSON Template ${data_template} ${arguments}
+ ${resp}= Internal Post Openstack ${alias} ${GLOBAL_OPENSTACK_NEUTRON_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NEUTRON_NETWORK_PATH} data_path= data=${data}
+ Should Be Equal As Strings 201 ${resp.status_code}
+ [Return] ${resp.json()['network']['id']}
+
+Delete Openstack Network
+ [Documentation] Runs an Openstack Request to delete a network
+ [Arguments] ${alias} ${network_id}
+ ${resp}= Internal Delete Openstack ${alias} ${GLOBAL_OPENSTACK_NEUTRON_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NEUTRON_NETWORK_PATH} /${network_id}
+ ${status_string}= Convert To String ${resp.status_code}
+ Should Match Regexp ${status_string} ^(204|200)$
+ [Return] ${resp.text}
+
+Add Openstack Network With Subnet If Not Exists
+ [Documentation] Runs an Openstack Request to add a network and returns that network id of the created network
+ [Arguments] ${alias} ${name} ${cidr}
+ ${network}= Get Openstack Subnet By Name ${alias} ${name} ${cidr}
+ ${pass} ${v}= Run Keyword and Ignore Error Dictionary Should Contain Key ${network} id
+ Run Keyword If '${pass}' == 'FAIL' Add Openstack Network With Subnet ${alias} ${name} ${cidr}
+ ${network}= Get Openstack Subnet By Name ${alias} ${name} ${cidr}
+ ${network_id}= Get From Dictionary ${network} id
+ [Return] ${network_id}
+
+
+Add Openstack Network With Subnet
+ [Documentation] Runs an Openstack Request to add a network and returns that network id of the created network
+ [Arguments] ${alias} ${name} ${cidr}
+ ${network_id}= Add Openstack Network ${alias} ${name}
+ ${data_template}= OperatingSystem.Get File ${OPENSTACK_NEUTRON_SUBNET_ADD_BODY_FILE}
+ ${arguments}= Create Dictionary network_id=${network_id} cidr=${cidr} subnet_name=${name}
+ ${data}= Fill JSON Template ${data_template} ${arguments}
+ ${resp}= Internal Post Openstack ${alias} ${GLOBAL_OPENSTACK_NEUTRON_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NEUTRON_SUBNET_PATH} data_path= data=${data}
+ Should Be Equal As Strings 201 ${resp.status_code}
+ [Return] ${network_id}
+
+Get Openstack Subnet By Name
+ [Documentation] Retrieve the subnet from openstack by it's name.
+ [Arguments] ${alias} ${network_name} ${network_cidr}
+ ${resp}= Get Openstack Subnets ${alias}
+ @{list}= Get From Dictionary ${resp} subnets
+ ${returnnet}= Set Variable
+ :for ${net} in @{list}
+ \ ${name}= Get From Dictionary ${net} name
+ \ ${cidr}= Get From Dictionary ${net} cidr
+ \ ${returnnet}= Set Variable ${net}
+ \ Exit For Loop If '${name}'=='${network_name}' and '${cidr}'=='${network_cidr}'
+ \ ${returnnet}= Create DIctionary
+ [Return] ${returnnet}
+
+Get Openstack IP By Name
+ [Arguments] ${alias} ${network_name} ${cidr} ${ip}
+ ${ports}= Get Openstack Ports For Subnet ${alias} ${network_name} ${cidr}
+ Log ${ports}
+ :for ${port} in @{ports}
+ \ Return From Keyword If '${port['fixed_ips'][0]['ip_address']}' == '${ip}' ${port}
+ [Return] None
+
+Get Openstack Ports For Subnet
+ [Arguments] ${alias} ${network_name} ${cidr}
+ ${net}= Get Openstack Subnet By Name ${alias} ${network_name} ${cidr}
+ ${ports}= Get Openstack Ports ${alias}
+ ${net_ports}= Create List
+ :for ${port} in @{ports['ports']}
+ \ Run Keyword If '${net['network_id']}' == '${port['network_id']}' Append To List ${net_ports} ${port}
+ [Return] ${net_ports}
+
+Delete Openstack Port
+ [Arguments] ${alias} ${port_id}
+ ${resp}= Internal Delete Openstack ${alias} ${GLOBAL_OPENSTACK_NEUTRON_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NEUTRON_PORT_PATH} /${port_id}
+ ${status_string}= Convert To String ${resp.status_code}
+ Should Match Regexp ${status_string} ^(204|200)$
+ [Return] ${resp.text}
+
+ \ No newline at end of file
diff --git a/robot/resources/openstack/nova_interface.robot b/robot/resources/openstack/nova_interface.robot
new file mode 100644
index 00000000..efee279a
--- /dev/null
+++ b/robot/resources/openstack/nova_interface.robot
@@ -0,0 +1,149 @@
+*** Settings ***
+Documentation The main interface for interacting with Openstack. It handles low level stuff like managing the authtoken and Openstack required fields
+Library OpenstackLibrary
+Library RequestsLibrary
+Library JSONUtils
+Library UUID
+Library OperatingSystem
+Library Collections
+Resource ../global_properties.robot
+Resource ../json_templater.robot
+Resource openstack_common.robot
+
+*** Variables ***
+${OPENSTACK_NOVA_API_VERSION} /v2
+${OPENSTACK_NOVA_KEYPAIR_PATH} /os-keypairs
+${OPENSTACK_NOVA_KEYPAIR_ADD_BODY_FILE} robot/assets/templates/nova_add_keypair.template
+${OPENSTACK_NOVA_KEYPAIR_SSH_KEY} robot/assets/keys/robot_ssh_public_key.txt
+${OPENSTACK_NOVA_FLAVORS_PATH} /flavors
+${OPENSTACK_NOVA_SERVERS_PATH} /servers
+${OPENSTACK_NOVA_IMAGES_PATH} /images
+${OPENSTACK_NOVA_SERVERS_REBOOT_BODY} {"reboot" : { "type" : "SOFT" }}
+${OPENSTACK_NOVA_SERVER_ADD_BODY_FILE} robot/assets/templates/nova_add_server.template
+
+
+*** Keywords ***
+Get Openstack Keypair
+ [Documentation] Runs an Openstack Request and returns the keypair info
+ [Arguments] ${alias} ${keypair_name}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NOVA_KEYPAIR_PATH} /${keypair_name}
+ [Return] ${resp.json()}
+
+Add Openstack Keypair
+ [Documentation] Runs an Openstack Request to add a keypair and returns the keypair name
+ [Arguments] ${alias} ${name}
+ ${data_template}= OperatingSystem.Get File ${OPENSTACK_NOVA_KEYPAIR_ADD_BODY_FILE}
+ ${ssh_key}= OperatingSystem.Get File ${OPENSTACK_NOVA_KEYPAIR_SSH_KEY}
+ ${arguments}= Create Dictionary name=${name} publickey=${ssh_key}
+ ${data}= Fill JSON Template ${data_template} ${arguments}
+ ${resp}= Internal Post Openstack ${alias} ${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NOVA_KEYPAIR_PATH} data_path= data=${data}
+ Should Be Equal As Strings 200 ${resp.status_code}
+ [Return] ${resp.json()['keypair']['name']}
+
+Delete Openstack Keypair
+ [Documentation] Runs an Openstack Request to delete a keypair
+ [Arguments] ${alias} ${keypair_name}
+ ${resp}= Internal Delete Openstack ${alias} ${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NOVA_KEYPAIR_PATH} /${keypair_name}
+ ${status_string}= Convert To String ${resp.status_code}
+ Should Match Regexp ${status_string} ^(204|202|200)$
+ [Return] ${resp.text}
+
+
+Get Openstack Servers
+ [Documentation] Returns the list of servers as a dictionary by name
+ [Arguments] ${alias}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NOVA_SERVERS_PATH} /detail
+ Log Returned from Internal Get Openstack
+ ${by_name}= Make List Into Dict ${resp.json()['servers']} name
+ Log got it
+ [Return] ${by_name}
+
+Get Openstack Server By Id
+ [Documentation] Returns the openstack stacks info for the given stack name
+ [Arguments] ${alias} ${server_id}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NOVA_SERVERS_PATH} /${server_id}
+ [Return] ${resp}
+
+Get Openstack Flavors
+ [Documentation] Runs an Openstack Request and returns the flavor list
+ [Arguments] ${alias}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NOVA_FLAVORS_PATH}
+ [Return] ${resp.json()}
+
+Get Openstack Images
+ [Documentation] Runs an Openstack Request and returns the flavor list
+ [Arguments] ${alias}
+ ${resp}= Internal Get Openstack ${alias} ${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NOVA_IMAGES_PATH}
+ [Return] ${resp.json()}
+
+Reboot Server
+ [Documentation] Requests a reboot of the passed server id
+ [Arguments] ${alias} ${server_id}
+ ${resp}= Internal Post Openstack ${alias} ${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NOVA_SERVERS_PATH} /${server_id}/action ${OPENSTACK_NOVA_SERVERS_REBOOT_BODY}
+ [Return] ${resp}
+
+Add Server
+ [Documentation] Adds a server for the passed if
+ [Arguments] ${alias} ${name} ${imageRef} ${flavorRef}
+ ${dict}= Create Dictionary name=${name} imageRef=${imageRef} flavorRef=${flavorRef}
+ ${data}= Fill JSON Template File ${OPENSTACK_NOVA_SERVER_ADD_BODY_FILE} ${dict}
+ ${resp}= Internal Post Openstack ${alias} ${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NOVA_SERVERS_PATH} data_path= data=${data}
+ [Return] ${resp}
+
+Add Server For Image Name
+ [Documentation] Adds a server for the passed if
+ [Arguments] ${alias} ${name} ${imageName} ${flavorName}
+ ${images}= Get Openstack Images ${alias}
+ ${flavors}= Get Openstack Flavors ${alias}
+ ${images}= Get From Dictionary ${images} images
+ ${flavors}= Get From Dictionary ${flavors} flavors
+ ${imageRef}= Get Id For Name ${images} ${imageName}
+ ${flavorRef}= Get Id For Name ${flavors} ${flavorName}
+ ${dict}= Create Dictionary name=${name} imageRef=${imageRef} flavorRef=${flavorRef}
+ ${data}= Fill JSON Template File ${OPENSTACK_NOVA_SERVER_ADD_BODY_FILE} ${dict}
+ ${resp}= Internal Post Openstack ${alias} ${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NOVA_SERVERS_PATH} data_path= data=${data}
+ ${status_string}= Convert To String ${resp.status_code}
+ Should Match Regexp ${status_string} ^(202)$
+ [Return] ${resp.json()}
+
+Wait for Server to Be Active
+ [Arguments] ${alias} ${server_id} ${timeout}=300s
+ ${server_info}= Wait Until Keyword Succeeds ${timeout} 10 sec Get Active Server ${alias} ${server_id}
+ ${status}= Get From Dictionary ${server_info} status
+ Should Be Equal ${status} ACTIVE
+ [Return] ${server_info}
+
+ Get Active Server
+ [Arguments] ${alias} ${server_id}
+ ${resp}= Get Openstack Server By Id ${alias} ${server_id}
+ Should Be Equal As Strings ${resp.status_code} 200
+ ${server_info}= Set Variable ${resp.json()}
+ ${server_info}= Get From Dictionary ${server_info} server
+ ${status}= Get From Dictionary ${server_info} status
+ Should Not Be Equal ${status} BUILD
+ [Return] ${server_info}
+
+Wait for Server to Be Deleted
+ [Arguments] ${alias} ${server_id}
+ Wait Until Keyword Succeeds 300s 10s Get Deleted Server ${alias} ${server_id}
+
+Get Deleted Server
+ [Arguments] ${alias} ${server_id}
+ ${resp}= Get Openstack Server By Id ${alias} ${server_id}
+ Should Be Equal As Strings ${resp.status_code} 404
+
+Delete Server
+ [Documentation] Runs an Openstack Request to delete a keypair
+ [Arguments] ${alias} ${server_id}
+ ${resp}= Internal Delete Openstack ${alias} ${GLOBAL_OPENSTACK_NOVA_SERVICE_TYPE} ${GLOBAL_OPENSTACK_SERVICE_REGION} ${OPENSTACK_NOVA_SERVERS_PATH} /${server_id}
+ ${status_string}= Convert To String ${resp.status_code}
+ Should Match Regexp ${status_string} ^(204)$
+ [Return] ${resp.text}
+
+Get Id For Name
+ [Arguments] ${list} ${name}
+ :for ${item} in @{list}
+ \ ${id}= Get From Dictionary ${item} id
+ \ ${n}= Get From Dictionary ${item} name
+ \ Return from Keyword If '${n}' == '${name}' ${id}
+ [Return] None
diff --git a/robot/resources/openstack/openstack_common.robot b/robot/resources/openstack/openstack_common.robot
new file mode 100644
index 00000000..6a53ab63
--- /dev/null
+++ b/robot/resources/openstack/openstack_common.robot
@@ -0,0 +1,50 @@
+*** Settings ***
+Documentation The private interface for interacting with Openstack. It handles low level stuff like managing the authtoken and Openstack required fields
+
+Library OpenstackLibrary
+Library RequestsLibrary
+Library UUID
+Resource ../global_properties.robot
+
+*** Keywords ***
+Internal Get Openstack
+ [Documentation] Runs an Openstack Get Request and returns the response
+ [Arguments] ${alias} ${service_type} ${region} ${url_ext} ${data_path}=
+ Log Internal Get Openstack values alias=${alias} service_type=${service_type} region=${region} url_ext=${url_ext} data_path=${data_path}
+ ${url}= Get Openstack Service Url ${alias} ${service_type} ${region}
+ ${uuid}= Generate UUID
+ ${session_alias}= Catenate openstack-${uuid}
+ ${session}= Create Session ${session_alias} ${url}${url_ext} verify=True
+ ${token}= Get Openstack Token ${alias}
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID} X-Auth-Token=${token}
+ ${resp}= Get Request ${session_alias} ${data_path} headers=${headers}
+ Log Received response from openstack ${resp.text}
+ [Return] ${resp}
+
+Internal Post Openstack
+ [Documentation] Runs an Openstack Post Response and returns the response
+ [Arguments] ${alias} ${service_type} ${region} ${url_ext} ${data_path}= ${data}=
+ Log Internal Post Openstack values alias=${alias} service_type=${service_type} region=${region} url_ext=${url_ext} data_path=${data_path}
+ ${url}= Get Openstack Service Url ${alias} ${service_type} ${region}
+ ${uuid}= Generate UUID
+ ${session_alias}= Catenate openstack-${uuid}
+ ${session}= Create Session ${session_alias} ${url}${url_ext} verify=True
+ ${token}= Get Openstack Token ${alias}
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID} X-Auth-Token=${token}
+ ${resp}= Post Request ${session_alias} ${data_path} data=${data} headers=${headers}
+ Log Received response from openstack ${resp.text}
+ [Return] ${resp}
+
+Internal Delete Openstack
+ [Documentation] Runs an Openstack Delete Request and returns the response
+ [Arguments] ${alias} ${service_type} ${region} ${url_ext} ${data_path}=
+ Log Internal Post Openstack values alias=${alias} service_type=${service_type} region=${region} url_ext=${url_ext} data_path=${data_path}
+ ${url}= Get Openstack Service Url ${alias} ${service_type} ${region}
+ ${uuid}= Generate UUID
+ ${session_alias}= Catenate openstack-${uuid}
+ ${session}= Create Session ${session_alias} ${url}${url_ext} verify=True
+ ${token}= Get Openstack Token ${alias}
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID} X-Auth-Token=${token}
+ ${resp}= Delete Request ${session_alias} ${data_path} headers=${headers}
+ Log Received response from openstack ${resp.text}
+ [Return] ${resp} \ No newline at end of file
diff --git a/robot/resources/policy_interface.robot b/robot/resources/policy_interface.robot
new file mode 100644
index 00000000..3bd51f5a
--- /dev/null
+++ b/robot/resources/policy_interface.robot
@@ -0,0 +1,58 @@
+*** Settings ***
+Documentation The main interface for interacting with Policy. It handles low level stuff like managing the http request library and Policy required fields
+Library RequestsClientCert
+Library RequestsLibrary
+Library String
+Library JSONUtils
+Library Collections
+Resource global_properties.robot
+
+*** Variables ***
+${POLICY_HEALTH_CHECK_PATH} /healthcheck
+
+*** Keywords ***
+
+Run Policy Health Check
+ [Documentation] Runs Policy Health check
+ ${auth}= Create List ${GLOBAL_POLICY_USERNAME} ${GLOBAL_POLICY_PASSWORD}
+ Log Creating session ${GLOBAL_POLICY_SERVER_URL}
+ ${session}= Create Session policy ${GLOBAL_POLICY_HEALTHCHECK_URL} auth=${auth}
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json
+ ${resp}= Get Request policy ${POLICY_HEALTH_CHECK_PATH} headers=${headers}
+ Log Received response from policy ${resp.text}
+ Should Be Equal As Strings ${resp.status_code} 200
+ Should Be True ${resp.json()['healthy']}
+ @{ITEMS}= Copy List ${resp.json()['details']}
+ :FOR ${ELEMENT} IN @{ITEMS}
+ \ Should Be Equal As Strings ${ELEMENT['code']} 200
+ \ Should Be True ${ELEMENT['healthy']}
+
+Run Policy Put Request
+ [Documentation] Runs Policy Put request
+ [Arguments] ${data_path} ${data}
+ Log Creating session ${GLOBAL_POLICY_SERVER_URL}
+ ${session}= Create Session policy ${GLOBAL_POLICY_SERVER_URL}
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json Authorization=Basic ${GLOBAL_POLICY_AUTH} ClientAuth=${GLOBAL_POLICY_CLIENTAUTH} Environment=TEST
+ ${resp}= Put Request policy ${data_path} data=${data} headers=${headers}
+ Log Received response from policy ${resp.text}
+ [Return] ${resp}
+
+Run Policy Delete Request
+ [Documentation] Runs Policy Delete request
+ [Arguments] ${data_path} ${data}
+ Log Creating session ${GLOBAL_POLICY_SERVER_URL}
+ ${session}= Create Session policy ${GLOBAL_POLICY_SERVER_URL}
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json Authorization=Basic ${GLOBAL_POLICY_AUTH} ClientAuth=${GLOBAL_POLICY_CLIENTAUTH} Environment=TEST
+ ${resp}= Delete Request policy ${data_path} data=${data} headers=${headers}
+ Log Received response from policy ${resp.text}
+ [Return] ${resp}
+
+Run Policy Get Configs Request
+ [Documentation] Runs Policy Get Configs request
+ [Arguments] ${data_path} ${data}
+ Log Creating session ${GLOBAL_POLICY_SERVER_URL}
+ ${session}= Create Session policy ${GLOBAL_POLICY_SERVER_URL}
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json Authorization=Basic ${GLOBAL_POLICY_AUTH} ClientAuth=${GLOBAL_POLICY_CLIENTAUTH}
+ ${resp}= Post Request policy ${data_path} data=${data} headers=${headers}
+ Log Received response from policy ${resp.text}
+ [Return] ${resp} \ No newline at end of file
diff --git a/robot/resources/portal_interface.robot b/robot/resources/portal_interface.robot
new file mode 100644
index 00000000..7d53b378
--- /dev/null
+++ b/robot/resources/portal_interface.robot
@@ -0,0 +1,28 @@
+*** Settings ***
+Documentation The main interface for interacting with Portal. It handles low level stuff like managing the http request library and Portal required fields
+Library RequestsClientCert
+Library RequestsLibrary
+Library UUID
+
+Resource global_properties.robot
+
+*** Variables ***
+${PORTAL_HEALTH_CHECK_PATH} /ECOMPPORTAL/portalApi/healthCheck
+
+*** Keywords ***
+Run Portal Health Check
+ [Documentation] Runs Portal Health check
+ ${resp}= Run Portal Get Request ${PORTAL_HEALTH_CHECK_PATH}
+ Should Be Equal As Strings ${resp.status_code} 200
+ Should Be Equal As Strings ${resp.json()['statusCode']} 200
+
+Run Portal Get Request
+ [Documentation] Runs Portal Get request
+ [Arguments] ${data_path}
+ ${session}= Create Session portal ${GLOBAL_PORTAL_SERVER}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Get Request portal ${data_path} headers=${headers}
+ Log Received response from portal ${resp.text}
+ [Return] ${resp}
+
diff --git a/robot/resources/sdngc_interface.robot b/robot/resources/sdngc_interface.robot
new file mode 100644
index 00000000..d413b6e0
--- /dev/null
+++ b/robot/resources/sdngc_interface.robot
@@ -0,0 +1,203 @@
+*** Settings ***
+Documentation The main interface for interacting with SDN-GC. It handles low level stuff like managing the http request library and SDN-GC required fields
+Library RequestsLibrary
+Library UUID
+Library OperatingSystem
+Library ExtendedSelenium2Library
+Library Collections
+Library String
+Library StringTemplater
+Resource global_properties.robot
+Resource ../resources/json_templater.robot
+Resource browser_setup.robot
+
+Variables ../assets/service_mappings.py
+
+*** Variables ***
+${PRELOAD_VNF_TOPOLOGY_OPERATION_PATH} /operations/VNF-API:preload-vnf-topology-operation
+${PRELOAD_VNF_CONFIG_PATH} /config/VNF-API:preload-vnfs/vnf-preload-list
+${PRELOAD_VNF_TOPOLOGY_OPERATION_BODY} robot/assets/templates/sdnc/
+${SDNGC_INDEX_PATH} /restconf
+${SDNCGC_HEALTHCHECK_OPERATION_PATH} /operations/SLI-API:healthcheck
+${SDNGC_REST_ENDPOINT} ${GLOBAL_SDNGC_SERVER}:${GLOBAL_SDNGC_REST_PORT}
+${SDNGC_ADMIN_ENDPOINT} ${GLOBAL_SDNGC_SERVER}:${GLOBAL_SDNGC_ADMIN_PORT}
+${SDNGC_ADMIN_SIGNUP_URL} ${SDNGC_ADMIN_ENDPOINT}/signup
+${SDNGC_ADMIN_LOGIN_URL} ${SDNGC_ADMIN_ENDPOINT}/login
+${SDNGC_ADMIN_VNF_PROFILE_URL} ${SDNGC_ADMIN_ENDPOINT}/mobility/getVnfProfile
+
+*** Keywords ***
+Run SDNGC Health Check
+ [Documentation] Runs an SDNGC healthcheck
+ ${resp}= Run SDNGC Post Request ${SDNGC_INDEX PATH}${SDNCGC_HEALTHCHECK_OPERATION_PATH} ${None}
+ Should Be Equal As Strings ${resp.status_code} 200
+ Should Be Equal As Strings ${resp.json()['output']['response-code']} 200
+
+Run SDNGC Get Request
+ [Documentation] Runs an SDNGC get request
+ [Arguments] ${data_path}
+ ${auth}= Create List ${GLOBAL_SDNGC_USERNAME} ${GLOBAL_SDNGC_PASSWORD}
+ Log Creating session ${SDNGC_REST_ENDPOINT}
+ ${session}= Create Session sdngc ${SDNGC_REST_ENDPOINT} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Get Request sdngc ${data_path} headers=${headers}
+ Log Received response from sdngc ${resp.text}
+ [Return] ${resp}
+
+Run SDNGC Put Request
+ [Documentation] Runs an SDNGC put request
+ [Arguments] ${data_path} ${data}
+ ${auth}= Create List ${GLOBAL_SDNGC_USERNAME} ${GLOBAL_SDNGC_PASSWORD}
+ Log Creating session ${SDNGC_REST_ENDPOINT}
+ ${session}= Create Session sdngc ${SDNGC_REST_ENDPOINT} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Put Request sdngc ${data_path} data=${data} headers=${headers}
+ Log Received response from sdngc ${resp.text}
+ [Return] ${resp}
+
+Run SDNGC Post Request
+ [Documentation] Runs an SDNGC post request
+ [Arguments] ${data_path} ${data}
+ ${auth}= Create List ${GLOBAL_SDNGC_USERNAME} ${GLOBAL_SDNGC_PASSWORD}
+ Log Creating session ${SDNGC_REST_ENDPOINT}
+ ${session}= Create Session sdngc ${SDNGC_REST_ENDPOINT} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Post Request sdngc ${data_path} data=${data} headers=${headers}
+ Log Received response from sdngc ${resp.text}
+ [Return] ${resp}
+
+Run SDNGC Delete Request
+ [Documentation] Runs an SDNGC delete request
+ [Arguments] ${data_path}
+ ${auth}= Create List ${GLOBAL_SDNGC_USERNAME} ${GLOBAL_SDNGC_PASSWORD}
+ Log Creating session ${SDNGC_REST_ENDPOINT}
+ ${session}= Create Session sdngc ${SDNGC_REST_ENDPOINT} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Delete Request sdngc ${data_path} headers=${headers}
+ Log Received response from sdngc ${resp.text}
+ [Return] ${resp}
+
+
+Preload Vnf
+ [Arguments] ${service_type_uuid} ${generic_vnf_name} ${generic_vnf_type} ${vf_module_name} ${vf_modules} ${service} ${uuid}
+ ${base_vf_module_type}= Catenate ''
+ ${closedloop_vf_module}= Create Dictionary
+ ${templates}= Get From Dictionary ${GLOBAL_SERVICE_TEMPLATE_MAPPING} ${service}
+ :for ${vf_module} in @{vf_modules}
+ \ ${vf_module_type}= Get From Dictionary ${vf_module} name
+ \ ${dict} Get From Mapping ${templates} ${vf_module}
+ \ ${filename}= Get From Dictionary ${dict} template
+ \ ${base_vf_module_type}= Set Variable If '${dict['isBase']}' == 'true' ${vf_module_type} ${base_vf_module_type}
+ \ ${closedloop_vf_module}= Set Variable If '${dict['isBase']}' == 'false' ${vf_module} ${closedloop_vf_module}
+ \ ${vf_name}= Update Module Name ${dict} ${vf_module_name}
+ \ Preload Vnf Profile ${vf_module_type}
+ \ Preload One Vnf Topology ${service_type_uuid} ${generic_vnf_name} ${generic_vnf_type} ${vf_name} ${vf_module_type} ${service} ${filename} ${uuid}
+ [Return] ${base_vf_module_type} ${closedloop_vf_module}
+
+
+Update Module Name
+ [Arguments] ${dict} ${vf_module_name}
+ Return From Keyword If 'prefix' not in ${dict} ${vf_module_name}
+ Return From Keyword If '${dict['prefix']}' == '' ${vf_module_name}
+ ${name}= Replace String ${vf_module_name} Vfmodule_ ${dict['prefix']}
+ [Return] ${name}
+
+Get From Mapping
+ [Documentation] Retrieve the appropriate prelad template entry for the passed vf_module
+ [Arguments] ${templates} ${vf_module}
+ ${vf_module_name}= Get From DIctionary ${vf_module} name
+ :for ${template} in @{templates}
+ \ Return From Keyword If '${template['name_pattern']}' in '${vf_module_name}' ${template}
+ [Return] None
+
+
+Preload One Vnf Topology
+ [Arguments] ${service_type_uuid} ${generic_vnf_name} ${generic_vnf_type} ${vf_module_name} ${vf_module_type} ${service} ${filename} ${uuid}
+ Return From Keyword If '${filename}' == ''
+ ${data_template}= OperatingSystem.Get File ${PRELOAD_VNF_TOPOLOGY_OPERATION_BODY}/${filename}
+ ${parameters}= Get Template Parameters ${filename} ${uuid}
+ Set To Dictionary ${parameters} generic_vnf_name=${generic_vnf_name} generic_vnf_type=${generic_vnf_type} service_type=${service_type_uuid} vf_module_name=${vf_module_name} vf_module_type=${vf_module_type} uuid=${uuid}
+ ${data}= Fill JSON Template ${data_template} ${parameters}
+ ${put_resp}= Run SDNGC Post Request ${SDNGC_INDEX_PATH}${PRELOAD_VNF_TOPOLOGY_OPERATION_PATH} ${data}
+ Should Be Equal As Strings ${put_resp.json()['output']['response-code']} 200
+ ${get_resp}= Run SDNGC Get Request ${SDNGC_INDEX_PATH}${PRELOAD_VNF_CONFIG_PATH}/${vf_module_name}/${vf_module_type}
+ Should Be Equal As Strings ${get_resp.status_code} 200
+
+Get Template Parameters
+ [Arguments] ${template} ${uuid}
+ ${rest} ${suite}= Split String From Right ${SUITE NAME} . 1
+ ${uuid}= Catenate ${uuid}
+ ${hostid}= Get Substring ${uuid} -4
+ ${ecompnet}= Evaluate ${GLOBAL_BUILD_NUMBER}%255
+ # Initialize the value map with the properties generated from the Robot VM /opt/config folder
+ ${valuemap}= Copy Dictionary ${GLOBAL_VM_PROPERTIES}
+ # update the value map with unique values.
+ Set To Dictionary ${valuemap} uuid=${uuid} hostid=${hostid} ecompnet=${ecompnet}
+ ${parameters}= Create Dictionary
+ ${defaults}= Get From Dictionary ${GLOBAL_PRELOAD_PARAMETERS} defaults
+ Resolve Values Into Dictionary ${valuemap} ${defaults} ${parameters}
+ ${suite_templates}= Get From Dictionary ${GLOBAL_PRELOAD_PARAMETERS} ${suite}
+ ${template}= Get From Dictionary ${suite_templates} ${template}
+ Resolve Values Into Dictionary ${valuemap} ${template} ${parameters}
+ [Return] ${parameters}
+
+Resolve Values Into Dictionary
+ [Arguments] ${valuemap} ${from} ${to}
+ ${keys}= Get Dictionary Keys ${from}
+ :for ${key} in @{keys}
+ \ ${value}= Get From Dictionary ${from} ${key}
+ \ ${value}= Template String ${value} ${valuemap}
+ \ Set To Dictionary ${to} ${key} ${value}
+
+Preload Vnf Profile
+ [Arguments] ${vnf_name}
+ Login To SDNGC Admin GUI
+ Go To ${SDNGC_ADMIN_VNF_PROFILE_URL}
+ Click Button xpath=//button[@data-target='#add_vnf_profile']
+ Input Text xpath=//input[@id='nf_vnf_type'] ${vnf_name}
+ Input Text xpath=//input[@id='nf_availability_zone_count'] 999
+ Input Text xpath=//input[@id='nf_equipment_role'] robot-ete-test
+ Click Button xpath=//button[contains(.,'Submit')]
+ Page Should Contain VNF Profile
+ Input Text xpath=//div[@id='vnf_profile_filter']//input ${vnf_name}
+ Page Should Contain ${vnf_name}
+
+Delete Vnf Profile
+ [Arguments] ${vnf_name}
+ Login To SDNGC Admin GUI
+ Go To ${SDNGC_ADMIN_VNF_PROFILE_URL}
+ Page Should Contain VNF Profile
+ Input Text xpath=//div[@id='vnf_profile_filter']//input ${vnf_name}
+ Page Should Contain ${vnf_name}
+ Click Button xpath=//button[contains(@onclick, '${vnf_name}')]
+ Page Should Contain Are you sure you want to delete VNF_PROFILE
+ Click Button xpath=//button[contains(text(), 'Yes')]
+ Page Should Not Contain ${vnf_name}
+
+Login To SDNGC Admin GUI
+ [Documentation] Login To SDNGC Admin GUI
+ ## Setup Browser is now being managed by the test case
+ ## Setup Browser
+ Go To ${SDNGC_ADMIN_SIGNUP_URL}
+ Maximize Browser Window
+ Set Selenium Speed ${GLOBAL_SELENIUM_DELAY}
+ Set Browser Implicit Wait ${GLOBAL_SELENIUM_BROWSER_IMPLICIT_WAIT}
+ Log Logging in to ${SDNGC_ADMIN_LOGIN_URL}
+ Handle Proxy Warning
+ Title Should Be AdminPortal
+ ${uuid}= Generate UUID
+ ${shortened_uuid}= Evaluate str("${uuid}")[:12]
+ ${email}= Catenate ${shortened_uuid}@robotete.com
+ Input Text xpath=//input[@id='nf_email'] ${email}
+ Input Password xpath=//input[@id='nf_password'] ${shortened_uuid}
+ Click Button xpath=//button[@type='submit']
+ Wait Until Page Contains User created 20s
+ Go To ${SDNGC_ADMIN_LOGIN_URL}
+ Input Text xpath=//input[@id='email'] ${email}
+ Input Password xpath=//input[@id='password'] ${shortened_uuid}
+ Click Button xpath=//button[@type='submit']
+ Title Should Be SDN-C AdminPortal
+ Log Logged in to ${SDNGC_ADMIN_LOGIN_URL} \ No newline at end of file
diff --git a/robot/resources/ssh/files.robot b/robot/resources/ssh/files.robot
new file mode 100644
index 00000000..798ce89e
--- /dev/null
+++ b/robot/resources/ssh/files.robot
@@ -0,0 +1,50 @@
+*** Settings ***
+Documentation Some handy Keywords for accessing log files over SSH. Assumptions are that logs will belong to users other than the currently logged in user and that sudo will be required
+Library OperatingSystem
+Library SSHLibrary
+Library HttpLibrary.HTTP
+Library String
+Library Collections
+
+*** Variables ***
+
+*** Keywords ***
+Open Connection And Log In
+ [Documentation] Open a connection using the passed user and SSH key. Connection alias will be the host name by default.
+ [Arguments] ${HOST} ${user} ${pvt} ${password}= ${alias}=${HOST} ${timeout}=20s
+ Open Connection ${HOST} alias=${alias} timeout=${timeout}
+ Login With Public Key ${user} ${pvt} password=${password} delay=0.5 seconds
+
+Grep Local File
+ [Documentation] Grep the passed file name and return all of the lines that match the passed pattern using the current connection
+ [Arguments] ${pattern} ${fullpath}
+ ${output}= Execute Command grep ${pattern} ${fullpath}
+ [Return] ${output}
+
+ Grep File on Host
+ [Documentation] Grep the passed file name and return all of the lines that match the passed pattern using passed connection alias/host
+ [Arguments] ${host} ${pattern} ${fullpath}
+ Switch Connection ${host}
+ ${output}= Grep Local File ${pattern} ${fullpath}
+ @{lines}= Split To Lines ${output}
+ [Return] @{lines}
+
+Grep File on Hosts
+ [Documentation] Grep the passed file name and return all of the lines that match the passed pattern using passed list of connections
+ [Arguments] ${HOSTS} ${pattern} ${fullpath}
+ &{map}= Create Dictionary
+ :FOR ${HOST} IN @{HOSTS}
+ \ Log ${HOST}
+ \ @{lines}= Grep File on Host ${HOST} ${pattern} ${fullpath}
+ \ &{map}= Create Dictionary ${HOST}=@{lines} &{map}
+ [Return] &{map}
+
+Tail File on Host Until
+ [Documentation] Tail log file into grep which returns file lines containing the grep pattern. Will timeout after timeout= if expected pattern not received.
+ [Arguments] ${host} ${pattern} ${fullpath} ${expected} ${timeout}=60 ${options}=-c -0
+ Switch Connection ${host}
+ ${tailcommand}= Catenate tail ${options} -f ${fullpath} | grep --color=never ${pattern}
+ Write ${tailcommand}
+ ${stdout}= Read Until Regexp ${expected}
+ @{lines}= Split To Lines ${stdout}
+ [Return] @{lines}
diff --git a/robot/resources/ssh/processes.robot b/robot/resources/ssh/processes.robot
new file mode 100644
index 00000000..e9f37318
--- /dev/null
+++ b/robot/resources/ssh/processes.robot
@@ -0,0 +1,74 @@
+*** Settings ***
+Documentation Some handy Keywords for accessing log files over SSH. Assumptions are that logs will belong to users other than the currently logged in user and that sudo will be required
+Library OperatingSystem
+Library SSHLibrary 60 seconds
+Library HttpLibrary.HTTP
+Library String
+Library Collections
+
+*** Variables ***
+
+*** Keywords ***
+
+Get Processes
+ [Documentation] Returns all of the processes on the currently connected host
+ ${output}= Execute Command ps -ef
+ ${map}= Create Process Map ${output}
+ [Return] ${map}
+
+Grep Processes
+ [Documentation] Return the list of processes matching the passed regex
+ [Arguments] ${pattern}
+ ${output}= Execute Command ps -ef|grep "${pattern}"|grep -v grep
+ ${map}= Create Process Map ${output}
+ [Return] ${map}
+
+Create Process Map
+ [Documentation] Extract process pids and process names from ps -ef output
+ [Arguments] ${input}
+ @{lines}= Split To Lines ${input}
+ ${map}= Create Dictionary
+ :for ${line} in @{lines}
+ \ @{parts}= Split String ${line} max_split=7
+ \ ${pid}= Catenate ${parts[1]}
+ \ ${name}= Catenate ${parts[7]}
+ \ Set To Dictionary ${map} ${pid}=${name}
+ [Return] ${map}
+
+
+Wait for Process on Host
+ [Documentation] Wait for the passed process name (regular expression) to be running on the passed host
+ [Arguments] ${process_name} ${host} ${timeout}=600s
+ ${map}= Wait Until Keyword Succeeds ${timeout} 10 sec Is Process On Host ${process_name} ${host}
+ [Return] ${map}
+
+
+Pkill Process on Host
+ [Documentation] Kill the named process(es). Process name must match exactly
+ [Arguments] ${process_name} ${host} ${timeout}=600s
+ Switch Connection ${host}
+ ${output}= Execute Command pkill -9 -e -f ${process_name}
+ [Return] ${output}
+
+Is Process on Host
+ [Documentation] Look for the passed process name (regex) to be running on the passed host. Process name can include regex.
+ [Arguments] ${process_name} ${host}
+ Switch Connection ${host}
+ ${pass} ${map}= Run Keyword and Ignore Error Grep Processes ${process_name}
+ @{pids}= Get Dictionary Keys ${map}
+ ${foundpid}= Catenate ""
+ :for ${pid} in @{pids}
+ \ ${process_cmd}= Get From Dictionary ${map} ${pid}
+ \ ${status} ${value}= Run Keyword And Ignore Error Should Match Regexp ${process_cmd} ${process_name}
+ \ Run Keyword If '${status}' == 'PASS' Set Test Variable ${foundpid} ${pid}
+ Should Not Be Equal ${foundpid} ""
+ [Return] ${map}[${foundpid}]
+
+
+Get Process List on Host
+ [Documentation] Gets the list of all processes on the passed host
+ [Arguments] ${host}
+ Switch Connection ${host}
+ ${map}= Get Processes
+ [Return] ${map}
+ \ No newline at end of file
diff --git a/robot/resources/stack_validation/darkstat_interface.robot b/robot/resources/stack_validation/darkstat_interface.robot
new file mode 100644
index 00000000..3537408a
--- /dev/null
+++ b/robot/resources/stack_validation/darkstat_interface.robot
@@ -0,0 +1,82 @@
+*** Settings ***
+Documentation The main interface for interacting with A&AI. It handles low level stuff like managing the http request library and A&AI required fields
+Library ExtendedSelenium2Library
+Library StringTemplater
+Library UUID
+Library OperatingSystem
+Resource ../global_properties.robot
+Resource ../browser_setup.robot
+
+*** Variables ***
+${SNK_HOSTS_TEMPLATE} http://\${host}:\${port}/hosts/
+${SNK_HOME_TEMPLATE} http://\${host}:\${port}/
+${SNK_PATH}
+${SNK_PORT} 667
+${BYTES_PER_PACKET} 29
+${PACKETS_PER_SECOND_PER_STREAM} 11
+${MONITOR_INTERVAL_IN_SECONDS} 4
+
+*** Keywords ***
+Get Darkstat Bytes In
+ [Documentation] Get bytes received on the passed interface for the given interval
+ [Arguments] ${host} ${interface} ${interval}=${MONITOR_INTERVAL_IN_SECONDS}
+ ${map}= Create Dictionary host=${host} port=${SNK_PORT} path=${SNK_PATH}
+ ${url}= Template String ${SNK_HOSTS_TEMPLATE} ${map}
+ Connect to Darkstat ${host} ${url}
+ Title Should Be Hosts (darkstat3 eth1)
+ ${initial_bytes}= Get Current Bytes In ${interface}
+ Sleep ${interval}
+ Go To ${url}
+ ${new_bytes}= Get Current Bytes In ${interface}
+ ${return_bytes}= Evaluate int(${new_bytes}) - int(${initial_bytes})
+ [Return] ${return_bytes}
+
+Get Darkstat Packets In
+ [Documentation] Get bytes received on the passed interface for the given interval
+ [Arguments] ${host} ${interval}=${MONITOR_INTERVAL_IN_SECONDS}
+ ${map}= Create Dictionary host=${host} port=${SNK_PORT} path=${SNK_PATH}
+ ${url}= Template String ${SNK_HOME_TEMPLATE} ${map}
+ Connect to Darkstat ${host} ${url}
+ Title Should Be Graphs (darkstat3 eth1)
+ ${initial_pkts}= Get Current Packets In
+ Sleep ${interval}
+ Go To ${url}
+ ${new_pkts}= Get Current Packets In
+ ${return_pkts}= Evaluate int(${new_pkts}) - int(${initial_pkts})
+ [Return] ${return_pkts}
+
+
+Connect to Darkstat
+ [Documentation] COnnects to the Darkstat port on passed host
+ [Arguments] ${host} ${url}
+ ## Being managed by the test case
+ ##Setup Browser
+ Go To ${url}
+ Maximize Browser Window
+ Set Selenium Speed ${GLOBAL_SELENIUM_DELAY}
+ Set Browser Implicit Wait ${GLOBAL_SELENIUM_BROWSER_IMPLICIT_WAIT}
+ Log Logging in to ${url}
+ Handle Proxy Warning
+
+
+Get Current Bytes In
+ [Documentation] Retrieves packets input from given host from current Darkstats hosts page
+ [Arguments] ${interface}
+ ${bytes}= Get Text xpath=//tr[td/a[text() = '${interface}']]/td[4]
+ ${bytes}= Evaluate ${bytes.replace(',', '')}
+ [Return] ${bytes}
+
+Get Current Packets In
+ [Documentation] Retrieves packets input from given host from current Darkstats hosts page
+ ${bytes}= Get Text xpath=//span[@id = 'tp']
+ ${bytes}= Evaluate ${bytes.replace(',', '')}
+ [Return] ${bytes}
+
+
+Get Expected Range For Number Of Streams
+ [Documentation] Calculates the expected range of bytes for an interval for the given number of streams
+ [Arguments] ${number_of_streams}
+ ${bytes_per_second}= Evaluate ${BYTES_PER_PACKET}*(${PACKETS_PER_SECOND_PER_STREAM}*${number_of_streams})
+ ${low_bytes}= Evaluate (${MONITOR_INTERVAL_IN_SECONDS}-1)*${bytes_per_second}
+ ${high_bytes}= Evaluate (${MONITOR_INTERVAL_IN_SECONDS}+1)*${bytes_per_second}
+ [Return] ${low_bytes} ${high_bytes} \ No newline at end of file
diff --git a/robot/resources/stack_validation/packet_generator_interface.robot b/robot/resources/stack_validation/packet_generator_interface.robot
new file mode 100644
index 00000000..cc9ba04f
--- /dev/null
+++ b/robot/resources/stack_validation/packet_generator_interface.robot
@@ -0,0 +1,98 @@
+*** Settings ***
+Documentation The main interface for interacting with A&AI. It handles low level stuff like managing the http request library and A&AI required fields
+Library RequestsLibrary
+Library StringTemplater
+Library UUID
+Library OperatingSystem
+Resource ../global_properties.robot
+Resource ../json_templater.robot
+
+*** Variables ***
+${PGN_URL_TEMPLATE} http://\${host}:\${port}
+${PGN_PATH} /restconf/config/sample-plugin:sample-plugin
+${PGN_ENABLE_STREAM_TEMPLATE} robot/assets/templates/vfw_pg_stream_enable.template
+${PGN_ENABLE_STREAMS_TEMPLATE} robot/assets/templates/vfw_pg_streams_enable.template
+
+*** Keywords ***
+Connect To Packet Generator
+ [Documentation] Enables packet generator for the passed stream on the passed host
+ [Arguments] ${host} ${alias}=pgn
+ ${map}= Create Dictionary host=${host} port=${GLOBAL_PACKET_GENERATOR_PORT} path=${PGN_PATH}
+ ${url}= Template String ${PGN_URL_TEMPLATE} ${map}
+ ${auth}= Create List ${GLOBAL_PACKET_GENERATOR_USERNAME} ${GLOBAL_PACKET_GENERATOR_PASSWORD}
+ ${session}= Create Session ${alias} ${url} auth=${auth}
+ [Return] ${session}
+
+Enable Stream
+ [Documentation] Enable a single stream on the passed packet generator host IP
+ [Arguments] ${host} ${stream}=udp1 ${alias}=pgn
+ Connect To Packet Generator ${host} alias=${alias}
+ ${headers}= Create Headers
+ ${data_path}= Catenate ${PGN_PATH}/pg-streams
+ ${map}= Create Dictionary stream=${stream}
+ ${streams}= Fill JSON Template File ${PGN_ENABLE_STREAM_TEMPLATE} ${map}
+ ${streams}= evaluate json.dumps(${streams}) json
+ ${map}= Create Dictionary pgstreams=${streams}
+ ${data}= Fill JSON Template File ${PGN_ENABLE_STREAMS_TEMPLATE} ${map}
+ ${resp}= Put Request ${alias} ${data_path} data=${data} headers=${headers}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp}
+
+Enable Streams
+ [Documentation] Enable <stream_count> number of streams on the passed packet generator host IP
+ [Arguments] ${host} ${stream_count}=5 ${alias}=pgn ${prefix}=fw_udp
+ Connect To Packet Generator ${host} alias=${alias}
+ ${headers}= Create Headers
+ ${data_path}= Catenate ${PGN_PATH}/pg-streams
+ ${streams}= Set Variable
+ ${comma}= Set Variable
+ ${stream_count}= Evaluate ${stream_count}+1
+ :for ${i} in Range 1 ${stream_count}
+ \ ${name}= Catenate ${prefix}${i}
+ \ ${map}= Create Dictionary stream=${name}
+ \ ${one}= Fill JSON Template File ${PGN_ENABLE_STREAM_TEMPLATE} ${map}
+ \ ${one}= evaluate json.dumps(${one}) json
+ \ ${streams}= Set Variable ${streams}${comma}${one}
+ \ ${comma}= Set Variable ,
+ ${map}= Create Dictionary pgstreams=${streams}
+ ${data}= Fill JSON Template File ${PGN_ENABLE_STREAMS_TEMPLATE} ${map}
+ ${resp}= Put Request ${alias} ${data_path} data=${data} headers=${headers}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp}
+
+Disable All Streams
+ [Documentation] Disable all streams on the passed packet generator host IP
+ [Arguments] ${host} ${stream}=udp1 ${alias}=pgn
+ Connect To Packet Generator ${host} alias=${alias}
+ ${headers}= Create Headers
+ ${data_path}= Catenate ${PGN_PATH}/pg-streams
+ ${data}= Catenate {"pg-streams":{"pg-stream": []}}
+ ${resp}= Put Request ${alias} ${data_path} data=${data} headers=${headers}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp}
+
+ Disable Stream
+ [Documentation] Disables packet generator for the passed stream
+ [Arguments] ${host} ${stream}=udp1 ${alias}=pgn
+ ${session}= Connect To Packet Generator ${host} alias=${alias}
+ ${headers}= Create Headers
+ ${data_path}= Catenate ${PGN_PATH}/pg-streams/pg-stream/${stream}
+ ${resp}= Delete Request ${alias} ${data_path} headers=${headers}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp}
+
+Get List Of Enabled Streams
+ [Documentation] Get a list of streams on the passed packet generator host IP
+ [Arguments] ${host} ${alias}=pgn
+ ${session}= Connect To Packet Generator ${host} alias=${alias}
+ ${headers}= Create Headers
+ ${data_path}= Catenate /
+ ${resp}= Get Request ${alias} ${PGN_PATH} headers=${headers}
+ Should Be Equal As Strings ${resp.status_code} 200
+ [Return] ${resp.json()}
+
+
+Create Headers
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ [Return] ${headers} \ No newline at end of file
diff --git a/robot/resources/stack_validation/policy_check_vfw.robot b/robot/resources/stack_validation/policy_check_vfw.robot
new file mode 100644
index 00000000..a1ed3fa3
--- /dev/null
+++ b/robot/resources/stack_validation/policy_check_vfw.robot
@@ -0,0 +1,95 @@
+*** Settings ***
+Documentation Testing openstack.
+Library OperatingSystem
+Library Process
+Library SSHLibrary
+Library RequestsLibrary
+Library JSONUtils
+Library OpenstackLibrary
+Library HEATUtils
+Library Collections
+LIbrary String
+Resource ../../resources/openstack/keystone_interface.robot
+Resource ../../resources/openstack/nova_interface.robot
+Resource ../../resources/openstack/heat_interface.robot
+Resource ../../resources/ssh/files.robot
+Resource ../../resources/ssh/processes.robot
+Resource packet_generator_interface.robot
+Resource darkstat_interface.robot
+Resource validate_common.robot
+
+
+*** Variables ***
+${ASSETS} ${EXECDIR}/robot/assets/
+
+*** Keywords ***
+Policy Check Firewall Stack
+ [Documentation] Identifies the firewall servers in the VFW Stack in the GLOBAL_OPENSTACK_SERVICE_REGION
+ [Arguments] ${stack_name} ${policy_rate}
+ Run Openstack Auth Request auth
+ ${stack_info}= Wait for Stack to Be Deployed auth ${stack_name}
+ ${stack_id}= Get From Dictionary ${stack_info} id
+ ${server_list}= Get Openstack Servers auth
+ Log ${server_list}
+ ${vpg_unprotected_ip}= Get From Dictionary ${stack_info} vpg_private_ip_0
+ ${vsn_protected_ip}= Get From Dictionary ${stack_info} vsn_private_ip_0
+ ${vpg_public_ip}= Get Server Ip ${server_list} ${stack_info} vpg_name_0 network_name=public
+ ${vsn_public_ip}= Get Server Ip ${server_list} ${stack_info} vsn_name_0 network_name=public
+ ${upper_bound}= Evaluate ${policy_rate}*2
+ Wait Until Keyword Succeeds 300s 1s Run VFW Policy Check ${vpg_public_ip} ${policy_rate} ${upper_bound} 1
+
+Run VFW Policy Check
+ [Documentation] Push traffic above upper bound, wait for policy to fix it, push traffic to lower bound, wait for policy to fix it,
+ [Arguments] ${vpg_public_ip} ${policy_rate} ${upper_bound} ${lower_bound}
+ # Force traffic above threshold
+ Check For Policy Enforcement ${vpg_public_ip} ${policy_rate} ${upper_bound}
+ # Force traffic below threshold
+ Check For Policy Enforcement ${vpg_public_ip} ${policy_rate} ${lower_bound}
+
+
+Check For Policy Enforcement
+ [Documentation] Push traffic above upper bound, wait for policy to fix it, push traffic to lower bound, wait for policy to fix it,
+ [Arguments] ${vpg_public_ip} ${policy_rate} ${forced_rate}
+ Enable Streams ${vpg_public_ip} ${forced_rate}
+ Wait Until Keyword Succeeds 20s 5s Test For Expected Rate ${vpg_public_ip} ${forced_rate}
+ Wait Until Keyword Succeeds 280s 5s Test For Expected Rate ${vpg_public_ip} ${policy_rate}
+
+Test For Expected Rate
+ [Documentation] Ge the number of pg-streams from the PGN, and test to see if it is what we expect.
+ [Arguments] ${vpg_public_ip} ${number_of_streams}
+ ${list}= Get List Of Enabled Streams ${vpg_public_ip}
+ ${list}= Evaluate ${list['sample-plugin']}['pg-streams']['pg-stream']
+ Length Should Be ${list} ${number_of_streams}
+
+
+
+Policy Check vLB Stack
+ [Documentation] Identifies the firewall servers in the VFW Stack in the GLOBAL_OPENSTACK_SERVICE_REGION
+ [Arguments] ${stack_name} ${policy_rate}
+ Run Openstack Auth Request auth
+ ${stack_info}= Wait for Stack to Be Deployed auth ${stack_name}
+ ${stack_id}= Get From Dictionary ${stack_info} id
+ ${server_list}= Get Openstack Servers auth
+ ${vlb_public_ip}= Get Server Ip ${server_list} ${stack_info} vlb_name_0 network_name=public
+ ${upper_bound}= Evaluate ${policy_rate}*2
+ Start DNS Traffic ${vlb_public_ip} ${upper_bound}
+
+ # Now wiat for the dnsscaling stack to be deployed
+ ${prefix}= Get DNSScaling Prefix
+ ${dnsscaling}= Replace String Using Regexp ${stack_name} ^Vfmodule_ ${prefix}
+ ${dnsscaling_info}= Wait for Stack to Be Deployed auth ${dnsscaling}
+ # TO DO: Log into vLB and cehck that traffic is flowing to the new DNS
+ [Return] ${dnsscaling}
+
+Get DNSScaling Prefix
+ ${mapping}= Get From Dictionary ${GLOBAL_SERVICE_TEMPLATE_MAPPING} vLB
+ :for ${dict} in @{mapping}
+ \ Return From Keyword If '${dict['isBase']}' == 'false' ${dict['prefix']}
+ [Return] None
+
+
+Start DNS Traffic
+ [Documentation] Run nslookups at rate per second. Run for 10 minutes or until it is called by the terminate process
+ [Arguments] ${vlb_public_ip} ${rate}
+ ${pid}= Start Process ./dnstraffic.sh ${vlb_public_ip} ${rate} ${GLOBAL_DNS_TRAFFIC_DURATION}
+ [Return] ${pid} \ No newline at end of file
diff --git a/robot/resources/stack_validation/validate_common.robot b/robot/resources/stack_validation/validate_common.robot
new file mode 100644
index 00000000..eb7f9f5a
--- /dev/null
+++ b/robot/resources/stack_validation/validate_common.robot
@@ -0,0 +1,51 @@
+*** Settings ***
+Documentation Testing openstack.
+Library OperatingSystem
+Library SSHLibrary
+Library RequestsLibrary
+Library JSONUtils
+Library OpenstackLibrary
+Library HEATUtils
+Library Collections
+Resource ../../resources/openstack/keystone_interface.robot
+Resource ../../resources/openstack/nova_interface.robot
+Resource ../../resources/openstack/heat_interface.robot
+Resource ../../resources/ssh/files.robot
+Resource ../../resources/ssh/processes.robot
+Resource packet_generator_interface.robot
+
+
+*** Variables ***
+${ASSETS} ${EXECDIR}/robot/assets/
+${VFW_STACK_NAME} EcompETE_VFWStack
+${VLB_STACK_NAME} EcompETE_VLBStack
+${DNS_STACK_NAME} EcompETE_DNSStack
+
+*** Keywords ***
+Wait For Server
+ [Documentation] Attempts to login to the passed server info and verify (??). Uses server info to get public ip and locate corresponding provate key file
+ [Arguments] ${server_ip} ${timeout}=300s
+ ${file}= Catenate ${ASSETS}keys/robot_ssh_private_key.pvt
+ Wait Until Keyword Succeeds ${timeout} 5 sec Open Connection And Log In ${server_ip} root ${file}
+ ${lines}= Grep Local File "Accepted publickey" /var/log/auth.log
+ Log ${lines}
+ Should Not Be Empty ${lines}
+
+Get Server Ip
+ [Arguments] ${server_list} ${stack_info} ${key_name} ${network_name}=public
+ ${server_name}= Get From Dictionary ${stack_info} ${key_name}
+ ${server}= Get From Dictionary ${server_list} ${server_name}
+ Log Entering Get Openstack Server Ip
+ ${ip}= Get Openstack Server Ip ${server} network_name=${network_name}
+ Log Returned Get Openstack Server Ip
+ [Return] ${ip}
+
+Find And Reboot The Server
+ [Documentation] Code to reboot the server by teh heat server name parameter value
+ [Arguments] ${stack_info} ${server_list} ${server_name_parameter}
+ ${server_name}= Get From Dictionary ${stack_info} ${server_name_parameter}
+ ${vfw_server}= Get From Dictionary ${server_list} ${server_name}
+ ${vfw_server_id}= Get From Dictionary ${vfw_server} id
+ Reboot Server auth ${vfw_server_id}
+
+
diff --git a/robot/resources/stack_validation/validate_dns_scaling.robot b/robot/resources/stack_validation/validate_dns_scaling.robot
new file mode 100644
index 00000000..f63479ea
--- /dev/null
+++ b/robot/resources/stack_validation/validate_dns_scaling.robot
@@ -0,0 +1,43 @@
+*** Settings ***
+Documentation Testing openstack.
+Library OperatingSystem
+Library SSHLibrary
+Library RequestsLibrary
+Library JSONUtils
+Library OpenstackLibrary
+Library HEATUtils
+Library Collections
+Resource ../../resources/openstack/keystone_interface.robot
+Resource ../../resources/openstack/nova_interface.robot
+Resource ../../resources/openstack/heat_interface.robot
+Resource ../../resources/ssh/files.robot
+Resource ../../resources/ssh/processes.robot
+Resource packet_generator_interface.robot
+Resource validate_common.robot
+
+
+*** Variables ***
+${ASSETS} ${EXECDIR}/robot/assets/
+
+*** Keywords ***
+Validate Dns Scaling Stack
+ [Documentation] Identifies the servers in the STACK_NAME in the GLOBAL_OPENSTACK_SERVICE_REGION
+ [Arguments] ${STACK_NAME}
+ Run Openstack Auth Request auth
+ ${stack_info}= Wait for Stack to Be Deployed auth ${STACK_NAME}
+ ${stack_id}= Get From Dictionary ${stack_info} id
+ ${server_list}= Get Openstack Servers auth
+ Log ${server_list}
+ #${vpg_unprotected_ip}= Get From Dictionary ${stack_info} vpg_private_ip_0
+ #${vsn_protected_ip}= Get From Dictionary ${stack_info} vsn_private_ip_0
+ ${vdns_public_ip}= Get Server Ip ${server_list} ${stack_info} vdns_name_0 network_name=public
+ Wait For Server ${vdns_public_ip}
+ Log Accessed all servers
+ #Wait for vDNS ${vdns_public_ip}
+ Log All server processes up
+
+Wait For vDNS
+ [Documentation] Wait for the defined firewall processes to come up
+ [Arguments] ${ip}
+ Wait for Process on Host java DNSServer ${ip}
+
diff --git a/robot/resources/stack_validation/validate_vfw.robot b/robot/resources/stack_validation/validate_vfw.robot
new file mode 100644
index 00000000..51f29b4a
--- /dev/null
+++ b/robot/resources/stack_validation/validate_vfw.robot
@@ -0,0 +1,94 @@
+*** Settings ***
+Documentation Testing openstack.
+Library OperatingSystem
+Library SSHLibrary
+Library RequestsLibrary
+Library JSONUtils
+Library OpenstackLibrary
+Library HEATUtils
+Library Collections
+Resource ../../resources/openstack/keystone_interface.robot
+Resource ../../resources/openstack/nova_interface.robot
+Resource ../../resources/openstack/heat_interface.robot
+Resource ../../resources/ssh/files.robot
+Resource ../../resources/ssh/processes.robot
+Resource ../appc_interface.robot
+Resource packet_generator_interface.robot
+Resource validate_common.robot
+
+
+*** Variables ***
+${ASSETS} ${EXECDIR}/robot/assets/
+
+*** Keywords ***
+Validate Firewall Stack
+ [Documentation] Identifies the firewall servers in the VFW Stack in the GLOBAL_OPENSTACK_SERVICE_REGION
+ [Arguments] ${STACK_NAME}
+ Run Openstack Auth Request auth
+ ${stack_info}= Wait for Stack to Be Deployed auth ${STACK_NAME}
+ ${stack_id}= Get From Dictionary ${stack_info} id
+ ${server_list}= Get Openstack Servers auth
+
+ ${vpg_unprotected_ip}= Get From Dictionary ${stack_info} vpg_private_ip_0
+ ${vsn_protected_ip}= Get From Dictionary ${stack_info} vsn_private_ip_0
+ ${vpg_name_0}= Get From Dictionary ${stack_info} vpg_name_0
+ ${vfw_public_ip}= Get Server Ip ${server_list} ${stack_info} vfw_name_0 network_name=public
+ ${vpg_public_ip}= Get Server Ip ${server_list} ${stack_info} vpg_name_0 network_name=public
+ ${vsn_public_ip}= Get Server Ip ${server_list} ${stack_info} vsn_name_0 network_name=public
+
+ Wait For Server ${vfw_public_ip}
+ Wait For Server ${vpg_public_ip}
+ Wait For Server ${vsn_public_ip}
+ Log Accessed all servers
+ Wait For Firewall ${vfw_public_ip}
+ Wait For Packet Generator ${vpg_public_ip}
+ Wait For Packet Sink ${vsn_public_ip}
+ Log All server processes up
+ ${appc}= Create Mount Point In APPC ${vpg_name_0} ${vpg_public_ip}
+
+ # Following hack was implemented because the stack doesn't always come up clean
+ # It was found that rebooting the servers at this point did not improve the
+ # chances of the packets flowing to the SNK
+ #${status} ${data}= Run Keyword And Ignore Error Wait For Packets ${vpg_public_ip} ${vpg_unprotected_ip} ${vsn_protected_ip} ${vsn_public_ip}
+ #Return From Keyword if '${status}' == 'PASS'
+ #Close All Connections
+ #Find And Reboot The Server ${stack_info} ${server_list} vfw_name_0
+ #Find And Reboot The Server ${stack_info} ${server_list} vpg_name_0
+ #Find And Reboot The Server ${stack_info} ${server_list} vsn_name_0
+ ## Gives some time for servers to shutdown
+ #Sleep 10s
+ #Wait For Server ${vfw_public_ip}
+ #Wait For Server ${vpg_public_ip}
+ #Wait For Server ${vsn_public_ip}
+
+ Wait For Packets ${vpg_public_ip} ${vpg_unprotected_ip} ${vsn_protected_ip} ${vsn_public_ip}
+
+Wait For Packets
+ [Documentation] Final vfw validation that packets are flowing from the pgn VM to the snk VM
+ [Arguments] ${vpg_public_ip} ${vpg_unprotected_ip} ${vsn_protected_ip} ${vsn_public_ip}
+ ${resp}= Enable Stream ${vpg_public_ip}
+ Should Be Equal As Strings ${resp.status_code} 200
+ ${syslog_message}= Catenate UDP: short packet: From ${vpg_unprotected_ip}:.* to ${vsn_protected_ip}:.*
+ Tail File on Host Until ${vsn_public_ip} UDP: /var/log/syslog ${syslog_message} timeout=120s
+ Disable All Streams ${vpg_public_ip}
+
+
+Wait For Firewall
+ [Documentation] Wait for the defined firewall processes to come up
+ [Arguments] ${ip}
+ Wait for Process on Host ./vpp_measurement_reporter ${ip}
+ Wait for Process on Host vpp -c /etc/vpp/startup.conf ${ip}
+
+Wait For Packet Generator
+ [Documentation] Wait for the defined packet generator processes to come up
+ [Arguments] ${ip}
+ Wait for Process on Host vpp -c /etc/vpp/startup.conf ${ip}
+ Wait for Process on Host java .* -jar /opt/honeycomb/Honeycomb/vpp-integration/minimal-distribution/target/vpp-integration-distribution-1.16.9-hc/vpp-integration-distribution-1.16.9/vpp-integration-distribution-1.16.9.jar ${ip}
+ Wait Until Keyword Succeeds 180s 5s Tail File on Host Until ${ip} Honeycomb /var/log/honeycomb/honeycomb.log - Honeycomb initialized options=-c +0 timeout=120s
+ Run Keyword And Ignore Error Wait for Process on Host run_traffic_fw_demo.sh ${ip} timeout=60s
+ Pkill Process On Host "/bin/bash ./run_traffic_fw_demo.sh" ${ip}
+
+Wait For Packet Sink
+ [Documentation] Wait for the defined packet sink processes to come up
+ [Arguments] ${ip}
+ Log noting to check on ${ip}
diff --git a/robot/resources/stack_validation/validate_vlb.robot b/robot/resources/stack_validation/validate_vlb.robot
new file mode 100644
index 00000000..9af768fa
--- /dev/null
+++ b/robot/resources/stack_validation/validate_vlb.robot
@@ -0,0 +1,60 @@
+*** Settings ***
+Documentation Testing openstack.
+Library String
+Library DNSUtils
+Library Collections
+Library SSHLibrary
+Resource validate_common.robot
+
+
+*** Variables ***
+${ASSETS} ${EXECDIR}/robot/assets/
+
+*** Keywords ***
+Validate vLB Stack
+ [Documentation] Identifies the LB and DNS servers in the vLB stack in the GLOBAL_OPENSTACK_SERVICE_REGION
+ [Arguments] ${stack_name}
+ Run Openstack Auth Request auth
+ ${stack_info}= Wait for Stack to Be Deployed auth ${stack_name}
+ ${stack_id}= Get From Dictionary ${stack_info} id
+ ${server_list}= Get Openstack Servers auth
+ Log Returned from Get Openstack Servers
+
+ #${vpg_unprotected_ip}= Get From Dictionary ${stack_info} vpg_private_ip_0
+ #${vsn_protected_ip}= Get From Dictionary ${stack_info} vsn_private_ip_0
+ ${vlb_public_ip}= Get Server Ip ${server_list} ${stack_info} vlb_name_0 network_name=public
+ ##${vdns_public_ip}= Get Server Ip ${server_list} ${stack_info} vdns_name_0 network_name=public
+
+# SCript hands right here. Trying to figure out what it is....
+ #Wait For Server ${vlb_public_ip}
+ #Wait For Server ${vdns_public_ip}
+ #Log Accessed all servers
+
+
+ # Following is a hack because the stack doesn't always come up clean
+ # Give some time for VLB server to reconfigure the network so our script doesn't hang
+ Log Waiting for ${vlb_public_ip} to reconfigure
+ Sleep 180s
+ #${status} ${data}= Run Keyword And Ignore Error Wait For vLB ${vlb_public_ip}
+ #Return From Keyword if '${status}' == 'PASS'
+ #Close All Connections
+ #Find And Reboot The Server ${stack_info} ${server_list} vlb_name_0
+
+ # Give some time for VLB server to reconfigure the network so our script doesn't hang
+ #Log Waiting for ${vlb_public_ip} to reconfigure
+ #Sleep 180s
+ Wait For vLB ${vlb_public_ip}
+ Log All server processes up
+
+Wait For vLB
+ [Documentation] Wait for the VLB to be functioning as a DNS
+ [Arguments] ${ip}
+ Wait Until Keyword Succeeds 300s 10s DNSTest ${ip}
+ Log Succeeded
+
+DNSTest
+ [Documentation] Wait for the defined VLoadBalancer to process nslookup
+ [Arguments] ${ip}
+ Log Looking up ${ip}
+ #${returned_ip}= Dns Request host1.dnsdemo.openecomp.org ${ip}
+ #Should Contain '${returned_ip}' .
diff --git a/robot/resources/stack_validation/validate_vvg.robot b/robot/resources/stack_validation/validate_vvg.robot
new file mode 100644
index 00000000..75340a47
--- /dev/null
+++ b/robot/resources/stack_validation/validate_vvg.robot
@@ -0,0 +1,17 @@
+*** Settings ***
+Documentation Testing openstack.
+Library String
+Library DNSUtils
+Library Collections
+Resource validate_common.robot
+
+
+*** Variables ***
+${ASSETS} ${EXECDIR}/robot/assets/
+
+*** Keywords ***
+Validate vVG Stack
+ [Documentation] Identifies the LB and DNS servers in the vLB stack in the GLOBAL_OPENSTACK_SERVICE_REGION
+ [Arguments] ${stack_name}
+ Log All server processes up
+
diff --git a/robot/resources/test_templates/closedloop_test_template.robot b/robot/resources/test_templates/closedloop_test_template.robot
new file mode 100644
index 00000000..67bf0cb1
--- /dev/null
+++ b/robot/resources/test_templates/closedloop_test_template.robot
@@ -0,0 +1,210 @@
+*** Settings ***
+Documentation Policy Closed Loop Test cases
+
+Resource ../policy_interface.robot
+Resource ../stack_validation/policy_check_vfw.robot
+Resource vnf_orchestration_test_template.robot
+Library String
+Library HttpLibrary.HTTP
+LIbrary Process
+
+*** Variables ***
+${RESOURCE_PATH_CREATE} /PyPDPServer/createPolicy
+${RESOURCE_PATH_CREATE_PUSH} /PyPDPServer/pushPolicy
+${RESOURCE_PATH_CREATE_DELETE} /PyPDPServer/deletePolicy
+${RESOURCE_PATH_GET_CONFIG} /PyPDPServer/getConfig
+${CREATE_CONFIG_TEMPLATE} robot/assets/templates/policy/closedloop_configpolicy.template
+${CREATE_OPS_TEMPLATE} robot/assets/templates/policy/closedloop_opspolicy.template
+${PUSH_POLICY_TEMPLATE} robot/assets/templates/policy/closedloop_pushpolicy.template
+${DEL_POLICY_TEMPLATE} robot/assets/templates/policy/closedloop_deletepolicy.template
+${GECONFIG_VFW_TEMPLATE} robot/assets/templates/policy/closedloop_getconfigpolicy.template
+
+# 'Normal' number of pg streams that will be set when policy is triggered
+${VFWPOLICYRATE} 5
+
+# Max nslookup requests per second before triggering event.
+${VLBPOLICYRATE} 20
+
+${CONFIG_POLICY_NAME} vFirewall
+${CONFIG_POLICY_TYPE} Unknown
+${OPS_POLICY_NAME}
+${OPS_POLICY_TYPE} BRMS_PARAM
+
+# VFW low threshold
+${Expected_Severity_1} MAJOR
+${Expected_Threshold_1} 300
+${Expected_Direction_1} LESS_OR_EQUAL
+
+# VFW high threshold
+${Expected_Severity_2} CRITICAL
+${Expected_Threshold_2} 700
+${Expected_Direction_2} GREATER_OR_EQUAL
+
+# VDNS High threshold
+${Expected_Severity_3} MAJOR
+${Expected_Threshold_3} 200
+${Expected_Direction_3} GREATER_OR_EQUAL
+
+${DNSSCALINGSTACK}
+
+*** Keywords ***
+VFW Policy
+ Log Suite name ${SUITE NAME} ${TEST NAME} ${PREV TEST NAME}
+ Initialize VFW Policy
+ ${stackname}= Orchestrate VNF vFW closedloop
+ Policy Check Firewall Stack ${stackname} ${VFWPOLICYRATE}
+
+
+VDNS Policy
+ Initialize VDNS Policy
+ ${stackname}= Orchestrate VNF vDNS closedloop
+ ${dnsscaling}= Policy Check vLB Stack ${stackname} ${VLBPOLICYRATE}
+ Set Test Variable ${DNSSCALINGSTACK} ${dnsscaling}
+
+Initialize VFW Policy
+# Create Config Policy
+# Push Config Policy ${CONFIG_POLICY_NAME} ${CONFIG_POLICY_TYPE}
+# Create Ops Policy
+# Push Ops Policy ${OPS_POLICY_NAME} ${OPS_POLICY_TYPE}
+ Get Configs VFW Policy
+
+Initialize VDNS Policy
+ Get Configs VDNS Policy
+
+Get Configs VFW Policy
+ [Documentation] Get Config Policy for VFW
+ ${getconfigpolicy}= Catenate .*${CONFIG_POLICY_NAME}*
+ ${configpolicy_name}= Create Dictionary config_policy_name=${getconfigpolicy}
+ ${output} = Fill JSON Template File ${GECONFIG_VFW_TEMPLATE} ${configpolicy_name}
+ ${get_resp} = Run Policy Get Configs Request ${RESOURCE_PATH_GET_CONFIG} ${output}
+ Should Be Equal As Strings ${get_resp.status_code} 200
+
+ ${json}= Parse Json ${get_resp.content}
+ ${config}= Parse Json ${json[0]["config"]}
+
+ # Extract object1 from Array
+ ${severity}= Get Variable Value ${config["content"]["thresholds"][0]["severity"]}
+ Should Be Equal ${severity} ${Expected_Severity_1}
+ ${Thresold_Value}= Get Variable Value ${config["content"]["thresholds"][0]["thresholdValue"]}
+ Should Be Equal ${Thresold_Value} ${Expected_Threshold_1}
+ ${direction}= Get Variable Value ${config["content"]["thresholds"][0]["direction"]}
+ Should Be Equal ${direction} ${Expected_Direction_1}
+
+ # Extract object2 from Array
+ ${severity_1}= Get Variable Value ${config["content"]["thresholds"][1]["severity"]}
+ Should Be Equal ${severity_1} ${Expected_Severity_2}
+ ${Thresold_Value_1}= Get Variable Value ${config["content"]["thresholds"][1]["thresholdValue"]}
+ Should Be Equal ${Thresold_Value_1} ${Expected_Threshold_2}
+ ${direction_1}= Get Variable Value ${config["content"]["thresholds"][1]["direction"]}
+ Should Be Equal ${direction_1} ${Expected_Direction_2}
+
+Get Configs VDNS Policy
+ [Documentation] Get Config Policy for VDNS
+ ${getconfigpolicy}= Catenate .*vLoadBalancer*
+ ${configpolicy_name}= Create Dictionary config_policy_name=${getconfigpolicy}
+ ${output} = Fill JSON Template File ${GECONFIG_VFW_TEMPLATE} ${configpolicy_name}
+ ${get_resp} = Run Policy Get Configs Request ${RESOURCE_PATH_GET_CONFIG} ${output}
+ Should Be Equal As Strings ${get_resp.status_code} 200
+ ${json}= Parse Json ${get_resp.content}
+ ${config}= Parse Json ${json[0]["config"]}
+
+ # Extract object1 from Array
+ ${severity}= Get Variable Value ${config["content"]["thresholds"][0]["severity"]}
+ Should Be Equal ${severity} ${Expected_Severity_3}
+ ${Thresold_Value}= Get Variable Value ${config["content"]["thresholds"][0]["thresholdValue"]}
+ Should Be Equal ${Thresold_Value} ${Expected_Threshold_3}
+ ${direction}= Get Variable Value ${config["content"]["thresholds"][0]["direction"]}
+ Should Be Equal ${direction} ${Expected_Direction_3}
+
+Teardown Closed Loop
+ [Documentation] Tear down a closed loop test case
+ Terminate All Processes
+ Teardown VDNS
+ Teardown VNF
+ #Clean A&AI Inventory VFWPolicy_Customer Rackspece vFW
+# Delete Config Policy ${CONFIG_POLICY_NAME}
+# Delete Ops Policy ${OPS_POLICY_NAME}
+ Log Teardown complete
+
+Teardown VDNS
+ Return From Keyword if '${DNSSCALINGSTACK}' == ''
+ # This needs to be done via VID
+ Teardown Stack ${DNSSCALINGSTACK}
+
+Create Config Policy
+ [Documentation] Create Config Policy
+ ${randompolicyname} = Create Policy Name
+ ${policyname1}= Catenate com.${randompolicyname}
+ ${CONFIG_POLICY_NAME}= Set Test Variable ${policyname1}
+ ${configpolicy}= Create Dictionary policy_name=${CONFIG_POLICY_NAME}
+ ${output} = Fill JSON Template File ${CREATE_CONFIG_TEMPLATE} ${configpolicy}
+ ${put_resp} = Run Policy Put Request ${RESOURCE_PATH_CREATE} ${output}
+ Should Be Equal As Strings ${put_resp.status_code} 200
+
+ Create Policy Name
+ [Documentation] Generate Policy Name
+ [Arguments] ${prefix}=ETE_
+ ${random}= Generate Random String 15 [LOWER][NUMBERS]
+ ${policyname}= Catenate ${prefix}${random}
+ [Return] ${policyname}
+
+Create Ops Policy
+ [Documentation] Create Opertional Policy
+ ${randompolicyname} = Create Policy Name
+ ${policyname1}= Catenate com.${randompolicyname}
+ ${OPS_POLICY_NAME}= Set Test Variable ${policyname1}
+ ${dict}= Create Dictionary policy_name=${OPS_POLICY_NAME}
+ #${NEWPOLICY1}= Create Dictionary policy_name=com.${OPS_POLICY_NAME}
+ ${output} = Fill JSON Template File ${CREATE_OPS_TEMPLATE} ${dict}
+ ${put_resp} = Run Policy Put Request ${RESOURCE_PATH_CREATE} ${output}
+ Log ${put_resp}
+ Should Be Equal As Strings ${put_resp.status_code} 200
+
+Push Ops Policy
+ [Documentation] Push Ops Policy
+ [Arguments] ${policyname} ${policytype}
+ ${dict}= Create Dictionary policy_name=${policyname} policy_type=${policytype}
+ ${output} = Fill JSON Template ${PUSH_POLICY_TEMPLATE} ${dict}
+ ${put_resp} = Run Policy Put Request ${RESOURCE_PATH_CREATE_PUSH} ${output}
+ Should Be Equal As Strings ${put_resp.status_code} 200
+
+Push Config Policy
+ [Documentation] Push Config Policy
+ [Arguments] ${policyname} ${policytype}
+ ${dict}= Create Dictionary policy_name=${policyname} policy_type=${policytype}
+ ${output} = Fill JSON Template ${PUSH_POLICY_TEMPLATE} ${dict}
+ ${put_resp} = Run Policy Put Request ${RESOURCE_PATH_CREATE_PUSH} ${output}
+ Should Be Equal As Strings ${put_resp.status_code} 200
+
+
+Delete Config Policy
+ [Documentation] Delete Config Policy
+ [Arguments] ${policy_name}
+ ${policyname3}= Catenate com.Config_BRMS_Param_${policyname}.1.xml
+ ${dict}= Create Dictionary policy_name=${policyname3}
+ ${output} = Fill JSON Template ${DEL_POLICY_TEMPLATE} ${dict}
+ ${put_resp} = Run Policy Delete Request ${RESOURCE_PATH_CREATE_DELETE} ${output}
+ Should Be Equal As Strings ${put_resp.status_code} 200
+
+Delete Ops Policy
+ [Documentation] Delete Ops Policy
+ [Arguments] ${policy_name}
+ ${policyname3}= Catenate com.Config_MS_com.vFirewall.1.xml
+ ${dict}= Create Dictionary policy_name=${policyname3}
+ ${output} = Fill JSON Template ${DEL_POLICY_TEMPLATE} ${dict}
+ ${put_resp} = Run Policy Delete Request ${RESOURCE_PATH_CREATE_DELETE} ${output}
+ Should Be Equal As Strings ${put_resp.status_code} 200
+
+Orchestrate VNF vFW closedloop
+ [Documentation] VNF Orchestration for vFW
+ Log VNF Orchestration flow TEST NAME=${TEST NAME}
+ Setup Orchestrate VNF ${GLOBAL_AAI_CLOUD_OWNER} ${GLOBAL_OPENSTACK_SERVICE_REGION} SharedNode OwnerType v1 CloudZone
+ ${stack_name} ${service}= Orchestrate VNF ETE_CLP vFW vFW ${GLOBAL_OPENSTACK_SERVICE_REGION} ${TENANT_NAME}
+ [Return] ${stack_name}
+
+ Orchestrate VNF vDNS closedloop
+ [Documentation] VNF Orchestration for vLB
+ Log VNF Orchestration flow TEST NAME=${TEST NAME}
+ Setup Orchestrate VNF ${GLOBAL_AAI_CLOUD_OWNER} ${GLOBAL_OPENSTACK_SERVICE_REGION} SharedNode OwnerType v1 CloudZone
+ ${stack_name} ${service}= Orchestrate VNF ETE_CLP vLB vLB ${GLOBAL_OPENSTACK_SERVICE_REGION} ${TENANT_NAME}
+ [Return] ${stack_name}
diff --git a/robot/resources/test_templates/model_test_template.robot b/robot/resources/test_templates/model_test_template.robot
new file mode 100644
index 00000000..263c5929
--- /dev/null
+++ b/robot/resources/test_templates/model_test_template.robot
@@ -0,0 +1,57 @@
+*** Settings ***
+Documentation The main interface for interacting with ASDC. It handles low level stuff like managing the http request library and DCAE required fields
+Library OperatingSystem
+Library ArchiveLibrary
+Library Collections
+Resource ../asdc_interface.robot
+
+Variables ../../assets/service_mappings.py
+
+*** Variables ***
+${ASDC_BASE_PATH} /sdc1
+${ASDC_DESIGNER_PATH} /proxy-designer1#/dashboard
+${ASDC_ASSETS_DIRECTORY} robot/assets/asdc
+${VFW_DIRECTORY} base_vfw
+${VLB_DIRECTORY} base_vlb
+${VVG_DIRECTORY} base_vvg
+${SCALING_DIRECTORY} dns_scaling
+${ASDC_ZIP_DIRECTORY} ${ASDC_ASSETS_DIRECTORY}/temp
+
+${CATALOG_RESOURCE_IDS}
+${CATALOG_SERVICE_ID}
+
+*** Keywords ***
+
+Model Distribution For Directory
+ [Arguments] ${service}
+ ${directory_list}= Get From Dictionary ${GLOBAL_SERVICE_FOLDER_MAPPING} ${service}
+ ${ziplist}= Create List
+ :for ${directory} in @{directory_list}
+ \ ${zip}= Catenate ${ASDC_ZIP_DIRECTORY}/${directory}.zip
+ \ ${folder}= Catenate ${ASDC_ASSETS_DIRECTORY}/${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}
+ 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}
+
+
+
+
+Teardown Model Distribution
+ [Documentation] Clean up at the end of the test
+ Log ${CATALOG_SERVICE_ID} ${CATALOG_RESOURCE_IDS}
+ Teardown Models ${CATALOG_SERVICE_ID} ${CATALOG_RESOURCE_IDS}
+
+Teardown Models
+ [Documentation] Clean up at the end of the test
+ [Arguments] ${catalog_service_id} ${catalog_resource_ids}
+ Return From Keyword If '${catalog_service_id}' == ''
+ :for ${catalog_resource_id} in @{catalog_resource_ids}
+ \ ${resourece_json}= Mark ASDC Catalog Resource Inactive ${catalog_resource_id}
+ ${service_json}= Mark ASDC Catalog Service Inactive ${catalog_service_id}
+ ${services_json}= Delete Inactive ASDC Catalog Services
+ ${resources_json}= Delete Inactive ASDC Catalog Resources
+ \ No newline at end of file
diff --git a/robot/resources/test_templates/vnf_orchestration_test_template.robot b/robot/resources/test_templates/vnf_orchestration_test_template.robot
new file mode 100644
index 00000000..00f15cf8
--- /dev/null
+++ b/robot/resources/test_templates/vnf_orchestration_test_template.robot
@@ -0,0 +1,183 @@
+*** Settings ***
+Documentation This test template encapsulates the VNF Orchestration use case.
+
+Resource ../vid/create_service_instance.robot
+Resource ../vid/vid_interface.robot
+Resource ../aai/service_instance.robot
+Resource ../vid/create_vid_vnf.robot
+Resource ../sdngc_interface.robot
+Resource model_test_template.robot
+
+Resource ../aai/create_customer.robot
+Resource ../aai/create_tenant.robot
+Resource ../aai/create_service.robot
+Resource ../openstack/neutron_interface.robot
+Resource ../heatbridge.robot
+
+
+Library OpenstackLibrary
+Library ExtendedSelenium2Library
+Library UUID
+Library Collections
+
+
+
+*** Variables ***
+
+${TENANT_NAME}
+${TENANT_ID}
+${REGIONS}
+${CUSTOMER_NAME}
+${STACK_NAME}
+${SERVICE}
+${VVG_SERVER_ID}
+
+*** Keywords ***
+
+Orchestrate VNF
+ [Arguments] ${customer_name} ${service} ${product_family} ${lcp_region} ${tenant}
+ ${uuid}= Generate UUID
+ Set Test Variable ${CUSTOMER_NAME} ${customer_name}_${uuid}
+ Set Test Variable ${SERVICE} ${service}
+ ${vnf_name}= Catenate Vnf_Ete_Name${uuid}
+ ${service_name}= Catenate Service_Ete_Name${uuid}
+ ${service_type}= Set Variable ${service}
+ ${vf_module_name}= Catenate Vfmodule_Ete_Name${uuid}
+ ${service_model_type} ${vnf_type} ${vf_modules} = Model Distribution For Directory ${service}
+ ## MSO polling is 60 second intervals
+ Sleep 70s
+ Run Keyword If '${service}' == 'vVG' Create VVG Server ${uuid}
+ Create Customer For VNF ${CUSTOMER_NAME} ${CUSTOMER_NAME} INFRA ${service_type} ${GLOBAL_AAI_CLOUD_OWNER} ${GLOBAL_OPENSTACK_SERVICE_REGION}
+ Setup Browser
+ Login To VID GUI
+ ${service_instance_id}= Create VID Service Instance ${customer_name} ${service_model_type} ${service} ${service_name}
+ 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}
+ ${vf_module_id}= Create VID VNF module ${service_instance_id} ${vf_module_name} ${lcp_region} ${tenant} ${vf_module_type}
+ ${generic_vnf}= Validate Generic VNF ${vnf_name} ${vnf_type} ${service_instance_id}
+ VLB Closed Loop Hack ${service} ${generic_vnf} ${closedloop_vf_module}
+ Set Test Variable ${STACK_NAME} ${vf_module_name}
+ 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
+ [Documentation] VNF Orchestration Test setup....
+ ... Create Tenant if not exists, Create Customer, Create Service and related relationships
+ [Arguments] ${customer_name} ${customer_id} ${customer_type} ${service_type} ${cloud_owner} ${cloud_region_id}
+ ${resp}= Create Customer ${customer_name} ${customer_id} ${customer_type} ${service_type} ${cloud_owner} ${cloud_region_id} ${TENANT_ID}
+ Should Be Equal As Strings ${resp} 201
+ 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
+ [Arguments] ${cloud_owner} ${cloud_region_id} ${cloud_type} ${owner_defined_type} ${cloud_region_version} ${cloud_zone}
+ Initialize Tenant From Openstack
+ Initialize Regions From Openstack
+ :FOR ${region} IN @{REGIONS}
+ \ Inventory Tenant If Not Exists ${cloud_owner} ${region} ${cloud_type} ${owner_defined_type} ${cloud_region_version} ${cloud_zone} ${TENANT_NAME} ${TENANT_ID}
+ Log Orchestrate VNF setup complete
+
+Initialize Tenant From Openstack
+ 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}
+
+Initialize Regions From Openstack
+ Run Openstack Auth Request auth
+ ${regs}= Get Openstack Regions auth
+ Set Suite Variable ${REGIONS} ${regs}
+
+Create VVG Server
+ [Arguments] ${uuid}
+ Run Openstack Auth Request auth
+ ${vvg_server_name}= Catenate vVG_${uuid}
+ ${server}= Add Server For Image Name auth ${vvg_server_name} ${GLOBAL_VVGSERVER_IMAGE} ${GLOBAL_VVGSERVER_FLAVOR}
+ ${server}= Get From Dictionary ${server} server
+ ${server_id}= Get From Dictionary ${server} id
+ Set Test Variable ${VVG_SERVER_ID} ${server_id}
+ ${vvg_params}= Get VVG Preload Parameters
+ Set To Dictionary ${vvg_params} nova_instance ${server_id}
+ Wait for Server to Be Active auth ${server_id}
+
+Get VVG Preload Parameters
+ ${test_dict}= Get From Dictionary ${GLOBAL_PRELOAD_PARAMETERS} Vnf-Orchestration
+ ${vvg_params} Get From Dictionary ${test_dict} vvg_preload.template
+ [Return] ${vvg_params}
+
+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
+ Run Keyword If '${TEST STATUS}' == 'PASS' Teardown Model Distribution
+ Log Teardown VNF not completely implemented
+
+Teardown VVG Server
+ Return From Keyword if '${VVG_SERVER_ID}' == ''
+ Delete Server auth ${VVG_SERVER_ID}
+ Wait for Server To Be Deleted auth ${VVG_SERVER_ID}
+ ${vvg_params}= Get VVG Preload Parameters
+ Remove from Dictionary ${vvg_params} nova_instance
+ 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
+ [Arguments] ${stack}
+ Run Openstack Auth Request auth
+ ${stack_info}= Get Stack Details auth ${stack}
+ Log ${stack_info}
+ ${stack_id}= Get From Dictionary ${stack_info} id
+ ${key_pair_status} ${keypair_name}= Run Keyword And Ignore Error Get From Dictionary ${stack_info} key_name
+ 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
+
+
+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}
+
diff --git a/robot/resources/vid/create_service_instance.robot b/robot/resources/vid/create_service_instance.robot
new file mode 100644
index 00000000..2ea01ce2
--- /dev/null
+++ b/robot/resources/vid/create_service_instance.robot
@@ -0,0 +1,57 @@
+*** Settings ***
+Documentation Creates VID Service Instance
+...
+... Creates VID Service Instance
+
+Library ExtendedSelenium2Library
+Library UUID
+Library String
+Library DateTime
+
+Resource ../mso_interface.robot
+Resource vid_interface.robot
+
+*** Keywords ***
+Create VID Service Instance
+ [Documentation] Creates a service instance using VID
+ [Arguments] ${customer_name} ${service_model_type} ${service_type} ${service_name}
+ Go To VID HOME
+ Click Element partial link=Browse SDC Service
+ Page Should Contain Element xpath=//div/h1[text() = 'Browse SDC Service Models']
+ Wait Until Page Contains Element xpath=//button[text() = 'Deploy'] 240s
+ Input Text When Enabled //input[@ng-model='searchString'] ${service_model_type}
+ Wait Until Element Is Visible xpath=//tr[td/span/text() = '${service_model_type}']/td/button[contains(text(),'Deploy')] 300000
+ Press Key xpath=//tr[td/span/text() = '${service_model_type}']/td/button[text() = 'Deploy' and not(@disabled)] \\13
+ ${uuid}= Generate UUID
+ Wait Until Page Contains Element xpath=//input[@parameter-name='Instance Name'] 120s
+ Wait Until Element Is Visible xpath=//input[@parameter-name='Instance Name'] 120s
+ Xpath Should Match X Times //input[@parameter-name='Instance Name'] 1
+ Input Text When Enabled //input[@parameter-name='Instance Name'] ${service_name}
+ Select From List When Enabled //select[@prompt='Select Subscriber Name'] ${customer_name}
+ Select From List WHen Enabled //select[@prompt='Select Service Type'] ${service_type}
+ Click On Button When Enabled //div[@class = 'buttonRow']/button[text() = 'Confirm']
+ Wait Until Element Contains xpath=//div[@ng-controller= 'msoCommitController']/pre[@class = 'log ng-binding'] requestId timeout=120s
+ ${response text}= Get Text xpath=//div[@ng-controller= 'msoCommitController']/pre[@class = 'log ng-binding']
+ Click On Button When Enabled //div[@class = 'buttonRow']/button[text() = 'Close']
+ ${request_id}= Parse Request Id ${response text}
+ ${service_instance_id}= Parse Instance Id ${response text}
+ Poll MSO Get Request ${GLOBAL_MSO_STATUS_PATH}${request_id} COMPLETE
+ [return] ${service_instance_id}
+
+
+Delete Service Instance By GUI
+ [Arguments] ${service_instance_id} ${customer_name}
+ Click On Element When Visible xpath=//a/span[@class='glyphicon glyphicon-remove']
+ Click On Button When Visible xpath=//div[@class='buttonRow']/button[@ngx-enabled='true']
+ Wait Until Element Contains xpath=//div[@ng-controller='deletionDialogController']//div[@ng-controller= 'msoCommitController']/pre[@class = 'log ng-binding'] requestId timeout=120s
+ ${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}
+ Poll MSO Get Request ${GLOBAL_MSO_STATUS_PATH}${request_id} COMPLETE
+
+
+Search Service Instance
+ [Arguments] ${service_instance_id} ${customer_name}
+ Click Link xpath=//div[@heading = 'Search for Existing Service Instances']/a
+ Input Text When Enabled //input[@name='selectedServiceInstance'] ${service_instance_id}
+ Click On Button When Enabled //button[text() = 'Submit']
+ \ No newline at end of file
diff --git a/robot/resources/vid/create_vid_vnf.robot b/robot/resources/vid/create_vid_vnf.robot
new file mode 100644
index 00000000..a306637e
--- /dev/null
+++ b/robot/resources/vid/create_vid_vnf.robot
@@ -0,0 +1,122 @@
+*** Settings ***
+Documentation Creates VID VNF Instance
+
+Library ExtendedSelenium2Library 60
+Library UUID
+Library String
+Library DateTime
+Library RequestsLibrary
+
+Resource ../mso_interface.robot
+Resource vid_interface.robot
+
+*** Keywords ***
+
+Create VID VNF
+ [Documentation] Creates a VNF instance using VID for passed instance id with the passed service instance name
+ [Arguments] ${service_instance_id} ${service_instance_name} ${product_family} ${lcp_region} ${tenant} ${vnf_type}
+ Go To VID HOME
+ Click Link xpath=//div[@heading = 'Search for Existing Service Instances']/a
+ Wait Until Page Contains Please search by timeout=60s
+ #Wait Until Page Contains Element xpath=//div[@class='statusLine aaiHidden'] timeout=60s
+ #Wait Until Element Is Not Visible xpath=//div[@class='statusLine aaiHidden'] timeout=60s
+
+ # 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
+ Click Element xpath=//a[contains(text(), 'View/Edit')]
+ Wait Until Page Contains View/Edit Service Instance timeout=60s
+ #Wait Until Page Contains Element xpath=//div[@class='statusLine aaiVisible'] timeout=120s
+ #Wait Until Element Is Not Visible xpath=//div[@class='statusLine aaiVisible'] timeout=60s
+ Click Element button=Add VNF
+
+ # This is where firefox breaks. Th elink never becomes visible when run with the script.
+ Click Element link=${vnf_type}
+ Wait Until Page Contains Element xpath=//input[@parameter-id='instanceName'] 20s
+ Wait Until Element Is Enabled xpath=//input[@parameter-id='instanceName'] 20s
+
+ ## Without this sleep, the input text below gets immediately wiped out.
+ ## Wait Until Angular Ready just sleeps for its timeout value
+ Sleep 10s
+ Input Text xpath=//input[@parameter-id='instanceName'] ${service_instance_name}
+ Select From List By Label xpath=//select[@parameter-id='productFamily'] ${product_family}
+ Select From List By Label xpath=//select[@parameter-id='lcpRegion'] ${lcp_region}
+ Select From List By Label xpath=//select[@parameter-id='tenant'] ${tenant}
+ Click Element button=Confirm
+ Wait Until Element Contains xpath=//div[@ng-controller= 'msoCommitController']/pre[@class = 'log ng-binding'] Status: OK (200) timeout=120
+ ${response text}= Get Text xpath=//div[@ng-controller= 'msoCommitController']/pre[@class = 'log ng-binding']
+ Should Not Contain ${response text} FAILED
+ Click Element button=Close
+ ${instance_id}= Parse Instance Id ${response text}
+ Wait Until Page Contains ${service_instance_name} 60s
+ [Return] ${instance_id}
+
+Delete VID VNF
+ [Arguments] ${service_instance_id} ${lcp_region} ${tenant} ${vnf_instance_id}
+ Go To VID HOME
+ Click Link xpath=//div[@heading = 'Search for Existing Service Instances']/a
+ Wait Until Page Contains Please search by timeout=60s
+ Wait Until Page Contains Element xpath=//div[@class='statusLine aaiHidden'] timeout=60s
+ Wait Until Element Is Not Visible xpath=//div[@class='statusLine aaiHidden'] timeout=60s
+
+ # 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
+ Click Element link=View/Edit
+ Wait Until Page Contains View/Edit Service Instance timeout=60s
+ Wait Until Page Contains Element xpath=//div[@class='statusLine'] timeout=120s
+ Wait Until Element Is Not Visible xpath=//div[@class='statusLine aaiHidden'] timeout=60s
+
+
+
+ Click On Element When Visible xpath=//li/div[contains(.,'${vnf_instance_id}')]/a/span[@class='glyphicon glyphicon-remove'] timeout=120s
+ Select From List By Label xpath=//select[@parameter-id='lcpRegion'] ${lcp_region}
+ Select From List By Label xpath=//select[@parameter-id='tenant'] ${tenant}
+ 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]
+
+ ${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}
+ Poll MSO Get Request ${GLOBAL_MSO_STATUS_PATH}${request_id} COMPLETE
+
+Create VID VNF module
+ [Arguments] ${service_instance_id} ${vf_module_name} ${LCP_REGION} ${TENANT} ${VNF_TYPE}
+ Go To VID HOME
+ Click Link xpath=//div[@heading = 'Search for Existing Service Instances']/a
+ Wait Until Page Contains Please search by timeout=60s
+ Wait Until Page Contains Element xpath=//div[@class='statusLine aaiHidden'] timeout=60s
+
+ # 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
+ Click Element link=View/Edit
+ Wait Until Page Contains View/Edit Service Instance timeout=60s
+ Wait Until Page Contains Element xpath=//div[@class='statusLine'] timeout=120s
+ Wait Until Element Is Not Visible xpath=//div[@class='statusLine aaiHidden'] timeout=120s
+ Wait Until Element Is Visible button=Add VF-Module timeout=120s
+ Click Element button=Add VF-Module
+
+ # This is where firefox breaks. Th elink never becomes visible when run with the script.
+ Click Element link=${vnf_type}
+ Wait Until Page Contains Element xpath=//input[@parameter-id='instanceName'] 20s
+ Wait Until Element Is Enabled xpath=//input[@parameter-id='instanceName'] 20s
+
+ ## Without this sleep, the input text below gets immediately wiped out.
+ ## Wait Until Angular Ready just sleeps for its timeout value
+ Sleep 10s
+ Input Text xpath=//input[@parameter-id='instanceName'] ${vf_module_name}
+ Select From List By Label xpath=//select[@parameter-id='lcpRegion'] ${lcp_region}
+ Select From List By Label xpath=//select[@parameter-id='tenant'] ${tenant}
+ Click Element button=Confirm
+ Wait Until Element Contains xpath=//div[@ng-controller= 'msoCommitController']/pre[@class = 'log ng-binding'] requestId timeout=120
+ ${response text}= Get Text xpath=//div[@ng-controller= 'msoCommitController']/pre[@class = 'log ng-binding']
+ Click Element button=Close
+ ${instance_id}= Parse Instance Id ${response text}
+
+ ${request_id}= Parse Request Id ${response text}
+ Poll MSO Get Request ${GLOBAL_MSO_STATUS_PATH}${request_id} COMPLETE
+
+ [Return] ${instance_id} \ No newline at end of file
diff --git a/robot/resources/vid/teardown_vid.robot b/robot/resources/vid/teardown_vid.robot
new file mode 100644
index 00000000..50b50518
--- /dev/null
+++ b/robot/resources/vid/teardown_vid.robot
@@ -0,0 +1,63 @@
+*** Settings ***
+Documentation The main interface for interacting with VID. It handles low level stuff like managing the selenium request library and VID required steps
+Library ExtendedSelenium2Library
+Library Collections
+Library String
+Library StringTemplater
+Library UUID
+Resource vid_interface.robot
+Resource create_vid_vnf.robot
+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}
+
+*** 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
+ 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}
+ 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
+ Wait Until Element Is Not Visible xpath=//div[@class='statusLine aaiHidden'] timeout=60s
+
+ # 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
+ 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!
+
+ # 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
+
+ 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}
+ 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
+ ${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
+ Poll MSO Get Request ${GLOBAL_MSO_STATUS_PATH}${request_id} COMPLETE
+ Fail Successful VID Delete - continue with next delete
+
diff --git a/robot/resources/vid/vid_interface.robot b/robot/resources/vid/vid_interface.robot
new file mode 100644
index 00000000..78b81484
--- /dev/null
+++ b/robot/resources/vid/vid_interface.robot
@@ -0,0 +1,101 @@
+*** Settings ***
+Documentation The main interface for interacting with VID. It handles low level stuff like managing the selenium request library and VID required steps
+Library ExtendedSelenium2Library
+Library Collections
+Library String
+Library RequestsLibrary
+Library UUID
+Resource ../global_properties.robot
+Resource ../browser_setup.robot
+
+*** Variables ***
+${VID_ENV} /vid
+${VID_LOGIN_URL} ${GLOBAL_VID_SERVER}${VID_ENV}/login_external.htm
+${VID_HEALTHCHECK_PATH} ${VID_ENV}/api/users
+${VID_HOME_URL} ${GLOBAL_VID_SERVER}${VID_ENV}/vidhome.htm
+
+*** Keywords ***
+Run VID Health Check
+ [Documentation] Logs in to VID GUI
+ ${resp}= Run VID Get Request ${VID_HEALTHCHECK_PATH}
+ Should Be Equal As Strings ${resp.status_code} 200
+ Should Be String ${resp.json()[0]['loginId']}
+
+Run VID Get Request
+ [Documentation] Runs an VID get request
+ [Arguments] ${data_path}
+ ${auth}= Create List ${GLOBAL_VID_HEALTH_USERNAME} ${GLOBAL_VID_HEALTH_PASSWORD}
+ Log Creating session ${GLOBAL_VID_SERVER}
+ ${session}= Create Session vid ${GLOBAL_VID_SERVER} auth=${auth}
+ ${uuid}= Generate UUID
+ ${headers}= Create Dictionary username=${GLOBAL_VID_HEALTH_USERNAME} password=${GLOBAL_VID_HEALTH_PASSWORD} Accept=application/json Content-Type=application/json X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid} X-FromAppId=${GLOBAL_APPLICATION_ID}
+ ${resp}= Get Request vid ${data_path} headers=${headers}
+ Log Received response from vid ${resp.text}
+ [Return] ${resp}
+
+Login To VID GUI
+ [Documentation] Logs in to VID GUI
+ # Setup Browser Now being managed by test case
+ ##Setup Browser
+ Go To ${VID_LOGIN_URL}
+ Maximize Browser Window
+ Set Selenium Speed ${GLOBAL_SELENIUM_DELAY}
+ Set Browser Implicit Wait ${GLOBAL_SELENIUM_BROWSER_IMPLICIT_WAIT}
+ Log Logging in to ${GLOBAL_VID_SERVER}${VID_ENV}
+ Handle Proxy Warning
+ Title Should Be VID Login
+ Input Text xpath=//input[@ng-model='loginId'] ${GLOBAL_VID_USERNAME}
+ Input Password xpath=//input[@ng-model='password'] ${GLOBAL_VID_PASSWORD}
+ Click Button xpath=//input[@id='loginBtn']
+ Wait Until Page Contains Element xpath=//div[@class='applicationWindow'] ${GLOBAL_SELENIUM_BROWSER_WAIT_TIMEOUT}
+ Log Logged in to ${GLOBAL_VID_SERVER}${VID_ENV}
+
+Go To VID HOME
+ [Documentation] Naviage to VID Home
+ Go To ${VID_HOME_URL}
+ Wait Until Page Contains Element xpath=//div[@class='applicationWindow'] ${GLOBAL_SELENIUM_BROWSER_WAIT_TIMEOUT}
+
+Click On Button When Enabled
+ [Arguments] ${xpath} ${timeout}=60s
+ Wait Until Page Contains Element xpath=${xpath} ${timeout}
+ Wait Until Element Is Enabled xpath=${xpath} ${timeout}
+ Click Button xpath=${xpath}
+
+Click On Button When Visible
+ [Arguments] ${xpath} ${timeout}=60s
+ Wait Until Page Contains Element xpath=${xpath} ${timeout}
+ Wait Until Element Is Visible xpath=${xpath} ${timeout}
+ Click Button xpath=${xpath}
+
+Click On Element When Visible
+ [Arguments] ${xpath} ${timeout}=60s
+ Wait Until Page Contains Element xpath=${xpath} ${timeout}
+ Wait Until Element Is Visible xpath=${xpath} ${timeout}
+ Click Element xpath=${xpath}
+
+Select From List When Enabled
+ [Arguments] ${xpath} ${value} ${timeout}=60s
+ Wait Until Page Contains Element xpath=${xpath} ${timeout}
+ Wait Until Element Is Enabled xpath=${xpath} ${timeout}
+ Select From List xpath=${xpath} ${value}
+
+Input Text When Enabled
+ [Arguments] ${xpath} ${value} ${timeout}=60s
+ Wait Until Page Contains Element xpath=${xpath} ${timeout}
+ Wait Until Element Is Enabled xpath=${xpath} ${timeout}
+ Input Text xpath=${xpath} ${value}
+
+Parse Request Id
+ [Arguments] ${mso_response_text}
+ ${request_list}= Split String ${mso_response_text} 202)\n 1
+ ${clean_string}= Replace String ${request_list[1]} \n ${empty}
+ ${json}= To Json ${clean_string}
+ ${request_id}= Catenate ${json['requestReferences']['requestId']}
+ [Return] ${request_id}
+
+Parse Instance Id
+ [Arguments] ${mso_response_text}
+ ${request_list}= Split String ${mso_response_text} 202)\n 1
+ ${json}= To Json ${request_list[1]}
+ ${request_id}= Catenate ${json['requestReferences']['instanceId']}
+ [Return] ${request_id} \ No newline at end of file