summaryrefslogtreecommitdiffstats
path: root/cvp/3rd_party/static/testapi-ui/components
diff options
context:
space:
mode:
authorgrakiss <grakiss.wanglei@huawei.com>2017-09-28 03:47:54 -0400
committergrakiss <grakiss.wanglei@huawei.com>2017-09-28 05:15:01 -0400
commit0cf6b232ac9cf128ee9183a27c08f4f74ab2e2e6 (patch)
tree7be233b8f8f65fa968c7b93f1d1e75b691952ed9 /cvp/3rd_party/static/testapi-ui/components
parent63c2e2aa4b8d86349a767f611123ceafc19fa6d6 (diff)
add api&web services for cvp
JIRA: DOVETAIL-512 add api&web services for cvp Change-Id: I9ef9525e980fe61dc3108035ef9a3ff8783b2697 Signed-off-by: grakiss <grakiss.wanglei@huawei.com>
Diffstat (limited to 'cvp/3rd_party/static/testapi-ui/components')
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/about/about.html11
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/about/aboutController.js53
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/about/templates/README.html131
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/application/application.html251
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/application/applicationController.js140
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/application/logo-request1417
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/application/modal/confirmModal.html43
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/auth-failure/authFailureController.js33
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/auth/authPortal.html21
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/guidelines/data/danube.json590
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/guidelines/data/gen.py16
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/guidelines/data/mandatory.json248
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/guidelines/guidelines.html70
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/guidelines/guidelinesController.js188
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/guidelines/partials/guidelineDetails.html90
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/guidelines/partials/testListModal.html46
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/home/home.html74
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/home/homeController.js42
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/logout/logout.html1
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/logout/logoutController.js44
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/profile/importPubKeyModal.html27
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/profile/profile.html38
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/profile/profileController.js219
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/profile/showPubKeyModal.html11
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/results-report/partials/editTestModal.html65
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/results-report/partials/fullTestListModal.html13
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/results-report/partials/reportDetails.html65
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/results-report/resultsReport.html46
-rw-r--r--cvp/3rd_party/static/testapi-ui/components/results-report/resultsReportController.js182
29 files changed, 4175 insertions, 0 deletions
diff --git a/cvp/3rd_party/static/testapi-ui/components/about/about.html b/cvp/3rd_party/static/testapi-ui/components/about/about.html
new file mode 100644
index 00000000..f356050c
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/about/about.html
@@ -0,0 +1,11 @@
+<hr>
+<div class="about-sidebar">
+ <a><div class="about-option"
+ ng-click="ctrl.selectOption('about')"
+ ng-class="{ 'about-active': ctrl.selected === 'about' }">
+ About CVP
+ </div></a>
+</div>
+<div class="about-content">
+ <div ng-include src="ctrl.template"></div>
+</div>
diff --git a/cvp/3rd_party/static/testapi-ui/components/about/aboutController.js b/cvp/3rd_party/static/testapi-ui/components/about/aboutController.js
new file mode 100644
index 00000000..b0e36015
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/about/aboutController.js
@@ -0,0 +1,53 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ angular
+ .module('testapiApp')
+ .controller('AboutController', AboutController);
+
+ AboutController.$inject = ['$location'];
+
+ /**
+ * RefStack About Controller
+ * This controller handles the about page and the multiple templates
+ * associated to the page.
+ */
+ function AboutController($location) {
+ var ctrl = this;
+
+ ctrl.selectOption = selectOption;
+
+ ctrl.options = {
+ 'about' : {
+ 'title': 'About CVP',
+ 'template': 'testapi-ui/components/about/templates/README.html',
+ 'order': 1
+ }
+ };
+
+ /**
+ * Given an option key, mark it as selected and set the corresponding
+ * template and URL hash.
+ */
+ function selectOption(key) {
+ ctrl.selected = key;
+ ctrl.template = ctrl.options[key].template;
+ }
+
+ ctrl.selectOption('about');
+ }
+})();
diff --git a/cvp/3rd_party/static/testapi-ui/components/about/templates/README.html b/cvp/3rd_party/static/testapi-ui/components/about/templates/README.html
new file mode 100644
index 00000000..cb4140e4
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/about/templates/README.html
@@ -0,0 +1,131 @@
+<h2>Executive Summary</h2>
+<p>OPNFV® is offering OPNFV compliance verification through its Compliance Verification Program (CVP). The CVP verifies products (“Offerings”) that claim compliance to OPNFV.</p>
+<p>The OPNFV CVP is a compliance verification program intended to increase the awareness and adoption of OPNFV by demonstrating the readiness and availability of commercial products based on OPNFV. </p>
+<p>The key objectives and benefits of the OPNFV CVP are to:</p>
+<ul>
+ <li>Help build the market for </li>
+ <ul>
+ <li>OPNFV-based infrastructure</li>
+ <li>applications designed to run on that infrastructure</li>
+ </ul>
+ <li>Reduce adoption risks for end-users</li>
+ <li>Decrease testing costs by verifying hardware and software platform interfaces and components </li>
+ <li>Enhance interoperability</li>
+</ul>
+ <p>Verified products submitted by respective vendors are expected to differentiate themselves with different features and capabilities but remain compliant by implementing explicitly defined interfaces, behaviors, and key features.</p>
+<h3>Purpose of This Document</h3>
+<p>This document defines the framework and governance of the OPNFV CVP, including the scope and objectives of the program, maintenance of program materials, compliance verification requirements and processes, trademark/logo usage guidelines, requirements for systems under compliance verification, and escalation procedures. </p>
+This document does not define compliance verification procedures. Compliance verification procedures are defined by the community under the oversight of the Technical Steering Committee.
+<p>The current scope of compliance verification is based on multiple sources: </p>
+<ul>
+ <li>The latest release of OPNFV </li>
+ <li>Informative ETSI NFV ISG specifications, specifically:</li>
+ <ul>
+
+ <li>Pre-deployment Testing: Report on Validation of NFV Environments and Services <a href="http://www.etsi.org/deliver/etsi_gs/NFV-TST/001_099/001/01.01.01_60/gs_NFV-TST001v010101p.pdf">http://www.etsi.org/deliver/etsi_gs/NFV-TST/001_099/001/01.01.01_60/gs_NFV-TST001v010101p.pdf</a></li>
+ </ul>
+</ul>
+<p>Please note that these sources are subject to further revisions and may be updated at some future time. The current compliance verification procedures are published by OPNFV.</p>
+
+
+
+
+<h2>Program Management & Maintenance</h2>
+
+<h3>Role of C&C Committee</h3>
+<p>The OPNFV Certification & Compliance (C&C) Committee, hereafter referred to as the Committee, serves as the CVP administrator on behalf of the OPNFV Board of Directors. The Committee is responsible for defining program governance, compliance verification strategy, and the overall scope of the compliance verification procedures. </p>
+<h3>Maintenance of Program Documents</h3>
+<p>Program documents, such as this document, produced by the Committee will be labeled using semantic versioning. That is, they will be labeled using MAJOR.MINOR.PATCH notation, where MAJOR, MINOR, and PATCH are non-negative integers.</p>
+<p>1.MAJOR version. Note: to avoid market confusion, the scope of compliance verification and other project documents is tied to the major version, and once approved by the Board of Directors, will not change until the next major release.</p>
+<p>2.MINOR version is used to denote significant functionality changes (e.g., addition/subtraction of compliance verification procedures and/or document sections). Changes to a minor version of an approved document require Board approval. It is a goal that minor changes should not affect the ability of a product to achieve compliance/qualification status.</p>
+<p>3.PATCH version is used to indicate error corrections or editorial changes.</p>
+<p>The scope of a particular version of the CVP requirements, test-cases, compliance verification checks, tools and results is tied to an OPNFV release. </p>
+
+<h3>Maintenance of CVP compliance verification procedures</h3>
+<p>The overall CVP compliance verification scope tied to an OPNFV release is determined by the Committee. The OPNFV TSC defines and maintains the compliance verification procedures and associated tools. The scope is constrained to features, capabilities, components, and interfaces included in an OPNFV release that are generally available in the industry (e.g., through adoption by an upstream community). Compliance verification is evaluated using functional tests that focus on defined interfaces and/or behaviors without regard to the underlying system under test. In practice, testing exercises interfaces and/or behaviors developed or exposed by OPNFV. </p>
+
+<h3>OPNFV Trademark/Logo Usage Guidelines</h3>
+
+<p>Because of its position in the industry as an Open Source Project maintained by the Linux Foundation, OPNFV cannot endorse any products or appear to endorse any products.</p>
+
+<h3>Use of the Term OPNFV Ready</h3>
+<p>Products that pass the CVP compliance verification suite may be labeled as “OPNFV Ready”. Products that are “OPNFV Ready” expose key features/behaviors of the OPNFV release.</p>
+<ul>
+ <li>OPNFV Ready” asserts that a specific system under test</li>
+ <ul>
+ <li>Supply the key behaviors, functions, and related APIs of the OPNFV release</li>
+ <li>Promotes the key values of the OPNFV release, e.g. based upon the open source project components that comprise the OPNFV release</li>
+ <li>Performs basic NFV functions</li>
+ <li>Is interoperable with the OPNFV release</li>
+ <li>Suitable for further trials in an operator network</li>
+ </ul>
+ <li>OPNFV Ready” does not assert:</li>
+ <ul>
+ <li>Readiness for commercial deployment</li>
+ </ul>
+</ul>
+
+<p>The OPNFV C&C Committee on behalf of the Board of Directors can award a product “OPNFV Ready” status. “OPNFV Ready”, therefore, may not be used in relation to a vendor’s product without first having met the requirements outlined in this document. </p>
+<p>Use of “Ready” must be used in conjunction with the OPNFV release name under which the product was verified (e.g., “OPNFV Colorado Ready”). This allows the OPNFV compliance/qualification standard to evolve over time as the OPNFV platform matures.</p>
+<p>Organizations applying for compliance verification shall use the Logo/Trademark solely for the Product/Technology that was verified to have met the requirements designated by The Committee with respect to the appropriate category. </p>
+They shall not use the Logo/Trademark for any product/technology other than the Product/Technology submitted for compliance verification even if it belongs to the appropriate category.
+<p>They shall only use the Logo/Trademark solely for the following purposes in order to: </p>
+
+<ul>
+ <li>promote OPNFV; </li>
+ <li>indicate to procurers and users the information of interoperability for NFV infrastructure and applications; and </li>
+ <li>indicate that the verified product meets all requirements set by the Committee for use of the Logo/Trademark. </li>
+</ul>
+<p>Organizations shall not use the Logo/Trademark in any way that would associate it with any individual or company logo or brand, beyond the association to the specific platform to which it was awarded. </p>
+
+<p>They shall use the Logo/Trademark solely in accordance with the OPNFV Logo Style Guide which is prepared and amended by the Committee from time to time. Other than in association to the specific platform to which it was awarded, they shall not frame, post, upload, transmit or modify in any way, all or any part of the Logo, unless expressly authorized in writing by the Committee. </p>
+<p></p>
+<p>Organizations shall immediately notify the Committee if they suspect or discover that the Logo/Trademark is or will be used for any purposes other than the confirmed purposes or that the use conflicts with any of the representations hereof as a result of upgrading of its submitted product/technology. In the event that the above notification is provided, they shall provide the Committee with any and all information requested by the Committee in relation to the upgrading of the confirmed product/technology and all information in order to confirm the revised product/technology actually meets the requirements designated by the Committee with respect to the appropriate category. They shall not use the Logo/Trademark for any product/technology which does not meet the requirements designated by the Committee with respect to the confirmed category. </p>
+<p>Note: Such organizations will be held responsible for any illegal use of the Logo/Trademark by others. </p>
+<p>Organizations participating in the OPNFV CVP do not own any intellectual property rights in relation to the Logo/Trademark, program documents, or compliance verification procedures.</p>
+
+
+<h2>Compliance Verification & Application Requirements </h2>
+<h3>Compliance Verification Procedures Requirements</h3>
+<p>CVP compliance verification procedures leverage tests, compliance verification tools, test infrastructure and compliance verification program infrastructure defined and maintained by OPNFV projects which are included in an OPNFV release. The OPNFV TSC defines which compliance verification procedures are included as part of the CVP. Once published, the compliance verification procedure suites will not change until the next OPNFV release (except to fix bugs or errors), as described above.</p>
+<p>OPNFV compliance verification is applicable to one or more of the following categories:</p>
+<ul>
+ <li>1) Hardware Platform</li>
+ <li>2) Software Platform (e.g, Virtual Infrastructure – NFVI, VIM, etc.)</li>
+ <li>3) Applications (e.g., VNFs) </li>
+ <li>4) Orchestration (End to End management)</li>
+</ul>
+<p>The scope of the criteria and requirements for each CVP release is set forth in an addendum to this document.</p>
+
+<h3>Self-Compliance Verification</h3>
+<p>Organizations may conduct compliance verification using the OPNFV-designated tools at their facilities. The OPNFV-designated tools will ensure that the results were produced by an unaltered version of the tools, and that the results were unaltered. For example, this could be accomplished by digitally verifying the tools themselves, and signing the results file(s). Results MUST be submitted for review with application documentation and the logo usage agreement to OPNFV.</p>
+
+<h3>OPNFV Preferred Verification Labs</h3>
+<p>Vendors may request service from third parties to conduct OPNFV compliance verification and collect results. Compliance verification occurs as documented in “Self Compliance Verification” above. The compliance verification results and documentation may be submitted by the third party on behalf of the vendor requesting the use of an OPNFV Logo/Trademark.</p>
+<p>OPNFV may identify organizations providing third-party verification as Preferred Labs and list them on the OPNFV web site. OPNFV does not endorse or sponsor Preferred Labs’ services. Vendors are not required to use OPNFV Preferred Labs.</p>
+
+<h3>Compliance Application Requirements</h3>
+<p>The use of the OPNFV Ready logo is not restricted to OPNFV member companies. The request for use of an OPNFV Logo/Trademark must state the organization, a contact person (email and telephone number); their postal address; the location where the verification results and documentation was prepared, the category or categories the product is requesting an OPNFV Logo/Trademark(s) for; the attestation stating they will abide by OPNFV policies and procedures for use of an OPNFV Logo/Trademark; any third-party lab conducting the verification; and the product identifier.</p>
+
+<h3>Review Process</h3>
+<p>The compliance verification results and documentation submitted will be reviewed by the Committee for completeness and validity. Based on the determination of the Committee, a recommendation will be made to the OPNFV Board of Directors regarding the approval of the granting of permission to use an OPNFV Logo/Trademark.</p>
+<p>The Committee may request additional information regarding the application for use of an OPNFV Logo/Trademark.</p>
+<p>OPNFV may charge a reasonable fee for reviewing results. Reviews will be conducted by OPNFV member companies participating in the review committee (a C&C subcommittee). No member company may review its own compliance verification results.</p>
+<p>In the event of a dispute, the submitting organization has a right to appeal the decision with the OPNFV Board of Directors. An appeals process is documented in the Escalation Process below.</p>
+
+<h2>System Under Compliance Verification Requirements</h2>
+<p>The compliance verification environment (hardware and software) is defined by the OPNFV TSC.</p>
+
+<h3>Similarity Policy</h3>
+
+<p>Hardware platforms identified as similar to platforms that have passed CVP compliance verification procedures may apply to use the OPNFV Ready trademark. The C&C Committee can decide to grant “OPNFV Ready” to products designated “under similarity”. The Committee will consider similarity in the following areas (for example):</p>
+<ul>
+ <li>Compute</li>
+ <li>Network</li>
+ <li>Storage</li>
+</ul>
+<p>Hardware platforms receiving rights to use the Logo/Trademark “under similarity” will be so designated on the website.</p>
+
+<h2>Escalation Process</h2>
+<p>If, after submitting compliance verification results and documentation, a vendor believes its results were evaluated unfairly or if it identifies issues with the test plan, tools, or third party lab, it may send an appeal in writing to the Committee. The Committee will review the appeal in a reasonable timeframe and respond in writing.</p>
+<p>If the vendor wishes to appeal further, it may send a further appeal in writing to the OPNFV Board of Directors. The Board will evaluate the appeal at its next regular meeting.</p>
diff --git a/cvp/3rd_party/static/testapi-ui/components/application/application.html b/cvp/3rd_party/static/testapi-ui/components/application/application.html
new file mode 100644
index 00000000..f82aedda
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/application/application.html
@@ -0,0 +1,251 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ <meta charset="utf-8">
+ <title>Logo Request &raquo; OpenStack Open Source Cloud Computing Software</title>
+
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+
+<link rel="stylesheet" href="testapi-ui/assets/css/combine.css" />
+<body id="logo-request">
+
+
+<div class="top-site-banner">
+ <div class="container">
+ <p>
+ <p class="p1">Complete this application then start your CVP journey</p>
+ <!--
+ <a href="https://www.openstack.org/summit/sydney-2017/" class="top-site-banner-button">Register now</a>
+ -->
+ </p>
+ </div>
+</div>
+
+<div class="row" style="margin-top:20px">
+ <div class="col-lg-12 container">
+ <!--
+ <h1>Request information on OpenStack trademark licensing</h1>
+ <p>If you plan to offer an OpenStack-related product or service using a trademark or brand that includes an OpenStack mark (e.g. logo or the word OpenStack), you are required to apply for and obtain a trademark license. We@~Yve created a family of logos and a set of standards specifically for this pp
+urpose. Once we understand more about your product or service, we can determine which (if any) logo program it falls under, and send you the appropriate license for signature. </p>
+ -->
+ <form id="OsLogoProgramForm_Form" action="/brand/logo-request/Form" method="post" enctype="application/x-www-form-urlencoded">
+ <p id="OsLogoProgramForm_Form_error" class="message " style="display: none"></p>
+ <fieldset>
+ <div class="field text col-md-4">
+ <label class="left" >Organization name</label>
+ <i uib-tooltip="Organization name" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+
+ <div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.organization_name" required="required" aria-required="true" />
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Organization website (if public)</label>
+ <i uib-tooltip="Organization website if it is public" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.organization_web" required="required" aria-required="true" />
+ </div>
+ </div>
+ <div class="col-md-4"></div>
+ <div class="field email text col-md-4">
+ <label class="left">Product name and/or identifier</label>
+ <i uib-tooltip="Product name and/or identifier" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<div class="middleColumn">
+ <input type="text" class="email text form-control" ng-model="ctrl.product_name" required="required" aria-required="true" />
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Product specifications</label>
+ <i uib-tooltip="A link of product specifications" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.product_spec" required="required" aria-required="true" />
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Product public documentation</label>
+ <i uib-tooltip="A link of product public documentation" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.product_documentation" required="required" aria-required="true" />
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Product categories</label>
+ <i uib-tooltip="Product categories" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<div class="middleColumn">
+ <select class="form-control" ng-model="ctrl.product_categories">
+ <option value="soft&hard">software and hardware</option>
+ <option value="soft&3rd">software and third party hardware</option>
+ </select>
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Primary contact name</label>
+ <i uib-tooltip="Primary contact name" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.prim_name" required="required" aria-required="true" />
+ </div>
+ </div><div class="field text col-md-4">
+ <label class="left">Primary business email</label>
+ <i uib-tooltip="Only the Business email address should be used for official communication with OPNFV CVP" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.prim_email" required="required" aria-required="true" />
+ </div>
+ </div><div class="field text col-md-4">
+ <label class="left">Primary postal address</label>
+ <i uib-tooltip="Primary postal address" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.prim_address" required="required" aria-required="true" />
+ </div>
+ </div><div class="field text col-md-4">
+ <label class="left">Primary phone number</label>
+ <i uib-tooltip="Primary phone number" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.prim_phone" required="required" aria-required="true" />
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">User ID Type</label>
+ <i uib-tooltip="User ID Type" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <select class="form-control" ng-model="ctrl.id_type">
+ <option value="Linux Foundation">Linux Foundation</option>
+ <option value="Openstack">Openstack</option>
+ <option value="Github">Github</option>
+ <option value="Google">Google</option>
+ <option value="Fackbook">Fackbook</option>
+ </select>
+ </div>
+ </div>
+
+ <div class="field text col-md-4">
+ <label class="left">User ID for CVP web portal</label>
+ <i uib-tooltip="User ID for CVP web portal" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <input type="text" class="text form-control" ng-model="ctrl.user_id" />
+ </div>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Location</label>
+ <i uib-tooltip="Location" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+ <div class="middleColumn">
+ <select class="form-control" ng-model="ctrl.lab_location">
+ <option value="internal">internal vendor lab</option>
+ <option value="third">third-party lab</option>
+ </select>
+ </div>
+ </div>
+ <div ng-if="ctrl.lab_location=='third'" class="field text">
+ <div class="field text col-md-4">
+ <label class="left">Lab Name</label>
+ <i uib-tooltip="Lab Name" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<input type="text" class="text form-control" ng-model="ctrl.lab_name"/>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Lab Email</label>
+ <i uib-tooltip="Lab Email" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<input type="text" class="text form-control" ng-model="ctrl.lab_email"/>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Lab Address</label>
+ <i uib-tooltip="Lab Address" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<input type="text" class="text form-control" ng-model="ctrl.lab_address"/>
+ </div>
+ <div class="field text col-md-4">
+ <label class="left">Lab Phone Number</label>
+ <i uib-tooltip="Lab Phone Number" class="glyphicon glyphicon-question-sign opnfv-blue"></i>
+<input type="text" class="text form-control" ng-model="ctrl.lab_phone"/>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+</div>
+<div class="Actions">
+ <a class="nectar-button medium accent-color regular-button" ng-click="ctrl.openConfirmModal()" />submit</a>
+</div>
+<div class="results-table" style="margin-top:30px;overflow:scroll">
+ <table class="table table-striped table-hover">
+ <thead>
+ <tr>
+ <th>Create Date</th>
+ <th>Organization name</th>
+ <th>Organization website</th>
+ <th>Product name</th>
+ <th>Product specifications</th>
+ <th>Product documentation</th>
+ <th>Product categories</th>
+ <th>Primary contact name</th>
+ <th>Primary business email</th>
+ <th>Primary postal address</th>
+ <th>Primary phone number</th>
+ <th>User ID Type</th>
+ <th>User ID</th>
+ <th>Location</th>
+ <th>Operation</th>
+ </tr>
+ </thead>
+ <script type="text/ng-template" id="product.tpl.html">
+ <div class="input-group">
+ <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
+ <input type="text" value="{{app.product_spec}}">
+ </div>
+ <div class="input-group">
+ <span class="input-group-addon">@</span>
+ <input type="text" value="{{app.product_documentation}}">
+ </div>
+ <div class="input-group">
+ <span class="input-group-addon"><i class="glyphicon glyphicon-map-marker"></i></span>
+ <input type="text" value="{{app.product_categories | category}}">
+ </div>
+ </script>
+ <script type="text/ng-template" id="lab.tpl.html">
+ <div class="input-group">
+ <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
+ <input type="text" value="{{app.lab_name}}">
+ </div>
+ <div class="input-group">
+ <span class="input-group-addon">@</span>
+ <input type="text" value="{{app.lab_email}}">
+ </div>
+ <div class="input-group">
+ <span class="input-group-addon"><i class="glyphicon glyphicon-map-marker"></i></span>
+ <input type="text" value="{{app.lab_address}}">
+ </div>
+ <div class="input-group">
+ <span class="input-group-addon"><i class="glyphicon glyphicon-phone"></i></span>
+ <input type="text" value="{{app.lab_phone}}">
+ </div>
+ </script>
+ <tbody style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
+ <tr ng-repeat="app in ctrl.applications">
+ <td>{{ app.creation_date | limitTo: 10 }}</td>
+ <td>{{ app.organization_name }}</td>
+ <td><a href="{{app.organization_web}}">{{ app.organization_web }}</a></td>
+ <td>{{ app.product_name}}</td>
+ <td><a href="{{app.product_spec}}">{{app.product_spec}}</a></td>
+ <td><a href="{{app.product_documentation}}">{{app.product_documentation}}</a></td>
+ <td>{{ app.product_categories | category }}</td>
+ <td>{{ app.prim_name }}</td>
+ <td>{{ app.prim_email }}</td>
+ <td>{{ app.prim_address }}</td>
+ <td>{{ app.prim_phone }}</td>
+ <td>{{ app.id_type }}</td>
+ <td>{{ app.user_id }}</td>
+ <td><span popover-enable="app.lab_location != 'internal'" uib-popover-template="ctrl.lab_tpl" popover-title="Lab Info" popover-placement="top" popover-trigger="mouseenter">{{ app.lab_location | labLocation}}</span><i ng-if="app.lab_location != 'internal'" class="glyphicon glyphicon-info-sign opnfv-blue"></i></td>
+ <td><a ng-click="ctrl.deleteApp(app._id)" class="badge badge-info"><i class="glyphicon glyphicon-remove" ></i></a></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <div class="pages">
+ <uib-pagination
+ total-items="ctrl.totalItems"
+ ng-model="ctrl.currentPage"
+ items-per-page="ctrl.itemsPerPage"
+ max-size="ctrl.maxSize"
+ class="pagination-sm"
+ boundary-links="true"
+ rotate="false"
+ num-pages="ctrl.numPages"
+ ng-change="ctrl.updatePage()">
+ </uib-pagination>
+ </div>
+</div>
diff --git a/cvp/3rd_party/static/testapi-ui/components/application/applicationController.js b/cvp/3rd_party/static/testapi-ui/components/application/applicationController.js
new file mode 100644
index 00000000..f392d05e
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/application/applicationController.js
@@ -0,0 +1,140 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ angular
+ .module('testapiApp')
+ .controller('ApplicationController', ApplicationController);
+
+ ApplicationController.$inject = [
+ '$http', '$stateParams', '$window', '$sce',
+ '$uibModal', 'testapiApiUrl', 'raiseAlert', 'ngDialog', '$scope'
+ ];
+
+ /**
+ */
+ function ApplicationController($http, $stateParams, $window, $sce,
+ $uibModal, testapiApiUrl, raiseAlert, ngDialog, $scope) {
+
+ var ctrl = this;
+
+ function init(){
+ ctrl.organization_name = null;
+ ctrl.organization_web = null;
+ ctrl.product_name = null;
+ ctrl.product_spec = null;
+ ctrl.product_documentation = null;
+ ctrl.product_categories = "soft&hard";
+ ctrl.prim_name = null;
+ ctrl.prim_email = null;
+ ctrl.prim_address = null;
+ ctrl.prim_phone = null;
+ ctrl.id_type = "Linux Foundation";
+ ctrl.user_id = null;
+ ctrl.lab_location="internal";
+ ctrl.lab_name = null;
+ ctrl.lab_email=null;
+ ctrl.lab_address=null;
+ ctrl.lab_phone=null;
+ ctrl.applications = [];
+ ctrl.showApplications = [];
+
+ ctrl.totalItems = null;
+ ctrl.currentPage = 1;
+ ctrl.itemsPerPage = 5;
+ ctrl.numPages = null;
+ ctrl.lab_tpl = "lab.tpl.html";
+ ctrl.product_tpl = "product.tpl.html";
+ //ctrl.lab_html=$sce.trustAsHtml('<div>{{app.lab_email}}</div><div>{{app.lab_address}}</div><div>{{app.lab_phone}}</div>');
+
+ getApplication();
+ }
+
+
+ ctrl.submitForm = function(){
+ var data = {
+ "organization_name": ctrl.organization_name,
+ "organization_web": ctrl.organization_web,
+ "product_name": ctrl.product_name,
+ "product_spec": ctrl.product_spec,
+ "product_documentation": ctrl.product_documentation,
+ "product_categories": ctrl.product_categories,
+ "prim_name": ctrl.prim_name,
+ "prim_email": ctrl.prim_email,
+ "prim_address": ctrl.prim_address,
+ "prim_phone": ctrl.prim_phone,
+ "id_type": ctrl.id_type,
+ "user_id": ctrl.user_id,
+ "lab_location": ctrl.lab_location,
+ "lab_email": ctrl.lab_email,
+ "lab_address": ctrl.lab_address,
+ "lab_phone": ctrl.lab_phone
+ };
+ console.log(data);
+ $http.post(testapiApiUrl + "/cvp/applications", data).then(function(resp){
+ if(resp.data.code && resp.data.code != 0) {
+ alert(resp.data.msg);
+ return;
+ }
+ getApplication();
+ }, function(error){
+ });
+ }
+
+ ctrl.openConfirmModal = function(){
+ var resp = confirm("Are you sure to submit?");
+ if (resp) {
+ ctrl.submitForm();
+ }
+ }
+
+ ctrl.cancelSubmit = function(){
+ ngDialog.close();
+ }
+
+ ctrl.updatePage = function(){
+ getApplication();
+ }
+
+ ctrl.deleteApp = function(id){
+ var resp = confirm('Are you sure to delete this application?');
+ if (!resp)
+ return;
+
+ var delUrl = testapiApiUrl + "/cvp/applications/" + id;
+ $http.delete(delUrl)
+ .then( function(ret) {
+ if(ret.data.code && ret.data.code != 0) {
+ alert(ret.data.msg);
+ return;
+ }
+ getApplication();
+ });
+ }
+
+ function getApplication(){
+ $http.get(testapiApiUrl + "/cvp/applications?page="+ctrl.currentPage+"&signed&per_page="+ctrl.itemsPerPage).then(function(response){
+ ctrl.applications = response.data.applications;
+ ctrl.totalItems = response.data.pagination.total_pages* ctrl.itemsPerPage;
+ ctrl.currentPage = response.data.pagination.current_page;
+ ctrl.numPages = response.data.pagination.total_pages;
+ }, function(error){
+ });
+ }
+
+ init();
+ }
+})();
diff --git a/cvp/3rd_party/static/testapi-ui/components/application/logo-request b/cvp/3rd_party/static/testapi-ui/components/application/logo-request
new file mode 100644
index 00000000..c7bb109d
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/application/logo-request
@@ -0,0 +1,1417 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="globalsign-domain-verification" content="tWFOHNAA_WMHmHfBMq38uTgupHFugV_dZ2rqyRxNMx" />
+ <title>Logo Request &raquo; OpenStack Open Source Cloud Computing Software</title>
+
+ <meta name="generator" content="SilverStripe - http://silverstripe.org" />
+<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+<meta property="og:title" content="Logo Request &amp;raquo; OpenStack Open Source Cloud Computing Software" />
+<meta property="og:type" content="website" />
+<meta property="og:url" content="https://www.openstack.org/brand/logo-request/" />
+<link rel="image_src" href="https://www.openstack.org/themes/openstack/images/openstack-logo-full.png" type="image/png"/>
+<meta property="og:image" content="http://www.openstack.org/themes/openstack/images/openstack-logo-full.png" />
+<meta property="og:image:secure_url" content="https://www.openstack.org/themes/openstack/images/openstack-logo-full.png" />
+<meta property="og:image:type" content="image/png" />
+<meta property="og:description" content="If you plan to offer an OpenStack-related product or service using a trademark or brand that includes an OpenStack mark (e.g. logo or the word OpenStack), you are required to apply for and obtain a trademark license. We’ve created a family of logos and a set of standards specifically for this purpose. Once we understand more about your product or service, we can determine which (if any) logo program it falls under, and send you the appropriate license for signature.  " />
+<meta property="og:site_name" content="OpenStack" />
+<meta property="og:locale" content="en_US" />
+<meta property="fb:app_id" content="209869746011654" />
+<meta name="twitter:card" content="summary" />
+<meta name="twitter:site" content="@openstack" />
+
+
+ <base href="https://www.openstack.org/"><!--[if lte IE 6]></base><![endif]-->
+
+ <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="https://www.openstack.org/blog/feed/"/>
+ <link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png">
+ <link rel="icon" type="image/png" href="/favicon/favicon-32x32.png" sizes="32x32">
+ <link rel="icon" type="image/png" href="/favicon/favicon-16x16.png" sizes="16x16">
+ <link rel="manifest" href="/favicon/manifest.json">
+ <link rel="mask-icon" href="/favicon/safari-pinned-tab.svg" color="#5bbad5">
+
+
+ <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
+ <!--[if lt IE 9]>
+ <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
+ <script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
+ <![endif]-->
+
+ <script type="text/javascript">
+
+// Used to record outbound links before the browser resets to the new site
+
+function recordOutboundLink(link, category, action) {
+ try {
+ ga('send', 'event', {
+ eventCategory: category,
+ eventAction: 'click',
+ eventLabel: link.href
+ });
+ setTimeout('document.location = "' + link.href + '"', 100)
+ }
+ catch(err){}
+}
+
+</script>
+
+<script>
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+ ga('create', 'UA-17511903-1', 'auto');
+ ga('send', 'pageview');
+
+</script>
+
+ <script type="text/javascript">
+ _linkedin_data_partner_id = "36268";
+</script><script type="text/javascript">
+ (function(){var s = document.getElementsByTagName("script")[0];
+ var b = document.createElement("script");
+ b.type = "text/javascript";b.async = true;
+ b.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js";
+ s.parentNode.insertBefore(b, s);})();
+</script>
+ <link rel="stylesheet" type="text/css" href="/themes/openstack/css/bootstrap.min.css?m=1503597172" />
+<link rel="stylesheet" type="text/css" href="/themes/openstack/bower_assets/fontawesome/css/font-awesome.min.css?m=1502291691" />
+<link rel="stylesheet" type="text/css" href="/themes/openstack/css/combined.css?m=1503597172" />
+<link rel="stylesheet" type="text/css" href="/themes/openstack/css/navigation_menu.css?m=1503597172" />
+<link rel="stylesheet" type="text/css" href="/themes/openstack/css/dropdown.css?m=1503597172" />
+<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans:300,400,700" />
+<link rel="stylesheet" type="text/css" href="/framework/css/CheckboxSetField.css?m=1462921760" />
+<style type="text/css">
+.honey {
+ position: absolute; left: -9999px
+}
+</style>
+</head>
+
+ <body id="logo-request">
+
+
+<!-- Top Site Banner -->
+<div class="top-site-banner">
+ <div class="container">
+ <p>
+ <p class="p1">Join the global OpenStack community for use cases &amp; training at the OpenStack Summit Sydney, November 6-8 &nbsp; &nbsp;
+ <a href="https://www.openstack.org/summit/sydney-2017/" class="top-site-banner-button">Register now</a>
+ </p>
+ </div>
+</div>
+<!-- End Site Banner -->
+
+ <nav class="navbar navbar-default" role="navigation">
+
+ <div class="container">
+ <!-- Brand and toggle get grouped for better mobile display -->
+ <div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <div class="brand-wrapper">
+ <a class="navbar-brand" href="/"></a>
+ </div>
+ <div class="search-icon show"><i class="fa fa-search"></i> <span class="header-search-text">Search</span></div>
+ </div>
+ <!-- Collect the nav links, forms, and other content for toggling -->
+ <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+ <div class="search-container tiny">
+
+<input type="text" class="st-default-search-input custom-search-box" placeholder="Search OpenStack">
+
+<script type="text/javascript" src="/themes/openstack/javascript/jquery.min.js?m=1503597172"></script><script type="text/javascript" src="/themes/openstack/javascript/jquery-migrate-1.2.1.min.js?m=1503597172"></script><script type="text/javascript" src="/themes/openstack/javascript/jquery.cookie.js?m=1503597172"></script><script type="text/javascript" src="/themes/openstack/javascript/querystring.jquery.js?m=1503597172"></script><script type="text/javascript" src="/themes/openstack/javascript/shadowbox/shadowbox.js?m=1503597172"></script><script type="text/javascript" src="/themes/openstack/javascript/jquery.ticker.js?m=1503597172"></script><script type="text/javascript" src="/themes/openstack/javascript/jquery.tools.min.js?m=1503597172"></script><script type="text/javascript" src="/themes/openstack/javascript/jcarousellite.min.js?m=1503597172"></script><script type="text/javascript" src="/themes/openstack/javascript/navigation.js?m=1503597172"></script><script type="text/javascript" src="/themes/openstack/javascript/filetracking.jquery.js?m=1503597172"></script><script type="text/javascript" src="/themes/openstack/javascript/updateProfileModal.js?m=1503597172"></script><script type="text/javascript" src="/themes/openstack/javascript/bootstrap.min.js?m=1503597172"></script><script type="text/javascript">//<![CDATA[
+jQuery(document).ready(function($) {
+
+ var d = new Date();
+ var user_date = d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate();
+ $.cookie('user_date',user_date , { expires: 360, path: '/' });
+
+ $('body').filetracking();
+
+ $(document).on("click", ".outbound-link", function(event){
+ var href = $(this).attr('href');
+ recordOutboundLink(this,'Outbound Links',href);
+ event.preventDefault();
+ event.stopPropagation()
+ return false;
+ });
+
+ var use_shadow_box = false;
+ if(use_shadow_box)
+ Shadowbox.init();
+});
+
+//]]></script><script type="text/javascript">//<![CDATA[
+
+ jQuery(document).ready(function() {
+
+ if($('#OsLogoProgramForm_Form_CurrentSponsor').prop('checked') != true){
+ $('#openstack-companies').hide();
+ $('#non-sponsor-company').show();
+ } else {
+ $('#openstack-companies').show();
+ $('#non-sponsor-company').hide();
+ }
+
+ $('#OsLogoProgramForm_Form_CurrentSponsor').click(function () {
+ $('#openstack-companies').toggle();
+ $('#non-sponsor-company').toggle();
+ });
+ });
+
+
+//]]></script><script type="text/javascript">
+ (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
+ (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
+ e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
+ })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
+
+ _st('install','aDn5L_vgZ2yzRcE893kK','2.0.0');
+</script>
+ <i class="fa fa-times close-search"></i>
+ </div>
+ <ul class="nav navbar-nav navbar-main show">
+ <li>
+ <input type="text" class="st-default-search-input custom-search-box-mobile" placeholder="Search OpenStack">
+
+ </li>
+
+ <li>
+ <a href="https://www.openstack.org/software/" class="drop" id="dropdownMenuSoftware">Software <i class="fa fa-caret-down"></i></a><i class="mobile-expand"></i>
+ <ul class="dropdown-menu dropdown-hover" role="menu" aria-labelledby="dropdownMenuSoftware">
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/software/">Overview</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/software/project-navigator/">Project Navigator</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/software/sample-configs/">Sample Configs</a></li>
+ <li role="presentation" class="divider"></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/software/security/">Security</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/software/start/">Get Started</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/software/roadmap/">Roadmap</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/software/latest-release/">Latest Release</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/software/sourcecode/">Source Code</a></li>
+ </ul>
+</li>
+<li>
+ <a href="https://www.openstack.org/user-stories/" class="drop" id="dropdownMenuUsers">Users <i class="fa fa-caret-down"></i></a><i class="mobile-expand"></i>
+ <ul class="dropdown-menu dropdown-hover" role="menu" aria-labelledby="dropdownMenuUsers">
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/user-stories/">Overview</a></li>
+ <li role="presentation" class="divider"></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/edge/">Edge Computing</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/telecoms-and-nfv/">Telecom & NFV</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/enterprise/">OpenStack in the Enterprise</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/science/">OpenStack in Science</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/containers/">Containers</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="http://superuser.openstack.org/">Superuser Magazine</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/surveys/landing">User Survey</a></li>
+ </ul>
+</li>
+<li>
+ <a href="https://www.openstack.org/community/" class="drop" id="dropdownMenuCommunity">Community <i class="fa fa-caret-down"></i></a><i class="mobile-expand"></i>
+ <ul class="dropdown-menu dropdown-hover" role="menu" aria-labelledby="dropdownMenuCommunity">
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/community/">Welcome! Start Here</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/foundation/">OpenStack Foundation</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://wiki.openstack.org">OpenStack Wiki</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="http://groups.openstack.org">User Groups</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/community/speakers/">Speakers Bureau</a></li>
+ <li role="presentation" class="divider"></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/foundation/companies/">Supporting Companies</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/community/jobs/">Jobs</a></li>
+ <li role="presentation" class="divider"></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/join/">Join The Community</a></li>
+ </ul>
+</li>
+<li>
+ <a href="https://www.openstack.org/marketplace/">Marketplace</a>
+</li>
+<li>
+ <a href="https://www.openstack.org/events/" class="drop" id="dropdownMenuEvents">Events <i class="fa fa-caret-down"></i></a><i class="mobile-expand"></i>
+ <ul class="dropdown-menu dropdown-hover" role="menu" aria-labelledby="dropdownMenuEvents">
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/community/events/">Overview</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/summit/">The OpenStack Summit</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/ptg/">Project Teams Gathering</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/community/events/openstackdays">OpenStack Days</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/community/events/openstackhackathons">OpenStack App Hackathons</a></li>
+ </ul>
+</li>
+<li>
+ <a href="https://www.openstack.org/learn/" class="drop" id="dropdownMenuLearn">Learn <i class="fa fa-caret-down"></i></a><i class="mobile-expand"></i>
+ <ul class="dropdown-menu dropdown-hover" role="menu" aria-labelledby="dropdownMenuEvents">
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/marketplace/training/">Training</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/coa/">Get Certified</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://ask.openstack.org">Ask a Technical Question</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="http://superuser.openstack.org">Superuser Magazine</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/videos/">Summit Videos</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/analysts/">Analyst Reports</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/news/">News</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="https://www.openstack.org/blog/">Blog</a></li>
+ </ul>
+</li>
+<li>
+ <a href="http://docs.openstack.org/">Docs</a>
+</li>
+<li>
+
+</li>
+
+
+ <li>
+
+ <li class="join-nav-section">
+ <a href="#" id="dropdownMenuJoin">Join <i class="fa fa-caret-down"></i></a>
+ <ul class="dropdown-menu dropdown-hover" role="menu" aria-labelledby="dropdownMenuJoin" style="display: none;">
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="/join/register/?membership-type=foundation">Sign up for Foundation Membership</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="/join/#sponsor">Sponsor the Foundation</a></li>
+ <li role="presentation"><a role="menuitem" tabindex="-1" href="/foundation">More about the Foundation</a></li>
+ </ul>
+ </li>
+ <li>
+ <a href="/Security/login/?BackURL=/brand/logo-request/" class="sign-in-btn">Log In</a>
+ </li>
+
+ </li>
+ </ul>
+ </div>
+ <!-- /.navbar-collapse -->
+</div>
+<!-- /.container -->
+</nav>
+
+
+ <!-- Page Content -->
+ <div class="container">
+
+ <div class="container">
+
+ <div class="row">
+ <div class="col-lg-9 col-lg-push-3">
+
+
+ <h1>Request information on OpenStack trademark licensing</h1>
+<p>If you plan to offer an OpenStack-related product or service using a trademark or brand that includes an OpenStack mark (e.g. logo or the word OpenStack), you are required to apply for and obtain a trademark license. We’ve created a family of logos and a set of standards specifically for this purpose. Once we understand more about your product or service, we can determine which (if any) logo program it falls under, and send you the appropriate license for signature.  </p>
+
+<form id="OsLogoProgramForm_Form" action="/brand/logo-request/Form" method="post" enctype="application/x-www-form-urlencoded">
+
+
+ <p id="OsLogoProgramForm_Form_error" class="message " style="display: none"></p>
+
+
+ <fieldset>
+
+
+ <div id="FirstName" class="field text">
+ <label class="left" for="OsLogoProgramForm_Form_FirstName">First Name</label>
+ <div class="middleColumn">
+ <input type="text" name="FirstName" class="text form-control" id="OsLogoProgramForm_Form_FirstName" required="required" aria-required="true" />
+ </div>
+
+
+
+</div>
+
+
+ <div id="Surname" class="field text">
+ <label class="left" for="OsLogoProgramForm_Form_Surname">Last Name</label>
+ <div class="middleColumn">
+ <input type="text" name="Surname" class="text form-control" id="OsLogoProgramForm_Form_Surname" required="required" aria-required="true" />
+ </div>
+
+
+
+</div>
+
+
+ <div id="Email" class="field email text">
+ <label class="left" for="OsLogoProgramForm_Form_Email">Email Address</label>
+ <div class="middleColumn">
+ <input type="email" name="Email" class="email text form-control" id="OsLogoProgramForm_Form_Email" required="required" aria-required="true" />
+ </div>
+
+
+
+</div>
+
+
+ <div id="Phone" class="field text">
+ <label class="left" for="OsLogoProgramForm_Form_Phone">Phone Number</label>
+ <div class="middleColumn">
+ <input type="text" name="Phone" class="text form-control" id="OsLogoProgramForm_Form_Phone" required="required" aria-required="true" />
+ </div>
+
+
+
+</div>
+
+
+ <div id="Program" class="field optionset checkboxset">
+ <label class="left">Which logo program best fits your product offering?</label>
+ <div class="middleColumn">
+ <ul id="OsLogoProgramForm_Form_Program" class="optionset checkboxset" >
+
+
+ <li class="odd valPowered">
+ <input id="OsLogoProgramForm_Form_Program_Powered" class="checkbox" name="Program[Powered]" type="checkbox" value="Powered" />
+ <label for="OsLogoProgramForm_Form_Program_Powered">Powered</label>
+ </li>
+
+ <li class="even valCompatible">
+ <input id="OsLogoProgramForm_Form_Program_Compatible" class="checkbox" name="Program[Compatible]" type="checkbox" value="Compatible" />
+ <label for="OsLogoProgramForm_Form_Program_Compatible">Compatible</label>
+ </li>
+
+ <li class="odd valTraining">
+ <input id="OsLogoProgramForm_Form_Program_Training" class="checkbox" name="Program[Training]" type="checkbox" value="Training" />
+ <label for="OsLogoProgramForm_Form_Program_Training">Training</label>
+ </li>
+
+
+</ul>
+ </div>
+
+
+
+</div>
+
+
+ <hr/>
+
+ <div id="CurrentSponsor" class="field checkbox">
+ <input type="checkbox" name="CurrentSponsor" value="1" class="checkbox" id="OsLogoProgramForm_Form_CurrentSponsor" />
+ <label class="right" for="OsLogoProgramForm_Form_CurrentSponsor">My company is a Corporate Sponsor or Gold/Platinum Member of the OpenStack Foundation.</label>
+
+
+</div>
+
+
+ <div id="openstack-companies">
+
+ <div id="CompanyID" class="field dropdown">
+ <label class="left" for="OsLogoProgramForm_Form_CompanyID">Company</label>
+ <div class="middleColumn">
+ <select name="CompanyID" class="dropdown form-control" id="OsLogoProgramForm_Form_CompanyID">
+
+ <option value="988">3CX</option>
+
+ <option value="961">6WIND</option>
+
+ <option value="254">99Cloud Inc.</option>
+
+ <option value="864">@IT</option>
+
+ <option value="503">A10 Networks</option>
+
+ <option value="677">Accelerite</option>
+
+ <option value="786">Accenture</option>
+
+ <option value="800">Access Alto</option>
+
+ <option value="570">AcmeCloud</option>
+
+ <option value="752">AeroFS (Air Computing, Inc.)</option>
+
+ <option value="928">Agema Systems Inc</option>
+
+ <option value="719">Akanda</option>
+
+ <option value="959">Alta3 Research</option>
+
+ <option value="745">Amax</option>
+
+ <option value="683">Anchor</option>
+
+ <option value="764">Ansible, Inc</option>
+
+ <option value="758">Appcito, Inc</option>
+
+ <option value="780">AppFormix</option>
+
+ <option value="169">Aptira</option>
+
+ <option value="55">Arista Networks</option>
+
+ <option value="986">ARM</option>
+
+ <option value="941">Arrow Electronics</option>
+
+ <option value="183">AT&amp;T</option>
+
+ <option value="903">Attivo Networks</option>
+
+ <option value="907">ATTO Research</option>
+
+ <option value="613">AURO</option>
+
+ <option value="320">Avaya</option>
+
+ <option value="751">Avni Networks Inc</option>
+
+ <option value="954">Award Solutions</option>
+
+ <option value="843">AWcloud</option>
+
+ <option value="1058">BBVA</option>
+
+ <option value="958">Beijing GuoDianTong Network Technology</option>
+
+ <option value="912">Beyondsoft Consulting</option>
+
+ <option value="916">Biarca</option>
+
+ <option value="663">BIOS IT</option>
+
+ <option value="1045">Blizzard Entertainment</option>
+
+ <option value="667">Bloomberg</option>
+
+ <option value="416">Blue Box</option>
+
+ <option value="735">Breqwatr</option>
+
+ <option value="459">Bright Computing</option>
+
+ <option value="74">Brocade</option>
+
+ <option value="72">Bull</option>
+
+ <option value="849">BusinessIT</option>
+
+ <option value="636">c3dna</option>
+
+ <option value="322">Canadian Web Hosting</option>
+
+ <option value="57">Canonical</option>
+
+ <option value="757">Caringo</option>
+
+ <option value="348">Cavium</option>
+
+ <option value="149">CCAT </option>
+
+ <option value="1054">CENGN</option>
+
+ <option value="744">Chef</option>
+
+ <option value="1006">China Mobile</option>
+
+ <option value="1017">China Telecom</option>
+
+ <option value="1062">China Unicom</option>
+
+ <option value="846">Chinac Corporation</option>
+
+ <option value="882">ChinaCloud</option>
+
+ <option value="1031">CIO Review</option>
+
+ <option value="743">Cirba Inc.</option>
+
+ <option value="59">Cisco</option>
+
+ <option value="8">Citrix</option>
+
+ <option value="695">City Network</option>
+
+ <option value="766">Cleversafe</option>
+
+ <option value="572">Cliqr</option>
+
+ <option value="933">Cloud Computing Taiwan</option>
+
+ <option value="740">Cloud Foundry</option>
+
+ <option value="687">Cloud&amp;Heat Technologies</option>
+
+ <option value="664">cloud4u</option>
+
+ <option value="448">Cloudbase Solutions</option>
+
+ <option value="660">CloudFounders</option>
+
+ <option value="888">Cloudify</option>
+
+ <option value="635">CloudOrbit</option>
+
+ <option value="23">Cloudscaling</option>
+
+ <option value="1048">Cloudvisory</option>
+
+ <option value="252">Cloudwatt</option>
+
+ <option value="1039">CNCF</option>
+
+ <option value="905">Codership</option>
+
+ <option value="819">CodiLime SP (DeepSense.io)</option>
+
+ <option value="309">Comcast</option>
+
+ <option value="924">Concurrent</option>
+
+ <option value="277">Coraid</option>
+
+ <option value="774">CoreOS</option>
+
+ <option value="591">Cray</option>
+
+ <option value="397">Cumulus Networks</option>
+
+ <option value="622">DataCentred</option>
+
+ <option value="980">Datang Gohighsec Information Tech</option>
+
+ <option value="889">Datera</option>
+
+ <option value="932">DDN Storage</option>
+
+ <option value="9">Dell</option>
+
+ <option value="260">Dell EMC</option>
+
+ <option value="195">Deutsche Telekom</option>
+
+ <option value="659">Docker, Inc.</option>
+
+ <option value="1024">E8 Storage</option>
+
+ <option value="996">EANTC</option>
+
+ <option value="506">EasyStack</option>
+
+ <option value="1021">Ecloud</option>
+
+ <option value="645">Elastx AB</option>
+
+ <option value="594">Emulex Corporation</option>
+
+ <option value="168">eNovance</option>
+
+ <option value="754">Enter Cloud Suite</option>
+
+ <option value="1030">Enterprise DB</option>
+
+ <option value="866">EnterpriseZine</option>
+
+ <option value="931">Enzu</option>
+
+ <option value="753">Eplexity</option>
+
+ <option value="216">Ericsson</option>
+
+ <option value="160">F5 Networks</option>
+
+ <option value="1050">FD.io</option>
+
+ <option value="835">Fiberhome Telecommunication Technologies</option>
+
+ <option value="773">Firefly</option>
+
+ <option value="632">Flex</option>
+
+ <option value="488">Flexiant</option>
+
+ <option value="765">Fortinet</option>
+
+ <option value="403">Fujitsu</option>
+
+ <option value="307">Fusion-io</option>
+
+ <option value="902">FusionStorm</option>
+
+ <option value="244">Gale Technologies</option>
+
+ <option value="823">Gemini Open Cloud Computing</option>
+
+ <option value="1023">Genesis Hosting</option>
+
+ <option value="939">Gigamon</option>
+
+ <option value="925">Global Knowledge</option>
+
+ <option value="521">GoDaddy</option>
+
+ <option value="859">Google Cloud Platform</option>
+
+ <option value="906">GroundWork Open Source Inc.</option>
+
+ <option value="640">GuardiCore</option>
+
+ <option value="1055">HAProxy Technologies</option>
+
+ <option value="775">HCL</option>
+
+ <option value="908">Hedvig Inc.</option>
+
+ <option value="344">Hitachi </option>
+
+ <option value="1072">Host Telecom</option>
+
+ <option value="1059">HPE</option>
+
+ <option value="248">Huawei</option>
+
+ <option value="824">HyperHQ Inc.</option>
+
+ <option value="235">IBM</option>
+
+ <option value="573">INFINIDAT</option>
+
+ <option value="829">InfinitiesSoft Solutions Inc.</option>
+
+ <option value="628">Infoblox</option>
+
+ <option value="291">Inktank</option>
+
+ <option value="605">Inspur</option>
+
+ <option value="26">Intel</option>
+
+ <option value="41">Internap </option>
+
+ <option value="646">inwinSTACK</option>
+
+ <option value="755">ISA Technologies, Inc.</option>
+
+ <option value="853">IT Leaders</option>
+
+ <option value="638">it-novum</option>
+
+ <option value="865">ITmedia Enterprise</option>
+
+ <option value="806">ITOCHU</option>
+
+ <option value="820">ITRI</option>
+
+ <option value="749">JFrog</option>
+
+ <option value="1042">Joyent</option>
+
+ <option value="220">Juniper Networks</option>
+
+ <option value="261">KIO Networks</option>
+
+ <option value="502">Kontron</option>
+
+ <option value="927">Kubernetes</option>
+
+ <option value="720">Lenovo</option>
+
+ <option value="870">Linux Academy</option>
+
+ <option value="409">Linux Foundation</option>
+
+ <option value="1063">Logicalis</option>
+
+ <option value="1052">Loom Systems</option>
+
+ <option value="922">MemoScale</option>
+
+ <option value="71">Memset</option>
+
+ <option value="247">Metacloud</option>
+
+ <option value="1028">Micron Technology</option>
+
+ <option value="39">Midokura</option>
+
+ <option value="105">Mirantis</option>
+
+ <option value="121">MPSTOR</option>
+
+ <option value="135">Nebula</option>
+
+ <option value="150">NEC</option>
+
+ <option value="832">Net One Systems Co., Ltd</option>
+
+ <option value="80">NetApp</option>
+
+ <option value="894">Netronome</option>
+
+ <option value="699">NetScout</option>
+
+ <option value="525">New H3C Technologies Co., Limited</option>
+
+ <option value="202">Nexenta</option>
+
+ <option value="242">Nexus, a Dimension Data Co</option>
+
+ <option value="887">NGINX</option>
+
+ <option value="253">Nimbula</option>
+
+ <option value="625">Nokia</option>
+
+ <option value="776">NTT Communications</option>
+
+ <option value="818">NTT Software Innovation Center / NTT Group</option>
+
+ <option value="222">Nuage Networks</option>
+
+ <option value="688">Nubeliu</option>
+
+ <option value="455">Numergy</option>
+
+ <option value="353">Nutanix</option>
+
+ <option value="299">NxtGen</option>
+
+ <option value="184">Objectif Libre</option>
+
+ <option value="840">Okinawa Open Laboratory</option>
+
+ <option value="593">Onyx CCS</option>
+
+ <option value="1018">OP5</option>
+
+ <option value="1044">Open Compute</option>
+
+ <option value="895">Open Platform for NFV</option>
+
+ <option value="844">Open Source Storage, LLC</option>
+
+ <option value="1033">Open Switch</option>
+
+ <option value="822">Open vStorage</option>
+
+ <option value="1034">Open vSwitch</option>
+
+ <option value="665">OpenCloudware XLcloud</option>
+
+ <option value="1032">OpenSource.com</option>
+
+ <option value="433">OpenStack Foundation</option>
+
+ <option value="847">OpenVZ sponsored by Odin</option>
+
+ <option value="473">Oracle</option>
+
+ <option value="592">Orange</option>
+
+ <option value="1027">Ormuco</option>
+
+ <option value="856">OSDN</option>
+
+ <option value="783">OSPod</option>
+
+ <option value="698">OVH</option>
+
+ <option value="1071">Packt</option>
+
+ <option value="791">Parallels</option>
+
+ <option value="657">Paris Region Enterprises</option>
+
+ <option value="249">PayPal</option>
+
+ <option value="880">Penguin Computing</option>
+
+ <option value="50">Piston Cloud Computing, Inc.</option>
+
+ <option value="718">Platform9 Systems, Inc</option>
+
+ <option value="710">PLUMgrid</option>
+
+ <option value="702">Produban</option>
+
+ <option value="893">Project Calico</option>
+
+ <option value="1037">Promise Cloud Solutions</option>
+
+ <option value="863">Publickey</option>
+
+ <option value="603">Pure Storage</option>
+
+ <option value="604">QCT (Quanta Cloud Technology)</option>
+
+ <option value="634">Qosmos</option>
+
+ <option value="1">Rackspace</option>
+
+ <option value="750">Rancher Labs</option>
+
+ <option value="644">Ravello Systems</option>
+
+ <option value="227">Red Hat, Inc.</option>
+
+ <option value="250">RiverMeadow Software</option>
+
+ <option value="983">Samsung</option>
+
+ <option value="612">SAP</option>
+
+ <option value="489">Sardina Systems</option>
+
+ <option value="297">Scality</option>
+
+ <option value="1051">SDX</option>
+
+ <option value="787">SDX Central</option>
+
+ <option value="276">Seagate</option>
+
+ <option value="447">Servergy</option>
+
+ <option value="747">SevOne</option>
+
+ <option value="1046">Shanghai Engineering Research Center for Broadband Technologies &amp; Applications</option>
+
+ <option value="709">SI-TECH</option>
+
+ <option value="971">Sihua Technology</option>
+
+ <option value="969">SkyAtlas</option>
+
+ <option value="860">Skytap Inc</option>
+
+ <option value="113">SolidFire</option>
+
+ <option value="332">Solinea</option>
+
+ <option value="684">StackIQ</option>
+
+ <option value="626">StackStorm</option>
+
+ <option value="631">StackVelocity</option>
+
+ <option value="643">Storage Made Easy</option>
+
+ <option value="283">Stratus Technologies</option>
+
+ <option value="772">Supermicro</option>
+
+ <option value="910">SuperUser</option>
+
+ <option value="962">SurCloud</option>
+
+ <option value="987">Sureline Systems</option>
+
+ <option value="159">SUSE</option>
+
+ <option value="205">SwiftStack Inc</option>
+
+ <option value="871">T2 Cloud</option>
+
+ <option value="1053">Target</option>
+
+ <option value="697">Tata Communications</option>
+
+ <option value="854">TECH.ASCII</option>
+
+ <option value="784">TechTarget</option>
+
+ <option value="990">TelecomTV</option>
+
+ <option value="1049">Telefónica</option>
+
+ <option value="686">teuto.net</option>
+
+ <option value="361">Thales Group</option>
+
+ <option value="782">The Cube</option>
+
+ <option value="911">The New Stack</option>
+
+ <option value="848">ThinkIT</option>
+
+ <option value="734">Tintri</option>
+
+ <option value="633">Toshiba</option>
+
+ <option value="504">TrilioData</option>
+
+ <option value="742">Tufin</option>
+
+ <option value="940">UKCloud</option>
+
+ <option value="623">Ultimum Technologies s.r.o.</option>
+
+ <option value="374">UnitedStack Inc.</option>
+
+ <option value="215">UOLDIVEO</option>
+
+ <option value="926">UTSA Open Cloud Institute</option>
+
+ <option value="781">vBrownBag</option>
+
+ <option value="321">VCE</option>
+
+ <option value="873">Veritas Technologies</option>
+
+ <option value="945">Verizon</option>
+
+ <option value="120">VEXXHOST, Inc.</option>
+
+ <option value="571">Violin Memory</option>
+
+ <option value="1038">VirTool Networks</option>
+
+ <option value="474">Virtuozzo</option>
+
+ <option value="243">VMware</option>
+
+ <option value="909">Volkswagen AG</option>
+
+ <option value="989">vScaler Ltd.</option>
+
+ <option value="963">Walmart Labs</option>
+
+ <option value="839">Wanclouds</option>
+
+ <option value="1026">Wells Fargo</option>
+
+ <option value="431">Western Digital Corporation</option>
+
+ <option value="475">Wind River</option>
+
+ <option value="219">Xemeti</option>
+
+ <option value="1015">XILINX INC.</option>
+
+ <option value="203">Yahoo Inc.</option>
+
+ <option value="838">Yahoo! Japan</option>
+
+ <option value="872">ZDNet Japan</option>
+
+ <option value="825">ZeroStack</option>
+
+ <option value="430">ZTE Corporation</option>
+
+ <option value="858">クラウドWatch</option>
+
+ <option value="855">スラド</option>
+
+ <option value="857">日経Linux</option>
+
+</select>
+
+ </div>
+
+
+
+</div>
+
+
+ <div id="OtherCompany" class="field text">
+ <label class="left" for="OsLogoProgramForm_Form_OtherCompany">Other Company (if not listed above)</label>
+ <div class="middleColumn">
+ <input type="text" name="OtherCompany" class="text form-control" id="OsLogoProgramForm_Form_OtherCompany" />
+ </div>
+
+
+
+</div>
+
+
+ </div>
+
+ <div id="non-sponsor-company">
+
+ <div id="NonSponsorCompany" class="field text">
+ <label class="left" for="OsLogoProgramForm_Form_NonSponsorCompany">Company Name</label>
+ <div class="middleColumn">
+ <input type="text" name="NonSponsorCompany" class="text form-control" id="OsLogoProgramForm_Form_NonSponsorCompany" />
+ </div>
+
+
+
+</div>
+
+
+ </div>
+
+ <div id="Product" class="field text">
+ <label class="left" for="OsLogoProgramForm_Form_Product">Product or Service Name</label>
+ <div class="middleColumn">
+ <input type="text" name="Product" class="text form-control" id="OsLogoProgramForm_Form_Product" />
+ </div>
+
+
+
+</div>
+
+
+ If your proposed product name includes the OpenStack word mark, it will need to be approved as part of the licensing process.<br><br>
+
+ <hr/>
+
+ <div id="CompanyDetails" class="field textarea">
+ <label class="left" for="OsLogoProgramForm_Form_CompanyDetails">Product or Service Description</label>
+ <div class="middleColumn">
+ <textarea name="CompanyDetails" class="textarea form-control" id="OsLogoProgramForm_Form_CompanyDetails" rows="5" cols="20"></textarea>
+ </div>
+
+
+
+</div>
+
+
+ <div id="Category" class="field optionset checkboxset">
+ <label class="left">Which of the following categories does your product fit into? This will help us recommend the approprite licensing and associated marketing programs and assets:</label>
+ <div class="middleColumn">
+ <ul id="OsLogoProgramForm_Form_Category" class="optionset checkboxset" >
+
+
+ <li class="odd valPublic_Clouds">
+ <input id="OsLogoProgramForm_Form_Category_PublicClouds" class="checkbox" name="Category[Public Clouds]" type="checkbox" value="Public Clouds" />
+ <label for="OsLogoProgramForm_Form_Category_PublicClouds">Public Clouds</label>
+ </li>
+
+ <li class="even valDistributions">
+ <input id="OsLogoProgramForm_Form_Category_Distributions" class="checkbox" name="Category[Distributions]" type="checkbox" value="Distributions" />
+ <label for="OsLogoProgramForm_Form_Category_Distributions">Distributions</label>
+ </li>
+
+ <li class="odd valConverged_Appliances">
+ <input id="OsLogoProgramForm_Form_Category_ConvergedAppliances" class="checkbox" name="Category[Converged Appliances]" type="checkbox" value="Converged Appliances" />
+ <label for="OsLogoProgramForm_Form_Category_ConvergedAppliances">Converged Appliances</label>
+ </li>
+
+ <li class="even valStorage">
+ <input id="OsLogoProgramForm_Form_Category_Storage" class="checkbox" name="Category[Storage]" type="checkbox" value="Storage" />
+ <label for="OsLogoProgramForm_Form_Category_Storage">Storage</label>
+ </li>
+
+ <li class="odd valConsultants___System_Integrators">
+ <input id="OsLogoProgramForm_Form_Category_ConsultantsSystemIntegrators" class="checkbox" name="Category[Consultants & System Integrators]" type="checkbox" value="Consultants & System Integrators" />
+ <label for="OsLogoProgramForm_Form_Category_ConsultantsSystemIntegrators">Consultants & System Integrators</label>
+ </li>
+
+ <li class="even valTraining">
+ <input id="OsLogoProgramForm_Form_Category_Training" class="checkbox" name="Category[Training]" type="checkbox" value="Training" />
+ <label for="OsLogoProgramForm_Form_Category_Training">Training</label>
+ </li>
+
+ <li class="odd valPaaS">
+ <input id="OsLogoProgramForm_Form_Category_PaaS" class="checkbox" name="Category[PaaS]" type="checkbox" value="PaaS" />
+ <label for="OsLogoProgramForm_Form_Category_PaaS">PaaS</label>
+ </li>
+
+ <li class="even valManagement___Monitoring">
+ <input id="OsLogoProgramForm_Form_Category_ManagementMonitoring" class="checkbox" name="Category[Management & Monitoring]" type="checkbox" value="Management & Monitoring" />
+ <label for="OsLogoProgramForm_Form_Category_ManagementMonitoring">Management & Monitoring</label>
+ </li>
+
+ <li class="odd valApps_on_OpenStack">
+ <input id="OsLogoProgramForm_Form_Category_AppsonOpenStack" class="checkbox" name="Category[Apps on OpenStack]" type="checkbox" value="Apps on OpenStack" />
+ <label for="OsLogoProgramForm_Form_Category_AppsonOpenStack">Apps on OpenStack</label>
+ </li>
+
+ <li class="even valCompatible_HW___SW">
+ <input id="OsLogoProgramForm_Form_Category_CompatibleHWSW" class="checkbox" name="Category[Compatible HW & SW]" type="checkbox" value="Compatible HW & SW" />
+ <label for="OsLogoProgramForm_Form_Category_CompatibleHWSW">Compatible Hardware & Software</label>
+ </li>
+
+
+</ul>
+ </div>
+
+
+
+</div>
+
+
+ <div id="Regions" class="field optionset checkboxset">
+ <label class="left">In which regions does your company operate?</label>
+ <div class="middleColumn">
+ <ul id="OsLogoProgramForm_Form_Regions" class="optionset checkboxset" >
+
+
+ <li class="odd valNorth_America">
+ <input id="OsLogoProgramForm_Form_Regions_NorthAmerica" class="checkbox" name="Regions[North America]" type="checkbox" value="North America" />
+ <label for="OsLogoProgramForm_Form_Regions_NorthAmerica">North America</label>
+ </li>
+
+ <li class="even valSouth_America">
+ <input id="OsLogoProgramForm_Form_Regions_SouthAmerica" class="checkbox" name="Regions[South America]" type="checkbox" value="South America" />
+ <label for="OsLogoProgramForm_Form_Regions_SouthAmerica">South America</label>
+ </li>
+
+ <li class="odd valEurope">
+ <input id="OsLogoProgramForm_Form_Regions_Europe" class="checkbox" name="Regions[Europe]" type="checkbox" value="Europe" />
+ <label for="OsLogoProgramForm_Form_Regions_Europe">Europe</label>
+ </li>
+
+ <li class="even valAsia_Pacific">
+ <input id="OsLogoProgramForm_Form_Regions_AsiaPacific" class="checkbox" name="Regions[Asia Pacific]" type="checkbox" value="Asia Pacific" />
+ <label for="OsLogoProgramForm_Form_Regions_AsiaPacific">Asia Pacific</label>
+ </li>
+
+
+</ul>
+ </div>
+
+
+
+</div>
+
+
+ <div id="Projects" class="field optionset checkboxset">
+ <label class="left">Select the OpenStack projects your product uses:</label>
+ <div class="middleColumn">
+ <ul id="OsLogoProgramForm_Form_Projects" class="optionset checkboxset" >
+
+
+ <li class="odd valOpenStack_Compute">
+ <input id="OsLogoProgramForm_Form_Projects_OpenStackCompute" class="checkbox" name="Projects[OpenStack Compute]" type="checkbox" value="OpenStack Compute" />
+ <label for="OsLogoProgramForm_Form_Projects_OpenStackCompute">OpenStack Compute</label>
+ </li>
+
+ <li class="even valOpenStack_Object_Storage">
+ <input id="OsLogoProgramForm_Form_Projects_OpenStackObjectStorage" class="checkbox" name="Projects[OpenStack Object Storage]" type="checkbox" value="OpenStack Object Storage" />
+ <label for="OsLogoProgramForm_Form_Projects_OpenStackObjectStorage">OpenStack Object Storage</label>
+ </li>
+
+ <li class="odd valOpenStack_Image_Service">
+ <input id="OsLogoProgramForm_Form_Projects_OpenStackImageService" class="checkbox" name="Projects[OpenStack Image Service]" type="checkbox" value="OpenStack Image Service" />
+ <label for="OsLogoProgramForm_Form_Projects_OpenStackImageService">OpenStack Image Service</label>
+ </li>
+
+ <li class="even valOpenStack_Networking">
+ <input id="OsLogoProgramForm_Form_Projects_OpenStackNetworking" class="checkbox" name="Projects[OpenStack Networking]" type="checkbox" value="OpenStack Networking" />
+ <label for="OsLogoProgramForm_Form_Projects_OpenStackNetworking">OpenStack Networking</label>
+ </li>
+
+ <li class="odd valOpenStack_Dashboard">
+ <input id="OsLogoProgramForm_Form_Projects_OpenStackDashboard" class="checkbox" name="Projects[OpenStack Dashboard]" type="checkbox" value="OpenStack Dashboard" />
+ <label for="OsLogoProgramForm_Form_Projects_OpenStackDashboard">OpenStack Dashboard</label>
+ </li>
+
+ <li class="even valOpenStack_Orchestration">
+ <input id="OsLogoProgramForm_Form_Projects_OpenStackOrchestration" class="checkbox" name="Projects[OpenStack Orchestration]" type="checkbox" value="OpenStack Orchestration" />
+ <label for="OsLogoProgramForm_Form_Projects_OpenStackOrchestration">OpenStack Orchestration</label>
+ </li>
+
+ <li class="odd valOpenStack_Identity">
+ <input id="OsLogoProgramForm_Form_Projects_OpenStackIdentity" class="checkbox" name="Projects[OpenStack Identity]" type="checkbox" value="OpenStack Identity" />
+ <label for="OsLogoProgramForm_Form_Projects_OpenStackIdentity">OpenStack Identity</label>
+ </li>
+
+ <li class="even valOpenStack_Metering">
+ <input id="OsLogoProgramForm_Form_Projects_OpenStackMetering" class="checkbox" name="Projects[OpenStack Metering]" type="checkbox" value="OpenStack Metering" />
+ <label for="OsLogoProgramForm_Form_Projects_OpenStackMetering">OpenStack Metering</label>
+ </li>
+
+ <li class="odd valOpenStack_Block_Storage">
+ <input id="OsLogoProgramForm_Form_Projects_OpenStackBlockStorage" class="checkbox" name="Projects[OpenStack Block Storage]" type="checkbox" value="OpenStack Block Storage" />
+ <label for="OsLogoProgramForm_Form_Projects_OpenStackBlockStorage">OpenStack Block Storage</label>
+ </li>
+
+
+</ul>
+ </div>
+
+
+
+</div>
+
+
+ <div id="APIExposed" class="field checkbox">
+ <input type="checkbox" name="APIExposed" value="1" class="checkbox" id="OsLogoProgramForm_Form_APIExposed" />
+ <label class="right" for="OsLogoProgramForm_Form_APIExposed">My product exposes the OpenStack API</label>
+
+
+</div>
+
+
+ <div id="field_98438688" class="field text honey">
+ <label class="left" for="OsLogoProgramForm_Form_field_98438688">field_98438688</label>
+ <div class="middleColumn">
+ <input type="text" name="field_98438688" class="text honey form-control" id="OsLogoProgramForm_Form_field_98438688" />
+ </div>
+
+
+
+</div>
+
+
+ <input type="hidden" name="SecurityID" value="618918bae16ecff556e548f5dfd6eb0c9d3c79e5" class="hidden form-control" id="OsLogoProgramForm_Form_SecurityID" />
+
+
+ <div class="clear"><!-- --></div>
+ </fieldset>
+
+
+ <div class="Actions">
+
+
+ <input type="submit" name="action_save" value="Request Information" class="action" id="OsLogoProgramForm_Form_action_save" />
+
+
+
+ </div>
+
+
+</form>
+
+
+
+
+ </div> <!-- Close content div -->
+ <div class="col-lg-3 col-lg-pull-9">
+ <div class="newSubNav">
+ <ul class="overviewNav">
+
+ <li id="brand"><a href="/brand/" title="Go to the &Title&quot; page" class="section">Branding <i class="fa fa-chevron-right"></i></a></li>
+
+
+ <li id="openstack-trademark-policy"><a href="/brand/openstack-trademark-policy/" title="Go to the &quot;OpenStack Trademark Policy&quot; page" class="link">OpenStack Trademark Policy <i class="fa fa-chevron-right"></i></a></li>
+
+ <li id="web-badges"><a href="/brand/web-badges/" title="Go to the &quot;OpenStack Web Badges&quot; page" class="link">Web Badges <i class="fa fa-chevron-right"></i></a></li>
+
+ <li id="openstack-logo"><a href="/brand/openstack-logo/" title="Go to the &quot;OpenStack Logo&quot; page" class="link">OpenStack Logo <i class="fa fa-chevron-right"></i></a></li>
+
+ <li id="openstack-compatible"><a href="/brand/openstack-compatible/" title="Go to the &quot;OpenStack Compatible Logo&quot; page" class="link">OpenStack Compatible <i class="fa fa-chevron-right"></i></a></li>
+
+ <li id="event-policy"><a href="/brand/event-policy/" title="Go to the &quot;OpenStack Event Policy&quot; page" class="link">OpenStack Event Policy <i class="fa fa-chevron-right"></i></a></li>
+
+ <li id="openstack-blog-code-of-conduct"><a href="/brand/openstack-blog-code-of-conduct/" title="Go to the &quot;OpenStack Blog Code of Conduct&quot; page" class="link">Blog Code of Conduct <i class="fa fa-chevron-right"></i></a></li>
+
+ <li id="openstack-powered"><a href="/brand/openstack-powered/" title="Go to the &quot;OpenStack Powered&quot; page" class="link">OpenStack Powered <i class="fa fa-chevron-right"></i></a></li>
+
+ <li id="openstack-training"><a href="/brand/openstack-training/" title="Go to the &quot;OpenStack Training&quot; page" class="link">OpenStack Training Logo <i class="fa fa-chevron-right"></i></a></li>
+
+ <li id="interop"><a href="/brand/interop/" title="Go to the &quot;Interop&quot; page" class="link">Interop <i class="fa fa-chevron-right"></i></a></li>
+
+ </ul>
+</div>
+ </div>
+ </div> <!-- Close row div -->
+
+</div>
+ </div>
+
+ <footer>
+ <div class="container">
+ <div class="row footer-links">
+ <div class="col-lg-2 col-sm-2">
+ <h3>OpenStack</h3>
+ <ul>
+ <li><a href="//openstack.org/projects/">Projects</a></li>
+ <li><a href="//openstack.org/software/security/">OpenStack Security</a></li>
+ <li><a href="//openstack.org/projects/openstack-faq/">Common Questions</a></li>
+ <li><a href="https://openstack.org/blog/">Blog</a></li>
+ <li><a href="//openstack.org/news/">News</a></li>
+ </ul>
+ </div>
+ <div class="col-lg-2 col-sm-2">
+ <h3>Community</h3>
+ <ul>
+ <li><a href="//openstack.org/community/">User Groups</a></li>
+ <li><a href="//openstack.org/community/events/">Events</a></li>
+ <li><a href="//openstack.org/community/jobs/">Jobs</a></li>
+ <li><a href="//openstack.org/foundation/companies/">Companies</a></li>
+ <li><a href="http://docs.openstack.org/infra/manual/developers.html">Contribute</a></li>
+ <li><a href="//openstack.org/store">Get Swag!</a></li>
+ </ul>
+ </div>
+ <div class="col-lg-2 col-sm-2">
+ <h3>Documentation</h3>
+ <ul>
+ <li><a href="http://docs.openstack.org">OpenStack Manuals</a></li>
+ <li><a href="//openstack.org/software/start/">Getting Started</a></li>
+ <li><a href="http://developer.openstack.org">API Documentation</a></li>
+ <li><a href="https://wiki.openstack.org">Wiki</a></li>
+ </ul>
+ </div>
+ <div class="col-lg-2 col-sm-2">
+ <h3>Branding & Legal</h3>
+ <ul>
+ <li><a href="//openstack.org/brand/">Logos & Guidelines</a></li>
+ <li><a href="//openstack.org/brand/openstack-trademark-policy/">Trademark Policy</a></li>
+ <li><a href="//openstack.org/privacy/">Privacy Policy</a></li>
+ <li><a href="https://wiki.openstack.org/wiki/How_To_Contribute#Contributor_License_Agreement">OpenStack CLA</a></li>
+ </ul>
+ </div>
+ <div class="col-lg-4 col-sm-4">
+ <h3>Stay In Touch</h3>
+ <a href="https://twitter.com/OpenStack" target="_blank" class="social-icons footer-twitter"></a>
+ <a href="https://www.facebook.com/openstack" target="_blank" class="social-icons footer-facebook"></a>
+ <a href="https://www.linkedin.com/company/openstack" target="_blank" class="social-icons footer-linkedin"></a>
+ <a href="https://www.youtube.com/user/OpenStackFoundation" target="_blank" class="social-icons footer-youtube"></a>
+ <!-- <form class="form-inline">
+ <div class="form-group newsletter-form">
+ <label>Join Our Newsletter</label>
+ <input class="newsletter-input" type="input" placeholder="Email">
+ <button type="submit" class="newsletter-btn">Join</button>
+ </div>
+ </form> -->
+ <p class="fine-print">
+ The OpenStack project is provided under the Apache 2.0 license. Openstack.org is powered by <a href="https://rackspace.com" target="_blank">Rackspace Cloud Computing</a>.
+ </p>
+ </div>
+ </div>
+ </div>
+ </footer>
+ <div class="footer-bottom">
+ <div class="container">
+ <form class="form-inline" id="FeedbackForm_FeedbackForm" action="/brand/logo-request/FeedbackForm" method="post" enctype="application/x-www-form-urlencoded">
+ <div class="form-group">
+ <div>
+ <fieldset class="footer-feedback-fieldset">
+ <input class="feedback-input" type="input" placeholder="Give Us Your Feedback On This Page" id="FeedbackForm_FeedbackForm_Content" name="Content">
+ <input type="hidden" name="SecurityID" value="618918bae16ecff556e548f5dfd6eb0c9d3c79e5" class="hidden form-control" id="FeedbackForm_FeedbackForm_SecurityID" />
+
+ <button type="submit" class="feedback-btn" id="FeedbackForm_FeedbackForm_action_submitFeedback" name="action_submitFeedback">Submit</button>
+ </fieldset>
+ </div>
+ </div>
+</form>
+ </div>
+ </div>
+ <!-- Quantcast Tag -->
+<script type="text/javascript">
+var _qevents = _qevents || [];
+
+(function() {
+var elem = document.createElement('script');
+elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
+elem.async = true;
+elem.type = "text/javascript";
+var scpt = document.getElementsByTagName('script')[0];
+scpt.parentNode.insertBefore(elem, scpt);
+})();
+
+_qevents.push({
+qacct:"p-fM0cfazHHeyRH"
+});
+</script>
+
+<noscript>
+<div style="display:none;">
+<img src="//pixel.quantserve.com/pixel/p-fM0cfazHHeyRH.gif" border="0" height="1" width="1" alt="Quantcast"/>
+</div>
+</noscript>
+<!-- End Quantcast tag -->
+ <!-- Twitter universal website tag code -->
+<script>
+ !function(e,t,n,s,u,a){e.twq||(s=e.twq=function(){s.exe?s.exe.apply(s,arguments):s.queue.push(arguments);
+ },s.version='1.1',s.queue=[],u=t.createElement(n),u.async=!0,u.src='//static.ads-twitter.com/uwt.js',
+ a=t.getElementsByTagName(n)[0],a.parentNode.insertBefore(u,a))}(window,document,'script');
+ // Insert Twitter Pixel ID and Standard Event data below
+ twq('init','nxuu6');
+ twq('track','PageView');
+</script>
+<!-- End Twitter universal website tag code -->
+ </body>
+ <script type="text/javascript">
+ _linkedin_data_partner_id = "36268";
+</script><script type="text/javascript">
+ (function(){var s = document.getElementsByTagName("script")[0];
+ var b = document.createElement("script");
+ b.type = "text/javascript";b.async = true;
+ b.src = "https://snap.licdn.com/li.lms-analytics/insight.min.js";
+ s.parentNode.insertBefore(b, s);})();
+</script>
+</html> \ No newline at end of file
diff --git a/cvp/3rd_party/static/testapi-ui/components/application/modal/confirmModal.html b/cvp/3rd_party/static/testapi-ui/components/application/modal/confirmModal.html
new file mode 100644
index 00000000..749315d0
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/application/modal/confirmModal.html
@@ -0,0 +1,43 @@
+<div>
+ <div class="row" style="margin-top:20px">
+ <div class="col-sm-offset-1 col-sm-11">
+ <div>
+ <label class="col-sm-3">Organization name: </label>
+ <input type="text" class="text col-sm-7 application-modal-text" ng-model="ctrl.organization_name" disabled>
+ </div>
+ <div>
+ <label class="col-sm-3">Organization website: </label>
+ <input type="text" class="text col-sm-7 application-modal-text" ng-model="ctrl.organization_web" disabled>
+ </div>
+ <div>
+ <label class="col-sm-3">Product name: </label>
+ <input type="text" class="text col-sm-7 application-modal-text" ng-model="ctrl.product_name" disabled>
+ </div>
+ <div>
+ <label class="col-sm-3">Product documentation: </label>
+ <input type="text" class="text col-sm-7 application-modal-text" ng-model="ctrl.product_categories" disabled>
+ </div>
+ <div>
+ <label class="col-sm-3">User ID: </label>
+ <input type="text" class="text col-sm-7 application-modal-text" ng-model="ctrl.user_id" disabled>
+ </div>
+ </div>
+ <div class="btn-group col-sm-offset-5 application-modal-button" role="group">
+ <button type="button" class="btn btn-default" ng-click="ctrl.submitForm()">Confirm</button>
+ <button type="button" class="btn btn-default" style="margin-left:20px" ng-click="ctrl.cancelSubmit()">Cancel</button>
+ </div>
+ </div>
+</div>
+
+<style>
+.ngdialog.ngdialog-theme-default.custom-width-60 .ngdialog-content {
+ width: 50%;
+}
+.application-modal-text {
+ margin-bottom: 5px;
+}
+.application-modal-button {
+ margin-top: 10px;
+ margin-bottom: 20px;
+}
+</style>
diff --git a/cvp/3rd_party/static/testapi-ui/components/auth-failure/authFailureController.js b/cvp/3rd_party/static/testapi-ui/components/auth-failure/authFailureController.js
new file mode 100644
index 00000000..29d1d70f
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/auth-failure/authFailureController.js
@@ -0,0 +1,33 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ angular
+ .module('testapiApp')
+ .controller('AuthFailureController', AuthFailureController);
+
+ AuthFailureController.$inject = ['$location', '$state', 'raiseAlert'];
+ /**
+ * TestAPI Auth Failure Controller
+ * This controller handles messages from TestAPI API if user auth fails.
+ */
+ function AuthFailureController($location, $state, raiseAlert) {
+ var ctrl = this;
+ ctrl.message = $location.search().message;
+ raiseAlert('danger', 'Authentication Failure:', ctrl.message);
+ $state.go('home');
+ }
+})();
diff --git a/cvp/3rd_party/static/testapi-ui/components/auth/authPortal.html b/cvp/3rd_party/static/testapi-ui/components/auth/authPortal.html
new file mode 100644
index 00000000..82327695
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/auth/authPortal.html
@@ -0,0 +1,21 @@
+<h3>Sign In</h3>
+<b>Please choose your account provider:</b>
+<div class="row">
+ <div class="col-xs-6 col-md-3">
+ <a ng-click="auth.doSignIn('cas')" class="thumbnail">
+ <img style="width:256px;height:64px" src="https://identity.linuxfoundation.org/sites/all/themes/lfidentity/lflogo2016_color.png" alt="LinuxFoundationID">
+ </a>
+ </div>
+ <div class="col-xs-6 col-md-3">
+ <a ng-click="auth.doSignIn('openstack')" class="thumbnail">
+ <img style="width:256px;height:64px" src="https://www.openstack.org/themes/openstack/images/openstack-logo-full.svg" alt="OPENSTACK">
+ </a>
+ </div>
+ <!--
+ <div class="col-xs-6 col-md-3">
+ <a ng-click="auth.doSignIn('jira')" class="thumbnail">
+ <img style="width:256px;height:64px" src="https://www.linuxfoundation.org/themes/custom/linux_foundation/logo.svg" alt="LinuxFoundationID">
+ </a>
+ </div>
+ -->
+</div>
diff --git a/cvp/3rd_party/static/testapi-ui/components/guidelines/data/danube.json b/cvp/3rd_party/static/testapi-ui/components/guidelines/data/danube.json
new file mode 100644
index 00000000..99613b72
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/guidelines/data/danube.json
@@ -0,0 +1,590 @@
+{
+ "mandatory": {
+ "name": "Mandatory CVP Test Areas",
+ "value": [
+ {
+ "area_name": "Test Area VIM Operations - Compute",
+ "value": [
+ {
+ "api_name": "Image operations within the Compute API",
+ "value": [
+ "tempest.api.compute.images.test_images_oneserver.ImagesOneServerTestJSON.test_create_delete_image",
+ "tempest.api.compute.images.test_images_oneserver.ImagesOneServerTestJSON.test_create_image_specify_multibyte_character_image_name"
+ ]
+ },
+ {
+ "api_name": "Basic support Compute API for server actions such as reboot, rebuild, resize",
+ "value": [
+ "tempest.api.compute.servers.test_instance_actions.InstanceActionsTestJSON.test_get_instance_action",
+ "tempest.api.compute.servers.test_instance_actions.InstanceActionsTestJSON.test_list_instance_actions"
+ ]
+ },
+ {
+ "api_name": "Generate, import, and delete SSH keys within Compute services",
+ "value": [
+ "tempest.api.compute.servers.test_servers.ServersTestJSON.test_create_specify_keypair"
+ ]
+ },
+ {
+ "api_name": "List supported versions of the Compute API",
+ "value": [
+ "tempest.api.compute.test_versions.TestVersions.test_list_api_versions"
+ ]
+ },
+ {
+ "api_name": "Quotas management in Compute API",
+ "value": [
+ "tempest.api.compute.test_quotas.QuotasTestJSON.test_get_default_quotas",
+ "tempest.api.compute.test_quotas.QuotasTestJSON.test_get_quotas"
+ ]
+ },
+ {
+ "api_name": "Basic server operations in the Compute API",
+ "value": [
+ "tempest.api.compute.servers.test_servers.ServersTestJSON.test_create_server_with_admin_password",
+ "tempest.api.compute.servers.test_servers.ServersTestJSON.test_create_with_existing_server_name",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_numeric_server_name",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_server_metadata_exceeds_length_limit",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_server_name_length_exceeds_256",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_with_invalid_flavor",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_with_invalid_image",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_with_invalid_network_uuid",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_delete_server_pass_id_exceeding_length_limit",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_delete_server_pass_negative_id",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_get_non_existent_server",
+ "tempest.api.compute.servers.test_create_server.ServersTestJSON.test_host_name_is_same_as_server_name",
+ "tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_host_name_is_same_as_server_name",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_invalid_ip_v6_address",
+ "tempest.api.compute.servers.test_create_server.ServersTestJSON.test_list_servers",
+ "tempest.api.compute.servers.test_create_server.ServersTestJSON.test_list_servers_with_detail",
+ "tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_list_servers",
+ "tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_list_servers_with_detail",
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_detailed_filter_by_flavor",
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_detailed_filter_by_image",
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_detailed_filter_by_server_name",
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_detailed_filter_by_server_status",
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_detailed_limit_results",
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filter_by_flavor",
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filter_by_image",
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filter_by_limit",
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filter_by_server_name",
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filter_by_server_status",
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filtered_by_name_wildcard",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_changes_since_future_date",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_changes_since_invalid_date",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_limits",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_limits_greater_than_actual_count",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_limits_pass_negative_value",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_limits_pass_string",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_non_existing_flavor",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_non_existing_image",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_non_existing_server_name",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_detail_server_is_deleted",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_status_non_existing",
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_with_a_deleted_server",
+ "tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_lock_unlock_server",
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_delete_server_metadata_item",
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_get_server_metadata_item",
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_list_server_metadata",
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_set_server_metadata",
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_set_server_metadata_item",
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_update_server_metadata",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_server_name_blank",
+ "tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_reboot_non_existent_server",
+ "tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_rebuild_server",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_rebuild_deleted_server",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_rebuild_non_existent_server",
+ "tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_stop_start_server",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_stop_non_existent_server",
+ "tempest.api.compute.servers.test_servers.ServersTestJSON.test_update_access_server_address",
+ "tempest.api.compute.servers.test_servers.ServersTestJSON.test_update_server_name",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_update_name_of_non_existent_server",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_update_server_name_length_exceeds_256",
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_update_server_set_empty_name",
+ "tempest.api.compute.servers.test_create_server.ServersTestJSON.test_verify_created_server_vcpus",
+ "tempest.api.compute.servers.test_create_server.ServersTestJSON.test_verify_server_details",
+ "tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_verify_created_server_vcpus",
+ "tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_verify_server_details"
+ ]
+ },
+ {
+ "api_name": "Retrieve volume information through the Compute API",
+ "value": [
+ "tempest.api.compute.volumes.test_attach_volume.AttachVolumeTestJSON.test_attach_detach_volume",
+ "tempest.api.compute.volumes.test_attach_volume.AttachVolumeTestJSON.test_list_get_volume_attachments"
+ ]
+ }
+ ]
+ },
+ {
+ "area_name": "Test Area VIM Operations - Identity",
+ "value": [
+ {
+ "api_name": "API discovery operations within the Identity v3 API",
+ "value": [
+ "tempest.api.identity.v3.test_api_discovery.TestApiDiscovery.test_api_media_types",
+ "tempest.api.identity.v3.test_api_discovery.TestApiDiscovery.test_api_version_resources",
+ "tempest.api.identity.v3.test_api_discovery.TestApiDiscovery.test_api_version_statuses"
+ ]
+ },
+ {
+ "api_name": "Auth operations within the Identity API",
+ "value": [
+ "tempest.api.identity.v3.test_tokens.TokensV3Test.test_create_token"
+ ]
+ }
+ ]
+ },
+ {
+ "area_name": "Test Area VIM Operations - Image",
+ "value": [
+ {
+ "api_name": "Image deletion tests using the Glance v2 API",
+ "value": [
+ "tempest.api.image.v2.test_images.BasicOperationsImagesTest.test_delete_image",
+ "tempest.api.image.v2.test_images_negative.ImagesNegativeTest.test_delete_image_null_id",
+ "tempest.api.image.v2.test_images_negative.ImagesNegativeTest.test_delete_non_existing_image",
+ "tempest.api.image.v2.test_images_tags_negative.ImagesTagsNegativeTest.test_delete_non_existing_tag"
+ ]
+ },
+ {
+ "api_name": "Image get tests using the Glance v2 API",
+ "value": [
+ "tempest.api.image.v2.test_images.ListImagesTest.test_get_image_schema",
+ "tempest.api.image.v2.test_images.ListImagesTest.test_get_images_schema",
+ "tempest.api.image.v2.test_images_negative.ImagesNegativeTest.test_get_delete_deleted_image",
+ "tempest.api.image.v2.test_images_negative.ImagesNegativeTest.test_get_image_null_id",
+ "tempest.api.image.v2.test_images_negative.ImagesNegativeTest.test_get_non_existent_image"
+ ]
+ },
+ {
+ "api_name": "CRUD image operations in Images API v2",
+ "value": [
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_no_params"
+ ]
+ },
+ {
+ "api_name": "Image list tests using the Glance v2 API",
+ "value": [
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_container_format",
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_disk_format",
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_limit",
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_min_max_size",
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_size",
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_status",
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_visibility"
+ ]
+ },
+ {
+ "api_name": "Image update tests using the Glance v2 API",
+ "value": [
+ "tempest.api.image.v2.test_images.BasicOperationsImagesTest.test_update_image",
+ "tempest.api.image.v2.test_images_tags.ImagesTagsTest.test_update_delete_tags_for_image",
+ "tempest.api.image.v2.test_images_tags_negative.ImagesTagsNegativeTest.test_update_tags_for_non_existing_image"
+ ]
+ }
+ ]
+ },
+ {
+ "area_name": "Test Area VIM Operations - Network",
+ "value": [
+ {
+ "api_name": "Basic CRUD operations on L2 networks and L2 network ports",
+ "value": [
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_all_attributes",
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_with_allocation_pools",
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_with_dhcp_enabled",
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_with_gw",
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_with_gw_and_allocation_pools",
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_with_host_routes_and_dns_nameservers",
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_without_gateway",
+ "tempest.api.network.test_networks.NetworksTest.test_create_update_delete_network_subnet",
+ "tempest.api.network.test_networks.NetworksTest.test_delete_network_with_subnet",
+ "tempest.api.network.test_networks.NetworksTest.test_list_networks",
+ "tempest.api.network.test_networks.NetworksTest.test_list_networks_fields",
+ "tempest.api.network.test_networks.NetworksTest.test_list_subnets",
+ "tempest.api.network.test_networks.NetworksTest.test_list_subnets_fields",
+ "tempest.api.network.test_networks.NetworksTest.test_show_network",
+ "tempest.api.network.test_networks.NetworksTest.test_show_network_fields",
+ "tempest.api.network.test_networks.NetworksTest.test_show_subnet",
+ "tempest.api.network.test_networks.NetworksTest.test_show_subnet_fields",
+ "tempest.api.network.test_networks.NetworksTest.test_update_subnet_gw_dns_host_routes_dhcp",
+ "tempest.api.network.test_ports.PortsTestJSON.test_create_bulk_port",
+ "tempest.api.network.test_ports.PortsTestJSON.test_create_port_in_allowed_allocation_pools",
+ "tempest.api.network.test_ports.PortsTestJSON.test_create_update_delete_port",
+ "tempest.api.network.test_ports.PortsTestJSON.test_list_ports",
+ "tempest.api.network.test_ports.PortsTestJSON.test_list_ports_fields",
+ "tempest.api.network.test_ports.PortsTestJSON.test_show_port",
+ "tempest.api.network.test_ports.PortsTestJSON.test_show_port_fields",
+ "tempest.api.network.test_ports.PortsTestJSON.test_update_port_with_security_group_and_extra_attributes",
+ "tempest.api.network.test_ports.PortsTestJSON.test_update_port_with_two_security_groups_and_extra_attributes"
+ ]
+ },
+ {
+ "api_name": "Basic CRUD operations on security groups",
+ "value": [
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_list_update_show_delete_security_group",
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_security_group_rule_with_additional_args",
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_security_group_rule_with_icmp_type_code",
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_security_group_rule_with_protocol_integer_value",
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_security_group_rule_with_remote_group_id",
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_security_group_rule_with_remote_ip_prefix",
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_show_delete_security_group_rule",
+ "tempest.api.network.test_security_groups.SecGroupTest.test_list_security_groups",
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_additional_default_security_group_fails",
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_duplicate_security_group_rule_fails",
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_bad_ethertype",
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_bad_protocol",
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_bad_remote_ip_prefix",
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_invalid_ports",
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_non_existent_remote_groupid",
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_non_existent_security_group",
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_delete_non_existent_security_group",
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_show_non_existent_security_group",
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_show_non_existent_security_group_rule"
+ ]
+ }
+ ]
+ },
+ {
+ "area_name": "Test Area VIM Operations - Volume",
+ "value": [
+ {
+ "api_name": "Volume attach and detach operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_volumes_actions.VolumesV2ActionsTest.test_attach_detach_volume_to_instance",
+ "tempest.api.volume.test_volumes_actions.VolumesV2ActionsTest.test_get_volume_attachment",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_attach_volumes_with_nonexistent_volume_id",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_detach_volumes_with_invalid_volume_id"
+ ]
+ },
+ {
+ "api_name": "Volume service availability zone operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_availability_zone.AvailabilityZoneV2TestJSON.test_get_availability_zone_list"
+ ]
+ },
+ {
+ "api_name": "Volume cloning operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_volumes_get.VolumesV2GetTest.test_volume_create_get_update_delete_as_clone"
+ ]
+ },
+ {
+ "api_name": "Image copy-to-volume operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_volumes_actions.VolumesV2ActionsTest.test_volume_bootable",
+ "tempest.api.volume.test_volumes_get.VolumesV2GetTest.test_volume_create_get_update_delete_from_image"
+ ]
+ },
+ {
+ "api_name": "Volume creation and deletion operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_volumes_get.VolumesV2GetTest.test_volume_create_get_update_delete",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_invalid_size",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_nonexistent_source_volid",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_nonexistent_volume_type",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_out_passing_size",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_size_negative",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_size_zero"
+ ]
+ },
+ {
+ "api_name": "Volume service extension listing operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_extensions.ExtensionsV2TestJSON.test_list_extensions"
+ ]
+ },
+ {
+ "api_name": "Volume GET operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_get_invalid_volume_id",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_get_volume_without_passing_volume_id",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_volume_get_nonexistent_volume_id"
+ ]
+ },
+ {
+ "api_name": "Volume listing operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list",
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_by_name",
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_details_by_name",
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_param_display_name_and_status",
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_with_detail_param_display_name_and_status",
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_with_detail_param_metadata",
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_with_details",
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_with_param_metadata",
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volumes_list_by_availability_zone",
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volumes_list_by_status",
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volumes_list_details_by_availability_zone",
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volumes_list_details_by_status",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_list_volumes_detail_with_invalid_status",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_list_volumes_detail_with_nonexistent_name",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_list_volumes_with_invalid_status",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_list_volumes_with_nonexistent_name",
+ "tempest.api.volume.v2.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_details_pagination",
+ "tempest.api.volume.v2.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_details_with_multiple_params",
+ "tempest.api.volume.v2.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_pagination"
+ ]
+ },
+ {
+ "api_name": "Volume metadata operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_volume_metadata.VolumesV2MetadataTest.test_create_get_delete_volume_metadata",
+ "tempest.api.volume.test_volume_metadata.VolumesV2MetadataTest.test_update_volume_metadata_item"
+ ]
+ },
+ {
+ "api_name": "Verification of read-only status on volumes with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_volumes_actions.VolumesV2ActionsTest.test_volume_readonly_update"
+ ]
+ },
+ {
+ "api_name": "Volume reservation operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_volumes_actions.VolumesV2ActionsTest.test_reserve_unreserve_volume",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_reserve_volume_with_negative_volume_status",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_reserve_volume_with_nonexistent_volume_id",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_unreserve_volume_with_nonexistent_volume_id"
+ ]
+ },
+ {
+ "api_name": "Volume snapshot creation/deletion operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_snapshot_metadata.SnapshotV2MetadataTestJSON.test_create_get_delete_snapshot_metadata",
+ "tempest.api.volume.test_snapshot_metadata.SnapshotV2MetadataTestJSON.test_update_snapshot_metadata_item",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_nonexistent_snapshot_id",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_delete_invalid_volume_id",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_delete_volume_without_passing_volume_id",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_volume_delete_nonexistent_volume_id",
+ "tempest.api.volume.test_volumes_snapshots.VolumesV2SnapshotTestJSON.test_snapshot_create_get_list_update_delete",
+ "tempest.api.volume.test_volumes_snapshots.VolumesV2SnapshotTestJSON.test_volume_from_snapshot",
+ "tempest.api.volume.test_volumes_snapshots.VolumesV2SnapshotTestJSON.test_snapshots_list_details_with_params",
+ "tempest.api.volume.test_volumes_snapshots.VolumesV2SnapshotTestJSON.test_snapshots_list_with_params",
+ "tempest.api.volume.test_volumes_snapshots_negative.VolumesV2SnapshotNegativeTestJSON.test_create_snapshot_with_nonexistent_volume_id",
+ "tempest.api.volume.test_volumes_snapshots_negative.VolumesV2SnapshotNegativeTestJSON.test_create_snapshot_without_passing_volume_id"
+ ]
+ },
+ {
+ "api_name": "Volume update operations with the Cinder v2 API",
+ "value": [
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_update_volume_with_empty_volume_id",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_update_volume_with_invalid_volume_id",
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_update_volume_with_nonexistent_volume_id"
+ ]
+ }
+ ]
+ },
+ {
+ "area_name": "Test Area High Availability",
+ "value": [
+ {
+ "api_name": "Verify high availability of OpenStack controller services",
+ "value": [
+ "opnfv.ha.tc001.nova-api_service_down",
+ "opnfv.ha.tc003.neutron-server_service_down",
+ "opnfv.ha.tc004.keystone_service_down",
+ "opnfv.ha.tc005.glance-api_service_down",
+ "opnfv.ha.tc006.cinder-api_service_down",
+ "opnfv.ha.tc009.cpu_overload",
+ "opnfv.ha.tc010.disk_I/O_block",
+ "opnfv.ha.tc011.load_balance_service_down"
+ ]
+ }
+ ]
+ },
+ {
+ "area_name": "Test Area vPing - Basic VNF Connectivity",
+ "value": [
+ {
+ "api_name": "Verify basic VNF connectivity with ICMP ping packets",
+ "value": [
+ "opnfv.vping.userdata",
+ "opnfv.vping.ssh"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "optional": {
+ "name": "Optional CVP Test Areas",
+ "value": [
+ {
+ "area_name": "Test Area BGP VPN",
+ "value": [
+ {
+ "api_name": "Verify association and dissasocitation of node using route targets",
+ "value": [
+ "opnfv.sdnvpn.subnet_connectivity",
+ "opnfv.sdnvpn.tenant separation",
+ "opnfv.sdnvpn.router_association",
+ "opnfv.sdnvpn.router_association_floating_ip"
+ ]
+ }
+ ]
+ },
+ {
+ "area_name": "Test Area IPv6 Compliance Testing Methodology and Test Cases",
+ "value": [
+ {
+ "api_name": "Test Case 1: Create and Delete an IPv6 Network, Port and Subnet",
+ "value": [
+ "tempest.api.network.test_networks.BulkNetworkOpsIpV6Test.test_bulk_create_delete_network",
+ "tempest.api.network.test_networks.BulkNetworkOpsIpV6Test.test_bulk_create_delete_port",
+ "tempest.api.network.test_networks.BulkNetworkOpsIpV6Test.test_bulk_create_delete_subnet"
+ ]
+ },
+ {
+ "api_name": "Test Case 2: Create, Update and Delete an IPv6 Network and Subnet",
+ "value": [
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_create_update_delete_network_subnet"
+ ]
+ },
+ {
+ "api_name": "Test Case 3: Check External Network Visibility",
+ "value": [
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_external_network_visibility"
+ ]
+ },
+ {
+ "api_name": "Test Case 4: List IPv6 Networks and Subnets of a Tenant",
+ "value": [
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_list_networks",
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_list_subnets"
+ ]
+ },
+ {
+ "api_name": "Test Case 5: Show Information of an IPv6 Network and Subnet",
+ "value": [
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_show_network",
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_show_subnet"
+ ]
+ },
+ {
+ "api_name": "Test Case 6: Create an IPv6 Port in Allowed Allocation Pools",
+ "value": [
+ "tempest.api.network.test_ports.PortsIpV6TestJSON.test_create_port_in_allowed_allocation_pools"
+ ]
+ },
+ {
+ "api_name": "Test Case 7: Create an IPv6 Port without Security Groups",
+ "value": [
+ "tempest.api.network.test_ports.PortsIpV6TestJSON.test_create_port_with_no_securitygroups"
+ ]
+ },
+ {
+ "api_name": "Test Case 8: Create, Update and Delete an IPv6 Port",
+ "value": [
+ "tempest.api.network.test_ports.PortsIpV6TestJSON.test_create_update_delete_port"
+ ]
+ },
+ {
+ "api_name": "Test Case 9: List IPv6 Ports of a Tenant",
+ "value": [
+ "tempest.api.network.test_ports.PortsIpV6TestJSON.test_list_ports"
+ ]
+ },
+ {
+ "api_name": "Test Case 10: Show Information of an IPv6 Port",
+ "value": [
+ "tempest.api.network.test_ports.PortsIpV6TestJSON.test_show_port"
+ ]
+ },
+ {
+ "api_name": "Test Case 11: Add Multiple Interfaces for an IPv6 Router",
+ "value": [
+ "tempest.api.network.test_routers.RoutersIpV6Test.test_add_multiple_router_interfaces"
+ ]
+ },
+ {
+ "api_name": "Test Case 12: Add and Remove an IPv6 Router Interface with port_id",
+ "value": [
+ "tempest.api.network.test_routers.RoutersIpV6Test.test_add_remove_router_interface_with_port_id"
+ ]
+ },
+ {
+ "api_name": "Test Case 13: Add and Remove an IPv6 Router Interface with subnet_id",
+ "value": [
+ "tempest.api.network.test_routers.RoutersIpV6Test.test_add_remove_router_interface_with_subnet_id"
+ ]
+ },
+ {
+ "api_name": "Test Case 14: Create, Update, Delete, List and Show an IPv6 Router",
+ "value": [
+ "tempest.api.network.test_routers.RoutersIpV6Test.test_create_show_list_update_delete_router"
+ ]
+ },
+ {
+ "api_name": "Test Case 15: Create, Update, Delete, List and Show an IPv6 Security Group",
+ "value": [
+ "tempest.api.network.test_security_groups.SecGroupIPv6Test.test_create_list_update_show_delete_security_group"
+ ]
+ },
+ {
+ "api_name": "Test Case 16: Create, Delete and Show Security Group Rules",
+ "value": [
+ "tempest.api.network.test_security_groups.SecGroupIPv6Test.test_create_show_delete_security_group_rule"
+ ]
+ },
+ {
+ "api_name": "Test Case 17: List All Security Groups",
+ "value": [
+ "tempest.api.network.test_security_groups.SecGroupIPv6Test.test_list_security_groups"
+ ]
+ },
+ {
+ "api_name": "Test Case 18: IPv6 Address Assignment - Dual Stack, SLAAC, DHCPv6 Stateless",
+ "value": [
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_dhcp6_stateless_from_os"
+ ]
+ },
+ {
+ "api_name": "Test Case 19: IPv6 Address Assignment - Dual Net, Dual Stack, SLAAC, DHCPv6 Stateless",
+ "value": [
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_dualnet_dhcp6_stateless_from_os"
+ ]
+ },
+ {
+ "api_name": "Test Case 20: IPv6 Address Assignment - Multiple Prefixes, Dual Stack, SLAAC, DHCPv6 Stateless",
+ "value": [
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_multi_prefix_dhcpv6_stateless"
+ ]
+ },
+ {
+ "api_name": "Test Case 21: IPv6 Address Assignment - Dual Net, Multiple Prefixes, Dual Stack, SLAAC, DHCPv6 Stateless",
+ "value": [
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_dualnet_multi_prefix_dhcpv6_stateless"
+ ]
+ },
+ {
+ "api_name": "Test Case 22: IPv6 Address Assignment - Dual Stack, SLAAC",
+ "value": [
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_slaac_from_os"
+ ]
+ },
+ {
+ "api_name": "Test Case 23: IPv6 Address Assignment - Dual Net, Dual Stack, SLAAC",
+ "value": [
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_dualnet_slaac_from_os"
+ ]
+ },
+ {
+ "api_name": "Test Case 24: IPv6 Address Assignment - Multiple Prefixes, Dual Stack, SLAAC",
+ "value": [
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_multi_prefix_slaac"
+ ]
+ },
+ {
+ "api_name": "Test Case 25: IPv6 Address Assignment - Dual Net, Dual Stack, Multiple Prefixes, SLAAC",
+ "value": [
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_dualnet_multi_prefix_slaac"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/cvp/3rd_party/static/testapi-ui/components/guidelines/data/gen.py b/cvp/3rd_party/static/testapi-ui/components/guidelines/data/gen.py
new file mode 100644
index 00000000..34fb6941
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/guidelines/data/gen.py
@@ -0,0 +1,16 @@
+import json
+
+with open('danube.json') as f:
+ data = json.load(f)
+mapping = {}
+for i in data['mandatory']['value']:
+ for j in i['value']:
+ for k in j['value']:
+ mapping[k] = True
+for i in data['optional']['value']:
+ for j in i['value']:
+ for k in j['value']:
+ mapping[k] = False
+
+with open('mandatory.json', 'w') as f:
+ f.write(json.dumps(mapping))
diff --git a/cvp/3rd_party/static/testapi-ui/components/guidelines/data/mandatory.json b/cvp/3rd_party/static/testapi-ui/components/guidelines/data/mandatory.json
new file mode 100644
index 00000000..ce2ba857
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/guidelines/data/mandatory.json
@@ -0,0 +1,248 @@
+{
+ "opnfv.ha.tc001.nova-api_service_down": true,
+ "opnfv.ha.tc003.neutron-server_service_down": true,
+ "opnfv.ha.tc004.keystone_service_down": true,
+ "opnfv.ha.tc005.glance-api_service_down": true,
+ "opnfv.ha.tc006.cinder-api_service_down": true,
+ "opnfv.ha.tc009.cpu_overload": true,
+ "opnfv.ha.tc010.disk_I/O_block": true,
+ "opnfv.ha.tc011.load_balance_service_down": true,
+ "opnfv.sdnvpn.router_association": false,
+ "opnfv.sdnvpn.router_association_floating_ip": false,
+ "opnfv.sdnvpn.subnet_connectivity": false,
+ "opnfv.sdnvpn.tenant separation": false,
+ "tempest.api.compute.images.test_images_oneserver.ImagesOneServerTestJSON.test_create_delete_image": true,
+ "tempest.api.compute.images.test_images_oneserver.ImagesOneServerTestJSON.test_create_image_specify_multibyte_character_image_name": true,
+ "tempest.api.compute.servers.test_create_server.ServersTestJSON.test_host_name_is_same_as_server_name": true,
+ "tempest.api.compute.servers.test_create_server.ServersTestJSON.test_list_servers": true,
+ "tempest.api.compute.servers.test_create_server.ServersTestJSON.test_list_servers_with_detail": true,
+ "tempest.api.compute.servers.test_create_server.ServersTestJSON.test_verify_created_server_vcpus": true,
+ "tempest.api.compute.servers.test_create_server.ServersTestJSON.test_verify_server_details": true,
+ "tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_host_name_is_same_as_server_name": true,
+ "tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_list_servers": true,
+ "tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_list_servers_with_detail": true,
+ "tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_verify_created_server_vcpus": true,
+ "tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_verify_server_details": true,
+ "tempest.api.compute.servers.test_instance_actions.InstanceActionsTestJSON.test_get_instance_action": true,
+ "tempest.api.compute.servers.test_instance_actions.InstanceActionsTestJSON.test_list_instance_actions": true,
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_detailed_filter_by_flavor": true,
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_detailed_filter_by_image": true,
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_detailed_filter_by_server_name": true,
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_detailed_filter_by_server_status": true,
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_detailed_limit_results": true,
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filter_by_flavor": true,
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filter_by_image": true,
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filter_by_limit": true,
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filter_by_server_name": true,
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filter_by_server_status": true,
+ "tempest.api.compute.servers.test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filtered_by_name_wildcard": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_changes_since_future_date": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_changes_since_invalid_date": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_limits": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_limits_greater_than_actual_count": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_limits_pass_negative_value": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_limits_pass_string": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_non_existing_flavor": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_non_existing_image": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_by_non_existing_server_name": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_detail_server_is_deleted": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_status_non_existing": true,
+ "tempest.api.compute.servers.test_list_servers_negative.ListServersNegativeTestJSON.test_list_servers_with_a_deleted_server": true,
+ "tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_lock_unlock_server": true,
+ "tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard": true,
+ "tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_rebuild_server": true,
+ "tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_stop_start_server": true,
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_delete_server_metadata_item": true,
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_get_server_metadata_item": true,
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_list_server_metadata": true,
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_set_server_metadata": true,
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_set_server_metadata_item": true,
+ "tempest.api.compute.servers.test_server_metadata.ServerMetadataTestJSON.test_update_server_metadata": true,
+ "tempest.api.compute.servers.test_servers.ServersTestJSON.test_create_server_with_admin_password": true,
+ "tempest.api.compute.servers.test_servers.ServersTestJSON.test_create_specify_keypair": true,
+ "tempest.api.compute.servers.test_servers.ServersTestJSON.test_create_with_existing_server_name": true,
+ "tempest.api.compute.servers.test_servers.ServersTestJSON.test_update_access_server_address": true,
+ "tempest.api.compute.servers.test_servers.ServersTestJSON.test_update_server_name": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_numeric_server_name": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_server_metadata_exceeds_length_limit": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_server_name_length_exceeds_256": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_with_invalid_flavor": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_with_invalid_image": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_create_with_invalid_network_uuid": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_delete_server_pass_id_exceeding_length_limit": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_delete_server_pass_negative_id": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_get_non_existent_server": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_invalid_ip_v6_address": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_reboot_non_existent_server": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_rebuild_deleted_server": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_rebuild_non_existent_server": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_server_name_blank": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_stop_non_existent_server": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_update_name_of_non_existent_server": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_update_server_name_length_exceeds_256": true,
+ "tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_update_server_set_empty_name": true,
+ "tempest.api.compute.test_quotas.QuotasTestJSON.test_get_default_quotas": true,
+ "tempest.api.compute.test_quotas.QuotasTestJSON.test_get_quotas": true,
+ "tempest.api.compute.test_versions.TestVersions.test_list_api_versions": true,
+ "tempest.api.compute.volumes.test_attach_volume.AttachVolumeTestJSON.test_attach_detach_volume": true,
+ "tempest.api.compute.volumes.test_attach_volume.AttachVolumeTestJSON.test_list_get_volume_attachments": true,
+ "tempest.api.identity.v3.test_api_discovery.TestApiDiscovery.test_api_media_types": true,
+ "tempest.api.identity.v3.test_api_discovery.TestApiDiscovery.test_api_version_resources": true,
+ "tempest.api.identity.v3.test_api_discovery.TestApiDiscovery.test_api_version_statuses": true,
+ "tempest.api.identity.v3.test_tokens.TokensV3Test.test_create_token": true,
+ "tempest.api.image.v2.test_images.BasicOperationsImagesTest.test_delete_image": true,
+ "tempest.api.image.v2.test_images.BasicOperationsImagesTest.test_update_image": true,
+ "tempest.api.image.v2.test_images.ListImagesTest.test_get_image_schema": true,
+ "tempest.api.image.v2.test_images.ListImagesTest.test_get_images_schema": true,
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_container_format": true,
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_disk_format": true,
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_limit": true,
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_min_max_size": true,
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_size": true,
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_status": true,
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_images_param_visibility": true,
+ "tempest.api.image.v2.test_images.ListImagesTest.test_list_no_params": true,
+ "tempest.api.image.v2.test_images_negative.ImagesNegativeTest.test_delete_image_null_id": true,
+ "tempest.api.image.v2.test_images_negative.ImagesNegativeTest.test_delete_non_existing_image": true,
+ "tempest.api.image.v2.test_images_negative.ImagesNegativeTest.test_get_delete_deleted_image": true,
+ "tempest.api.image.v2.test_images_negative.ImagesNegativeTest.test_get_image_null_id": true,
+ "tempest.api.image.v2.test_images_negative.ImagesNegativeTest.test_get_non_existent_image": true,
+ "tempest.api.image.v2.test_images_tags.ImagesTagsTest.test_update_delete_tags_for_image": true,
+ "tempest.api.image.v2.test_images_tags_negative.ImagesTagsNegativeTest.test_delete_non_existing_tag": true,
+ "tempest.api.image.v2.test_images_tags_negative.ImagesTagsNegativeTest.test_update_tags_for_non_existing_image": true,
+ "tempest.api.network.test_networks.BulkNetworkOpsIpV6Test.test_bulk_create_delete_network": false,
+ "tempest.api.network.test_networks.BulkNetworkOpsIpV6Test.test_bulk_create_delete_port": false,
+ "tempest.api.network.test_networks.BulkNetworkOpsIpV6Test.test_bulk_create_delete_subnet": false,
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_create_update_delete_network_subnet": false,
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_external_network_visibility": false,
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_list_networks": false,
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_list_subnets": false,
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_show_network": false,
+ "tempest.api.network.test_networks.NetworksIpV6Test.test_show_subnet": false,
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_all_attributes": true,
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_with_allocation_pools": true,
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_with_dhcp_enabled": true,
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_with_gw": true,
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_with_gw_and_allocation_pools": true,
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_with_host_routes_and_dns_nameservers": true,
+ "tempest.api.network.test_networks.NetworksTest.test_create_delete_subnet_without_gateway": true,
+ "tempest.api.network.test_networks.NetworksTest.test_create_update_delete_network_subnet": true,
+ "tempest.api.network.test_networks.NetworksTest.test_delete_network_with_subnet": true,
+ "tempest.api.network.test_networks.NetworksTest.test_list_networks": true,
+ "tempest.api.network.test_networks.NetworksTest.test_list_networks_fields": true,
+ "tempest.api.network.test_networks.NetworksTest.test_list_subnets": true,
+ "tempest.api.network.test_networks.NetworksTest.test_list_subnets_fields": true,
+ "tempest.api.network.test_networks.NetworksTest.test_show_network": true,
+ "tempest.api.network.test_networks.NetworksTest.test_show_network_fields": true,
+ "tempest.api.network.test_networks.NetworksTest.test_show_subnet": true,
+ "tempest.api.network.test_networks.NetworksTest.test_show_subnet_fields": true,
+ "tempest.api.network.test_networks.NetworksTest.test_update_subnet_gw_dns_host_routes_dhcp": true,
+ "tempest.api.network.test_ports.PortsIpV6TestJSON.test_create_port_in_allowed_allocation_pools": false,
+ "tempest.api.network.test_ports.PortsIpV6TestJSON.test_create_port_with_no_securitygroups": false,
+ "tempest.api.network.test_ports.PortsIpV6TestJSON.test_create_update_delete_port": false,
+ "tempest.api.network.test_ports.PortsIpV6TestJSON.test_list_ports": false,
+ "tempest.api.network.test_ports.PortsIpV6TestJSON.test_show_port": false,
+ "tempest.api.network.test_ports.PortsTestJSON.test_create_bulk_port": true,
+ "tempest.api.network.test_ports.PortsTestJSON.test_create_port_in_allowed_allocation_pools": true,
+ "tempest.api.network.test_ports.PortsTestJSON.test_create_update_delete_port": true,
+ "tempest.api.network.test_ports.PortsTestJSON.test_list_ports": true,
+ "tempest.api.network.test_ports.PortsTestJSON.test_list_ports_fields": true,
+ "tempest.api.network.test_ports.PortsTestJSON.test_show_port": true,
+ "tempest.api.network.test_ports.PortsTestJSON.test_show_port_fields": true,
+ "tempest.api.network.test_ports.PortsTestJSON.test_update_port_with_security_group_and_extra_attributes": true,
+ "tempest.api.network.test_ports.PortsTestJSON.test_update_port_with_two_security_groups_and_extra_attributes": true,
+ "tempest.api.network.test_routers.RoutersIpV6Test.test_add_multiple_router_interfaces": false,
+ "tempest.api.network.test_routers.RoutersIpV6Test.test_add_remove_router_interface_with_port_id": false,
+ "tempest.api.network.test_routers.RoutersIpV6Test.test_add_remove_router_interface_with_subnet_id": false,
+ "tempest.api.network.test_routers.RoutersIpV6Test.test_create_show_list_update_delete_router": false,
+ "tempest.api.network.test_security_groups.SecGroupIPv6Test.test_create_list_update_show_delete_security_group": false,
+ "tempest.api.network.test_security_groups.SecGroupIPv6Test.test_create_show_delete_security_group_rule": false,
+ "tempest.api.network.test_security_groups.SecGroupIPv6Test.test_list_security_groups": false,
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_list_update_show_delete_security_group": true,
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_security_group_rule_with_additional_args": true,
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_security_group_rule_with_icmp_type_code": true,
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_security_group_rule_with_protocol_integer_value": true,
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_security_group_rule_with_remote_group_id": true,
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_security_group_rule_with_remote_ip_prefix": true,
+ "tempest.api.network.test_security_groups.SecGroupTest.test_create_show_delete_security_group_rule": true,
+ "tempest.api.network.test_security_groups.SecGroupTest.test_list_security_groups": true,
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_additional_default_security_group_fails": true,
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_duplicate_security_group_rule_fails": true,
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_bad_ethertype": true,
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_bad_protocol": true,
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_bad_remote_ip_prefix": true,
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_invalid_ports": true,
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_non_existent_remote_groupid": true,
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_create_security_group_rule_with_non_existent_security_group": true,
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_delete_non_existent_security_group": true,
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_show_non_existent_security_group": true,
+ "tempest.api.network.test_security_groups_negative.NegativeSecGroupTest.test_show_non_existent_security_group_rule": true,
+ "tempest.api.volume.test_availability_zone.AvailabilityZoneV2TestJSON.test_get_availability_zone_list": true,
+ "tempest.api.volume.test_extensions.ExtensionsV2TestJSON.test_list_extensions": true,
+ "tempest.api.volume.test_snapshot_metadata.SnapshotV2MetadataTestJSON.test_create_get_delete_snapshot_metadata": true,
+ "tempest.api.volume.test_snapshot_metadata.SnapshotV2MetadataTestJSON.test_update_snapshot_metadata_item": true,
+ "tempest.api.volume.test_volume_metadata.VolumesV2MetadataTest.test_create_get_delete_volume_metadata": true,
+ "tempest.api.volume.test_volume_metadata.VolumesV2MetadataTest.test_update_volume_metadata_item": true,
+ "tempest.api.volume.test_volumes_actions.VolumesV2ActionsTest.test_attach_detach_volume_to_instance": true,
+ "tempest.api.volume.test_volumes_actions.VolumesV2ActionsTest.test_get_volume_attachment": true,
+ "tempest.api.volume.test_volumes_actions.VolumesV2ActionsTest.test_reserve_unreserve_volume": true,
+ "tempest.api.volume.test_volumes_actions.VolumesV2ActionsTest.test_volume_bootable": true,
+ "tempest.api.volume.test_volumes_actions.VolumesV2ActionsTest.test_volume_readonly_update": true,
+ "tempest.api.volume.test_volumes_get.VolumesV2GetTest.test_volume_create_get_update_delete": true,
+ "tempest.api.volume.test_volumes_get.VolumesV2GetTest.test_volume_create_get_update_delete_as_clone": true,
+ "tempest.api.volume.test_volumes_get.VolumesV2GetTest.test_volume_create_get_update_delete_from_image": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_by_name": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_details_by_name": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_param_display_name_and_status": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_with_detail_param_display_name_and_status": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_with_detail_param_metadata": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_with_details": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_with_param_metadata": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volumes_list_by_availability_zone": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volumes_list_by_status": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volumes_list_details_by_availability_zone": true,
+ "tempest.api.volume.test_volumes_list.VolumesV2ListTestJSON.test_volumes_list_details_by_status": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_attach_volumes_with_nonexistent_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_invalid_size": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_nonexistent_snapshot_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_nonexistent_source_volid": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_nonexistent_volume_type": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_out_passing_size": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_size_negative": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_create_volume_with_size_zero": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_delete_invalid_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_delete_volume_without_passing_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_detach_volumes_with_invalid_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_get_invalid_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_get_volume_without_passing_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_list_volumes_detail_with_invalid_status": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_list_volumes_detail_with_nonexistent_name": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_list_volumes_with_invalid_status": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_list_volumes_with_nonexistent_name": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_reserve_volume_with_negative_volume_status": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_reserve_volume_with_nonexistent_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_unreserve_volume_with_nonexistent_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_update_volume_with_empty_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_update_volume_with_invalid_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_update_volume_with_nonexistent_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_volume_delete_nonexistent_volume_id": true,
+ "tempest.api.volume.test_volumes_negative.VolumesV2NegativeTest.test_volume_get_nonexistent_volume_id": true,
+ "tempest.api.volume.test_volumes_snapshots.VolumesV2SnapshotTestJSON.test_snapshot_create_get_list_update_delete": true,
+ "tempest.api.volume.test_volumes_snapshots.VolumesV2SnapshotTestJSON.test_snapshots_list_details_with_params": true,
+ "tempest.api.volume.test_volumes_snapshots.VolumesV2SnapshotTestJSON.test_snapshots_list_with_params": true,
+ "tempest.api.volume.test_volumes_snapshots.VolumesV2SnapshotTestJSON.test_volume_from_snapshot": true,
+ "tempest.api.volume.test_volumes_snapshots_negative.VolumesV2SnapshotNegativeTestJSON.test_create_snapshot_with_nonexistent_volume_id": true,
+ "tempest.api.volume.test_volumes_snapshots_negative.VolumesV2SnapshotNegativeTestJSON.test_create_snapshot_without_passing_volume_id": true,
+ "tempest.api.volume.v2.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_details_pagination": true,
+ "tempest.api.volume.v2.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_details_with_multiple_params": true,
+ "tempest.api.volume.v2.test_volumes_list.VolumesV2ListTestJSON.test_volume_list_pagination": true,
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_dhcp6_stateless_from_os": false,
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_dualnet_dhcp6_stateless_from_os": false,
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_dualnet_multi_prefix_dhcpv6_stateless": false,
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_dualnet_multi_prefix_slaac": false,
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_dualnet_slaac_from_os": false,
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_multi_prefix_dhcpv6_stateless": false,
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_multi_prefix_slaac": false,
+ "tempest.scenario.test_network_v6.TestGettingAddress.test_slaac_from_os": false
+}
diff --git a/cvp/3rd_party/static/testapi-ui/components/guidelines/guidelines.html b/cvp/3rd_party/static/testapi-ui/components/guidelines/guidelines.html
new file mode 100644
index 00000000..6e138b89
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/guidelines/guidelines.html
@@ -0,0 +1,70 @@
+<h3>OPNFV Ready&#8482; Guidelines</h3>
+
+<!-- Guideline Filters -->
+<div class="row">
+ <div class="col-md-3">
+ <strong>Version:</strong>
+ <!-- Slicing the version file name here gets rid of the '.json' file extension -->
+ <select ng-model="ctrl.version"
+ ng-change="ctrl.update()"
+ class="form-control"
+ ng-options="versionFile.slice(0,10) for versionFile in ctrl.versionList">
+ </select>
+ </div>
+ <!--
+ <div class="col-md-4">
+ <strong>Target Program:</strong>
+ <span class="program-about"><a target="_blank" href="http://www.openstack.org/brand/interop/">About</a></span>
+ <select ng-model="ctrl.target" class="form-control" ng-change="ctrl.updateTargetCapabilities()">
+ <option value="platform">OpenStack Powered Platform</option>
+ <option value="compute">OpenStack Powered Compute</option>
+ <option value="object">OpenStack Powered Object Storage</option>
+ </select>
+ </div>
+ -->
+</div>
+
+<br />
+<!--
+<div ng-if="ctrl.guidelines">
+ <strong>Guideline Status:</strong>
+ {{ctrl.guidelines.status | capitalize}}
+</div>
+
+<div ng-show="ctrl.guidelines">
+ <strong>Corresponding OpenStack Releases:</strong>
+ <ul class="list-inline">
+ <li ng-repeat="release in ctrl.guidelines.releases">
+ {{release | capitalize}}
+ </li>
+ </ul>
+</div>
+-->
+
+<strong>Capability Status:</strong>
+<div class="checkbox">
+ <label>
+ <input type="checkbox" ng-model="ctrl.showMandatory">
+ <span class="mandatory">Mandatory</span>
+ </label>
+ <label>
+ <input type="checkbox" ng-model="ctrl.showOptional">
+ <span class="optional">Optional</span>
+ </label>
+</div>
+<!-- End Capability Filters -->
+
+<!-- Loading animation divs -->
+<div cg-busy="{promise:ctrl.versionsRequest,message:'Loading versions'}"></div>
+<div cg-busy="{promise:ctrl.capsRequest,message:'Loading capabilities'}"></div>
+
+<!-- Get the version-specific template -->
+<div nf-show="ctrl.data" ng-include src="ctrl.detailsTemplate"></div>
+
+<!--
+<div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
+ <span class="sr-only">Error:</span>
+ {{ctrl.error}}
+</div>
+-->
diff --git a/cvp/3rd_party/static/testapi-ui/components/guidelines/guidelinesController.js b/cvp/3rd_party/static/testapi-ui/components/guidelines/guidelinesController.js
new file mode 100644
index 00000000..46d2042a
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/guidelines/guidelinesController.js
@@ -0,0 +1,188 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ angular
+ .module('testapiApp')
+ .controller('GuidelinesController', GuidelinesController);
+
+ GuidelinesController.$inject = ['$http', '$uibModal', 'testapiApiUrl'];
+
+ /**
+ * TestAPI Guidelines Controller
+ * This controller is for the '/guidelines' page where a user can browse
+ * through tests belonging to Interop WG defined capabilities.
+ */
+ function GuidelinesController($http, $uibModal, testapiApiUrl) {
+ var ctrl = this;
+
+ ctrl.getVersionList = getVersionList;
+ ctrl.update = update;
+
+ ctrl.showMandatory = true;
+ ctrl.showOptional = false;
+ ctrl.version = '';
+ ctrl.data = null;
+
+ /**
+ * The template to load for displaying capability details.
+ */
+ ctrl.detailsTemplate = 'testapi-ui/components/guidelines/partials/' +
+ 'guidelineDetails.html';
+
+ /**
+ * Retrieve an array of available guideline files from the TestAPI
+ * API server, sort this array reverse-alphabetically, and store it in
+ * a scoped variable. The scope's selected version is initialized to
+ * the latest (i.e. first) version here as well. After a successful API
+ * call, the function to update the capabilities is called.
+ * Sample API return array: ["2015.03.json", "2015.04.json"]
+ */
+ function getVersionList() {
+ ctrl.versionList = ['danube'];
+ ctrl.update();
+ }
+
+ /**
+ * This will contact the TestAPI API server to retrieve the JSON
+ * content of the guideline file corresponding to the selected
+ * version.
+ */
+ function update() {
+ if (ctrl.version != ''){
+ var path = 'testapi-ui/components/guidelines/data/' + ctrl.version + '.json';
+ $http.get(path).success(function(data){
+ ctrl.data = data;
+ }).error(function(error){
+ });
+ }
+ }
+
+
+ ctrl.getVersionList();
+ }
+
+
+
+
+
+ angular
+ .module('testapiApp')
+ .controller('TestListModalController', TestListModalController);
+
+ TestListModalController.$inject = [
+ '$uibModalInstance', '$http', 'version',
+ 'target', 'status', 'testapiApiUrl'
+ ];
+
+ /**
+ * Test List Modal Controller
+ * This controller is for the modal that appears if a user wants to see the
+ * test list corresponding to Interop WG capabilities with the selected
+ * statuses.
+ */
+ function TestListModalController($uibModalInstance, $http, version,
+ target, status, testapiApiUrl) {
+
+ var ctrl = this;
+
+ ctrl.version = version;
+ ctrl.target = target;
+ ctrl.status = status;
+ ctrl.close = close;
+ ctrl.updateTestListString = updateTestListString;
+
+ ctrl.aliases = true;
+ ctrl.flagged = false;
+
+ // Check if the API URL is absolute or relative.
+ if (testapiApiUrl.indexOf('http') > -1) {
+ ctrl.url = testapiApiUrl;
+ }
+ else {
+ ctrl.url = location.protocol + '//' + location.host +
+ testapiApiUrl;
+ }
+
+ /**
+ * This function will close/dismiss the modal.
+ */
+ function close() {
+ $uibModalInstance.dismiss('exit');
+ }
+
+ /**
+ * This function will return a list of statuses based on which ones
+ * are selected.
+ */
+ function getStatusList() {
+ var statusList = [];
+ angular.forEach(ctrl.status, function(value, key) {
+ if (value) {
+ statusList.push(key);
+ }
+ });
+ return statusList;
+ }
+
+ /**
+ * This will get the list of tests from the API and update the
+ * controller's test list string variable.
+ */
+ function updateTestListString() {
+ var statuses = getStatusList();
+ if (!statuses.length) {
+ ctrl.error = 'No tests matching selected criteria.';
+ return;
+ }
+ ctrl.testListUrl = [
+ ctrl.url, '/guidelines/', ctrl.version, '/tests?',
+ 'target=', ctrl.target, '&',
+ 'type=', statuses.join(','), '&',
+ 'alias=', ctrl.aliases.toString(), '&',
+ 'flag=', ctrl.flagged.toString()
+ ].join('');
+ ctrl.testListRequest =
+ $http.get(ctrl.testListUrl).
+ then(function successCallback(response) {
+ ctrl.error = null;
+ ctrl.testListString = response.data;
+ if (!ctrl.testListString) {
+ ctrl.testListCount = 0;
+ }
+ else {
+ ctrl.testListCount =
+ ctrl.testListString.split('\n').length;
+ }
+ }, function errorCallback(response) {
+ ctrl.testListString = null;
+ ctrl.testListCount = null;
+ if (angular.isObject(response.data) &&
+ response.data.message) {
+ ctrl.error = 'Error retrieving test list: ' +
+ response.data.message;
+ }
+ else {
+ ctrl.error = 'Unknown error retrieving test list.';
+ }
+ });
+ }
+
+ // updateTestListString();
+ //getVersionList();
+ update();
+ }
+})();
diff --git a/cvp/3rd_party/static/testapi-ui/components/guidelines/partials/guidelineDetails.html b/cvp/3rd_party/static/testapi-ui/components/guidelines/partials/guidelineDetails.html
new file mode 100644
index 00000000..05a1ef5c
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/guidelines/partials/guidelineDetails.html
@@ -0,0 +1,90 @@
+<!--
+HTML for guidelines page for all OpenStack Powered (TM) guideline schemas
+This expects the JSON data of the guidelines file to be stored in scope
+variable 'guidelines'.
+-->
+
+<h3 ng-show="ctrl.showMandatory">{{ctrl.data.mandatory.name}}</h3>
+<div ng-repeat="area in ctrl.data.mandatory.value" ng-show="ctrl.showMandatory">
+ <h4>{{area.area_name}}</h4>
+ <ol class="capabilities">
+ <li class="capability-list-item" ng-repeat="api in area.value">
+ <span class="capability-name">{{api.api_name}}</span><br />
+ Area: <em>{{area.area_name}}</em><br />
+ Status: <span>Mandatory</span><br />
+
+ <a ng-click="showTests = !showTests">Tests ({{api.value.length}})</a>
+ <ul uib-collapse="!showTests">
+ <li ng-repeat="test in api.value">
+ <span ng-class="{'glyphicon glyphicon-flag text-warning': capability.flagged.indexOf(test) > -1}"></span>
+ {{test}}
+ </li>
+ </ul>
+ </li>
+ </ol>
+</div>
+
+<h3 ng-show="ctrl.showOptional">{{ctrl.data.optional.name}}</h3>
+<div ng-repeat="area in ctrl.data.optional.value" ng-show="ctrl.showOptional">
+ <h4>{{area.area_name}}</h4>
+ <ol class="capabilities">
+ <li class="capability-list-item" ng-repeat="api in area.value">
+ <span class="capability-name">{{api.api_name}}</span><br />
+ Status: <span>Optional</span><br />
+
+ <a ng-click="showTests = !showTests">Tests ({{api.value.length}})</a>
+ <ul uib-collapse="!showTests">
+ <li ng-repeat="test in api.value">
+ <span ng-class="{'glyphicon glyphicon-flag text-warning': capability.flagged.indexOf(test) > -1}"></span>
+ {{test}}
+ </li>
+ </ul>
+ </li>
+ </ol>
+</div>
+<!--
+<ol ng-show="ctrl.data" class="capabilities">
+ <li class="capability-list-item" ng-repeat="capability in ctrl.guidelines.capabilities | arrayConverter | filter:ctrl.filterStatus | orderBy:'id'">
+ <span class="capability-name">{{capability.id}}</span><br />
+ <em>{{capability.description}}</em><br />
+ Status: <span class="{{ctrl.targetCapabilities[capability.id]}}">{{ctrl.targetCapabilities[capability.id]}}</span><br />
+ <span ng-if="capability.project">Project: {{capability.project | capitalize}}<br /></span>
+ <a ng-click="showAchievements = !showAchievements">Achievements ({{capability.achievements.length}})</a><br />
+ <ol uib-collapse="!showAchievements" class="list-inline">
+ <li ng-repeat="achievement in capability.achievements">
+ {{achievement}}
+ </li>
+ </ol>
+
+ <a ng-click="showTests = !showTests">Tests ({{ctrl.getObjectLength(capability.tests)}})</a>
+ <ul uib-collapse="!showTests">
+ <li ng-if="ctrl.guidelines.schema === '1.2'" ng-repeat="test in capability.tests">
+ <span ng-class="{'glyphicon glyphicon-flag text-warning': capability.flagged.indexOf(test) > -1}"></span>
+ {{test}}
+ </li>
+ <li ng-if="ctrl.guidelines.schema > '1.2'" ng-repeat="(testName, testDetails) in capability.tests">
+ <span ng-class="{'glyphicon glyphicon-flag text-warning': testDetails.flagged}" title="{{testDetails.flagged.reason}}"></span>
+ {{testName}}
+ <div class="test-detail" ng-if="testDetails.aliases">
+ <strong>Aliases:</strong>
+ <ul><li ng-repeat="alias in testDetails.aliases">{{alias}}</li></ul>
+ </div>
+ </li>
+ </ul>
+ </li>
+</ol>
+
+<div ng-show="ctrl.guidelines" class="criteria">
+ <hr>
+ <h4><a ng-click="showCriteria = !showCriteria">Criteria</a></h4>
+ <div uib-collapse="showCriteria">
+ <ul>
+ <li ng-repeat="(key, criterion) in ctrl.guidelines.criteria">
+ <span class="criterion-name">{{criterion.name}}</span><br />
+ <em>{{criterion.Description}}</em><br />
+ Weight: {{criterion.weight}}
+ </li>
+ </ul>
+ </div>
+</div>
+-->
diff --git a/cvp/3rd_party/static/testapi-ui/components/guidelines/partials/testListModal.html b/cvp/3rd_party/static/testapi-ui/components/guidelines/partials/testListModal.html
new file mode 100644
index 00000000..5b1d698d
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/guidelines/partials/testListModal.html
@@ -0,0 +1,46 @@
+<div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" aria-hidden="true" ng-click="modal.close()">&times;</button>
+ <h4>Test List ({{modal.testListCount}})</h4>
+ <p>Use this test list with <a title="testapi-client" target="_blank"href="https://github.com/openstack/testapi-client">testapi-client</a>
+ to run only tests in the {{modal.version}} OpenStack Powered&#8482; guideline from capabilities with the following statuses:
+ </p>
+ <ul class="list-inline">
+ <li class="required" ng-if="modal.status.required"> Required</li>
+ <li class="advisory" ng-if="modal.status.advisory"> Advisory</li>
+ <li class="deprecated" ng-if="modal.status.deprecated"> Deprecated</li>
+ <li class="removed" ng-if="modal.status.removed"> Removed</li>
+ </ul>
+ <div class="checkbox checkbox-test-list">
+ <label><input type="checkbox" ng-model="modal.aliases" ng-change="modal.updateTestListString()">Aliases</label>
+ <span class="glyphicon glyphicon-info-sign info-hover" aria-hidden="true"
+ title="Include test aliases as tests may have been renamed over time. It does not hurt to include these."></span>
+ &nbsp;
+ <label><input type="checkbox" ng-model="modal.flagged" ng-change="modal.updateTestListString()">Flagged</label>
+ <span class="glyphicon glyphicon-info-sign info-hover" aria-hidden="true"
+ title="Include flagged tests.">
+ </span>
+ </div>
+ <p ng-hide="modal.error"> Alternatively, get the test list directly from the API on your CLI:</p>
+ <code ng-hide="modal.error">wget "{{modal.testListUrl}}" -O {{modal.version}}-test-list.txt</code>
+ </div>
+ <div class="modal-body tests-modal-content">
+ <div cg-busy="{promise:modal.testListRequest,message:'Loading'}"></div>
+ <div ng-show="modal.error" class="alert alert-danger" role="alert">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
+ <span class="sr-only">Error:</span>
+ {{modal.error}}
+ </div>
+ <div class="form-group">
+ <textarea class="form-control" rows="16" id="tests" wrap="off">{{modal.testListString}}</textarea>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <a target="_blank" href="{{modal.testListUrl}}" download="{{modal.version + '-test-list.txt'}}">
+ <button class="btn btn-primary" ng-if="modal.testListCount > 0" type="button">
+ Download
+ </button>
+ </a>
+ <button class="btn btn-primary" type="button" ng-click="modal.close()">Close</button>
+ </div>
+</div>
diff --git a/cvp/3rd_party/static/testapi-ui/components/home/home.html b/cvp/3rd_party/static/testapi-ui/components/home/home.html
new file mode 100644
index 00000000..8b97bd64
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/home/home.html
@@ -0,0 +1,74 @@
+<div class="row">
+ <div class="col-lg-12" style="font-size:15px">
+ <h1>CVP Workflow</h1>
+ <hr>
+ <h2>Step 1: Applying</h2>
+ <br>
+ <p>A tester should start the process by completing an <a ng-click="ctrl.gotoApplication()">application</a>.</p>
+
+ <!--
+ <ul>
+ <li>Organization name</li>
+ <li>Organization website (if public)</li>
+ <li>Product name and identifier</li>
+ <li>Product public documentation</li>
+ <li>Product categories, choose one: (i) software and hardware (ii) software and third party hardware (please specify)</li>
+ <li>Primary contact name, business email, postal address and phone number Only the primary email address should be used for official communication with OPNFV CVP.</li>
+ <li>User ID for CVP web portal The CVP web portal supports (i) Linux Foundation user ID, and (ii) Openstack user ID, in the current release. Specify either one as user ID for the CVP web portal. If a new user ID is needed, visit https://identity.linuxfoundation.org, or https://www.openstack.org/join/register.</li>
+ <li>Location where the verification testing is to be conducted. Choose one: (internal vendor lab, third-party lab)</li>
+ <li>If the test is to be conducted by a third-party lab, please specify name and contact information of the third-party lab.</li>
+ </ul>
+
+ <p>Please email the completed application using the primary contact email account in order to establish identity.</p>
+ -->
+
+ <p>Once the application information is received and in order, an email response will be sent to the primary contact with confirmation and next step information.</p>
+
+ <!--
+ <p>[Editor'note: No fee has been established at this time for CVP applications. Recommend we skip fee for the initial release of CVP.]</p>
+ -->
+
+ <hr>
+ <h2>Step 2: Testing</h2>
+ <p>The following documents guide testers to prepare the test environment and run tests:</p>
+
+ <ul>
+ <li><a href="http://artifacts.opnfv.org/dovetail/docs/testing_user_systempreparation/index.html">System Requirements and Preparation Guide for OPNFV CVP </a></li>
+ <li><a href="http://artifacts.opnfv.org/dovetail/docs/testing_developer_testscope/index.html">OPNFV CVP Teslt Case Specification </a></li>
+ <li><a href="http://artifacts.opnfv.org/dovetail/docs/testing_user_userguide/index.html">Dovetail Test Tool User Guide </a></li>
+ </ul>
+ <!--
+ <p>[Editor's note: The above three documents are still work in progress. Names and references will be corrected when they are merged.]</p>
+
+ <p>A unique Test ID is generated by the Dovetail tool for each test run. Please take a note of this ID for future reference.</p>
+ -->
+
+ <hr>
+ <h2>Step 3: Submitting Test Results</h2>
+ <p>Testers can login to the CVP web portal <a href="https://cvp.opnfv.org">https://cvp.opnfv.org</a> with the LF ID or Openstack ID and upload the test results. By default, the results are visible only to the user who uploaded the data.</p>
+
+ <!--
+ <p>[Editor's note: the web portable URL is a placeholder and will be replaced once the actual URL is implemented.]</p>
+ -->
+
+ <p>Testers can self-review the test results through the portal until they are ready to ask for CVP review. They may also update with or add new test results as needed.</p>
+
+ <p>Once the tester is satisfied with the test result, the tester grants access to the test result for CVP review via the portal. The test result is identified by the unique Test ID.</p>
+
+ <p>Notify via the official CVP email address that a review request has been made and reference the Test ID. This will alert the C&C Committee to start the CVP review process.</p>
+
+ <hr>
+ <h2>Step 4: CVP Review</h2>
+ <p>Upon receiving the email notification and the Test ID, the C&C Committee conducts a peer based review of the test result. Persons employed by the same organization that submitted the test results or by affiliated organizations should not be part of the reviewers.</p>
+
+ <p>The primary contact may be asked via email for any missing information or clarification of the application. The reviewers will make a determination and recommend to the C&C Committee. Normally, the outcome of the review should be communicated to the tester within 10 business days after all required information is in order.</p>
+
+ <p>If an application is denied, an appeal can be made to the C&C Committee or ultimately to the Board of Directors of OPNFV.</p>
+
+ <hr>
+ <h2>Step 5: Grant of Use of Logo</h2>
+ <p>If an application is approved, further information will be communicated to the tester on the guidelines of using OPNFV logos for promotional purposes.</p>
+ <hr>
+ </div>
+</div>
+
diff --git a/cvp/3rd_party/static/testapi-ui/components/home/homeController.js b/cvp/3rd_party/static/testapi-ui/components/home/homeController.js
new file mode 100644
index 00000000..bd1ab0f9
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/home/homeController.js
@@ -0,0 +1,42 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ angular
+ .module('testapiApp')
+ .controller('HomeController', HomeController);
+
+ HomeController.$inject = [
+ '$scope', '$rootScope', '$state'
+ ];
+
+ /**
+ * TestAPI Results Controller
+ * This controller is for the '/results' page where a user can browse
+ * a listing of community uploaded results.
+ */
+ function HomeController($scope, $rootScope, $state) {
+ var ctrl = this;
+
+ ctrl.gotoApplication = function(){
+ if($rootScope.auth.isAuthenticated){
+ $state.go('application');
+ }else{
+ $rootScope.auth.doSignIn('cas');
+ }
+ }
+ }
+})();
diff --git a/cvp/3rd_party/static/testapi-ui/components/logout/logout.html b/cvp/3rd_party/static/testapi-ui/components/logout/logout.html
new file mode 100644
index 00000000..38a5c369
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/logout/logout.html
@@ -0,0 +1 @@
+<div cg-busy="{promise:ctrl.redirectWait,message:'Logging you out...'}"></div>
diff --git a/cvp/3rd_party/static/testapi-ui/components/logout/logoutController.js b/cvp/3rd_party/static/testapi-ui/components/logout/logoutController.js
new file mode 100644
index 00000000..1b6d78c6
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/logout/logoutController.js
@@ -0,0 +1,44 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ angular
+ .module('testapiApp')
+ .controller('LogoutController', LogoutController);
+
+ LogoutController.$inject = [
+ '$location', '$window', '$timeout'
+ ];
+
+ /**
+ * TestAPI Logout Controller
+ * This controller handles logging out. In order to fully logout, the
+ * openstackid_session cookie must also be removed. The way to do that
+ * is to have the user's browser make a request to the openstackid logout
+ * page. We do this by placing the logout link as the src for an html
+ * image. After some time, the user is redirected home.
+ */
+ function LogoutController($location, $window, $timeout) {
+ var ctrl = this;
+
+ ctrl.openid_logout_url = $location.search().openid_logout;
+ var img = new Image(0, 0);
+ img.src = ctrl.openid_logout_url;
+ ctrl.redirectWait = $timeout(function() {
+ $window.location.href = '/';
+ }, 500);
+ }
+})();
diff --git a/cvp/3rd_party/static/testapi-ui/components/profile/importPubKeyModal.html b/cvp/3rd_party/static/testapi-ui/components/profile/importPubKeyModal.html
new file mode 100644
index 00000000..0f55c27f
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/profile/importPubKeyModal.html
@@ -0,0 +1,27 @@
+<div class="modal-header">
+ <h4>Import Public Key</h4>
+ <p>Instructions for adding a public key and signature can be found
+ <a href="https://github.com/openstack/refstack/blob/master/doc/source/uploading_private_results.rst#generate-ssh-keys-locally"
+ target="_blank"
+ title="How to generate and upload SSH key and signature with testapi-client">here.
+ </a>
+ </p>
+</div>
+<div class="modal-body container-fluid">
+ <div class="row">
+ <div class="col-md-2">Public Key</div>
+ <div class="col-md-9 pull-right">
+ <textarea type="text" rows="10" cols="42" ng-model="modal.raw_key" required></textarea>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-2">Signature</div>
+ <div class="col-md-9 pull-right">
+ <textarea type="text" rows="10" cols="42" ng-model="modal.self_signature" required></textarea>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-warning btn-sm" ng-click="modal.cancel()">Cancel</button>
+ <button type="button" class="btn btn-default btn-sm" ng-click="modal.importPubKey()">Import Public Key</button>
+ </div>
+</div>
diff --git a/cvp/3rd_party/static/testapi-ui/components/profile/profile.html b/cvp/3rd_party/static/testapi-ui/components/profile/profile.html
new file mode 100644
index 00000000..b41a101c
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/profile/profile.html
@@ -0,0 +1,38 @@
+<h3>User profile</h3>
+<div cg-busy="{promise:ctrl.authRequest,message:'Loading'}"></div>
+<div>
+ <table class="table table-striped table-hover">
+ <tbody>
+ <tr> <td>User name</td> <td>{{auth.currentUser.fullname}}</td> </tr>
+ <tr> <td>User OpenId</td> <td>{{auth.currentUser.openid}}</td> </tr>
+ <tr> <td>Email</td> <td>{{auth.currentUser.email}}</td> </tr>
+ <tr> <td>Role</td> <td> {{auth.currentUser.role}}</td> </tr>
+ </tbody>
+ </table>
+</div>
+<div ng-show="ctrl.pubkeys">
+ <div class="container-fluid">
+ <div class="row">
+ <div class="col-md-4">
+ <h4>User Public Keys</h4>
+ </div>
+ <div class="col-md-2 pull-right">
+ <button type="button" class="btn btn-default btn-sm" ng-click="ctrl.openImportPubKeyModal()">
+ <span class="glyphicon glyphicon-plus"></span> Import Public Key
+ </button>
+ </div>
+ </div>
+ </div>
+
+ <div>
+ <table class="table table-striped table-hover">
+ <tbody>
+ <tr ng-repeat="pubKey in ctrl.pubkeys" ng-click="ctrl.openShowPubKeyModal(pubKey)">
+ <td>{{pubKey.format}}</td>
+ <td>{{pubKey.shortKey}}</td>
+ <td>{{pubKey.comment}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
diff --git a/cvp/3rd_party/static/testapi-ui/components/profile/profileController.js b/cvp/3rd_party/static/testapi-ui/components/profile/profileController.js
new file mode 100644
index 00000000..0660e19f
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/profile/profileController.js
@@ -0,0 +1,219 @@
+/*
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ angular
+ .module('testapiApp')
+ .factory('PubKeys', PubKeys);
+
+ PubKeys.$inject = ['$resource', 'testapiApiUrl'];
+
+ /**
+ * This is a provider for the user's uploaded public keys.
+ */
+ function PubKeys($resource, testapiApiUrl) {
+ return $resource(testapiApiUrl + '/profile/pubkeys/:id', null, null);
+ }
+
+ angular
+ .module('testapiApp')
+ .controller('ProfileController', ProfileController);
+
+ ProfileController.$inject = [
+ '$scope', '$http', 'testapiApiUrl', 'PubKeys',
+ '$uibModal', 'raiseAlert', '$state'
+ ];
+
+ /**
+ * TestAPI Profile Controller
+ * This controller handles user's profile page, where a user can view
+ * account-specific information.
+ */
+ function ProfileController($scope, $http, testapiApiUrl,
+ PubKeys, $uibModal, raiseAlert, $state) {
+
+ var ctrl = this;
+
+ ctrl.updatePubKeys = updatePubKeys;
+ ctrl.openImportPubKeyModal = openImportPubKeyModal;
+ ctrl.openShowPubKeyModal = openShowPubKeyModal;
+
+ // Must be authenticated to view this page.
+ if (!$scope.auth.isAuthenticated) {
+ $state.go('home');
+ }
+
+ /**
+ * This function will fetch all the user's public keys from the
+ * server and store them in an array.
+ */
+ function updatePubKeys() {
+ var keys = PubKeys.query(function() {
+ ctrl.pubkeys = [];
+ angular.forEach(keys, function (key) {
+ ctrl.pubkeys.push({
+ 'resource': key,
+ 'format': key.format,
+ 'shortKey': [
+ key.pubkey.slice(0, 10),
+ '.',
+ key.pubkey.slice(-10)
+ ].join('.'),
+ 'pubkey': key.pubkey,
+ 'comment': key.comment
+ });
+ });
+ });
+ }
+
+ /**
+ * This function will open the modal that will give the user a form
+ * for importing a public key.
+ */
+ function openImportPubKeyModal() {
+ $uibModal.open({
+ templateUrl: '/components/profile/importPubKeyModal.html',
+ backdrop: true,
+ windowClass: 'modal',
+ controller: 'ImportPubKeyModalController as modal'
+ }).result.finally(function() {
+ ctrl.updatePubKeys();
+ });
+ }
+
+ /**
+ * This function will open the modal that will give the full
+ * information regarding a specific public key.
+ * @param {Object} pubKey resource
+ */
+ function openShowPubKeyModal(pubKey) {
+ $uibModal.open({
+ templateUrl: '/components/profile/showPubKeyModal.html',
+ backdrop: true,
+ windowClass: 'modal',
+ controller: 'ShowPubKeyModalController as modal',
+ resolve: {
+ pubKey: function() {
+ return pubKey;
+ }
+ }
+ }).result.finally(function() {
+ ctrl.updatePubKeys();
+ });
+ }
+
+ ctrl.authRequest = $scope.auth.doSignCheck().then(ctrl.updatePubKeys);
+ }
+
+ angular
+ .module('testapiApp')
+ .controller('ImportPubKeyModalController', ImportPubKeyModalController);
+
+ ImportPubKeyModalController.$inject = [
+ '$uibModalInstance', 'PubKeys', 'raiseAlert'
+ ];
+
+ /**
+ * Import Pub Key Modal Controller
+ * This controller is for the modal that appears if a user wants to import
+ * a public key.
+ */
+ function ImportPubKeyModalController($uibModalInstance,
+ PubKeys, raiseAlert) {
+
+ var ctrl = this;
+
+ ctrl.importPubKey = importPubKey;
+ ctrl.cancel = cancel;
+
+ /**
+ * This function will save a new public key resource to the API server.
+ */
+ function importPubKey() {
+ var newPubKey = new PubKeys(
+ {raw_key: ctrl.raw_key, self_signature: ctrl.self_signature}
+ );
+ newPubKey.$save(
+ function(newPubKey_) {
+ raiseAlert('success', '', 'Public key saved successfully');
+ $uibModalInstance.close(newPubKey_);
+ },
+ function(httpResp) {
+ raiseAlert('danger',
+ httpResp.statusText, httpResp.data.title);
+ ctrl.cancel();
+ }
+ );
+ }
+
+ /**
+ * This function will dismiss the modal.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+ }
+
+ angular
+ .module('testapiApp')
+ .controller('ShowPubKeyModalController', ShowPubKeyModalController);
+
+ ShowPubKeyModalController.$inject = [
+ '$uibModalInstance', 'raiseAlert', 'pubKey'
+ ];
+
+ /**
+ * Show Pub Key Modal Controller
+ * This controller is for the modal that appears if a user wants to see the
+ * full details of one of their public keys.
+ */
+ function ShowPubKeyModalController($uibModalInstance, raiseAlert, pubKey) {
+ var ctrl = this;
+
+ ctrl.deletePubKey = deletePubKey;
+ ctrl.cancel = cancel;
+
+ ctrl.pubKey = pubKey.resource;
+ ctrl.rawKey = [pubKey.format, pubKey.pubkey, pubKey.comment].join('\n');
+
+ /**
+ * This function will delete a public key resource.
+ */
+ function deletePubKey() {
+ ctrl.pubKey.$remove(
+ {id: ctrl.pubKey.id},
+ function() {
+ raiseAlert('success',
+ '', 'Public key deleted successfully');
+ $uibModalInstance.close(ctrl.pubKey.id);
+ },
+ function(httpResp) {
+ raiseAlert('danger',
+ httpResp.statusText, httpResp.data.title);
+ ctrl.cancel();
+ }
+ );
+ }
+
+ /**
+ * This method will dismiss the modal.
+ */
+ function cancel() {
+ $uibModalInstance.dismiss('cancel');
+ }
+ }
+})();
diff --git a/cvp/3rd_party/static/testapi-ui/components/profile/showPubKeyModal.html b/cvp/3rd_party/static/testapi-ui/components/profile/showPubKeyModal.html
new file mode 100644
index 00000000..5f63a5ef
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/profile/showPubKeyModal.html
@@ -0,0 +1,11 @@
+<div class="modal-header">
+ <h4>Public Key</h4>
+</div>
+<div class="modal-body container-fluid">
+ <textarea type="text" rows="10" cols="67" readonly="readonly">{{modal.rawKey}}</textarea>
+ <div class="modal-footer">
+ <button class="btn btn-warning" ng-click="modal.cancel()">Cancel</button>
+ <button type="button" class="btn btn-danger btn-sm" ng-click="modal.deletePubKey() "
+ confirm="Are you sure you want to delete this public key? You will lose management access to any test results signed with this key.">Delete</button>
+ </div>
+</div>
diff --git a/cvp/3rd_party/static/testapi-ui/components/results-report/partials/editTestModal.html b/cvp/3rd_party/static/testapi-ui/components/results-report/partials/editTestModal.html
new file mode 100644
index 00000000..583c9b92
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/results-report/partials/editTestModal.html
@@ -0,0 +1,65 @@
+<div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" aria-hidden="true" ng-click="modal.close()">&times;</button>
+ <h4>Edit Test Run Metadata</h4>
+ <p>Make changes to your test metadata.</p>
+ </div>
+ <div class="modal-body">
+ <div class="form-group">
+ <strong>Publicly Shared:</strong>
+ <select ng-model="modal.metaCopy.shared"
+ class="form-control">
+ <option value="true">Yes</option>
+ <option value="">No</option>
+ </select>
+ <br />
+ <strong>Associated Guideline:</strong>
+ <select ng-model="modal.metaCopy.guideline"
+ ng-options="o as o.slice(0, -5) for o in modal.versionList"
+ class="form-control">
+ <option value="">None</option>
+ </select>
+ <br />
+ <strong>Associated Target Program:</strong>
+ <select ng-model="modal.metaCopy.target"
+ class="form-control">
+ <option value="">None</option>
+ <option value="platform">OpenStack Powered Platform</option>
+ <option value="compute">OpenStack Powered Compute</option>
+ <option value="object">OpenStack Powered Object Storage</option>
+ </select>
+ <hr>
+ <strong>Associated Product:</strong>
+ <select ng-options="product as product.name for product in modal.products | arrayConverter | orderBy: 'name' track by product.id"
+ ng-model="modal.selectedProduct"
+ ng-change="modal.getProductVersions()"
+ class="form-control">
+ <option value="">-- No Product --</option>
+ </select>
+
+ <span ng-if="modal.productVersions.length">
+ <strong>Product Version:</strong>
+ <select ng-options="version as version.version for version in modal.productVersions | orderBy: 'version' track by version.id"
+ ng-model="modal.selectedVersion"
+ class="form-control">
+ </select>
+
+ </span>
+
+ </div>
+ <div ng-show="modal.showError" class="alert alert-danger" role="alert">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
+ <span class="sr-only">Error:</span>
+ {{modal.error}}
+ </div>
+ <div ng-show="modal.showSuccess" class="alert alert-success" role="success">
+ <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
+ <span class="sr-only">Success:</span>
+ Changes saved successfully.
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-primary" type="button" ng-click="modal.saveChanges()">Save Changes</button>
+ <button class="btn btn-primary" type="button" ng-click="modal.close()">Close</button>
+ </div>
+</div>
diff --git a/cvp/3rd_party/static/testapi-ui/components/results-report/partials/fullTestListModal.html b/cvp/3rd_party/static/testapi-ui/components/results-report/partials/fullTestListModal.html
new file mode 100644
index 00000000..6db198b0
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/results-report/partials/fullTestListModal.html
@@ -0,0 +1,13 @@
+<div class="modal-content">
+ <div class="modal-header">
+ <h4>All Passed Tests ({{modal.tests.length}})</h4>
+ </div>
+ <div class="modal-body tests-modal-content">
+ <div class="form-group">
+ <textarea class="form-control" rows="20" id="tests" wrap="off">{{modal.getTestListString()}}</textarea>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-primary" type="button" ng-click="modal.close()">Close</button>
+ </div>
+</div>
diff --git a/cvp/3rd_party/static/testapi-ui/components/results-report/partials/reportDetails.html b/cvp/3rd_party/static/testapi-ui/components/results-report/partials/reportDetails.html
new file mode 100644
index 00000000..9f8ed140
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/results-report/partials/reportDetails.html
@@ -0,0 +1,65 @@
+<!--
+HTML for each accordion group that separates the status types on the results
+report page.
+-->
+
+Test Filters:<br />
+<div class="btn-toolbar" role="toolbar">
+ <div class="btn-group button-margin" data-toggle="buttons">
+ <label class="btn btn-default" ng-class="{'active': ctrl.testStatus === 'total'}">
+ <input type="radio" ng-model="ctrl.testStatus" value="total">
+ <span class="text-primary">All</span>
+ </label>
+ <label class="btn btn-default" ng-class="{'active': ctrl.testStatus === 'passed'}">
+ <input type="radio" ng-model="ctrl.testStatus" value="passed">
+ <span class="text-success">Passed</span>
+ </label>
+ <label class="btn btn-default" ng-class="{'active': ctrl.testStatus === 'not passed'}">
+ <input type="radio" ng-model="ctrl.testStatus" value="not passed">
+ <span class="text-danger">Not Passed</span>
+ </label>
+ </div>
+ <div class="btn-group button-margin" style="float:right">
+ <button type="button" class="btn btn-default" ng-click="ctrl.openAll()">Expand</button>
+ <button type="button" class="btn btn-default" ng-click="ctrl.folderAll()">Collapse</button>
+ </div>
+</div>
+
+<uib-accordion-group is-open="isOpen" is-disabled="ctrl.cases == 0">
+<uib-accordion-heading>
+ {{ ctrl.testId }}
+ <small>
+ (<strong>Total:</strong> {{ ctrl.cases.length }} tests)
+ </small>
+ <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': isOpen, 'glyphicon-chevron-right': !isOpen}"></i>
+ </uib-accordion-heading>
+ <ol class="capabilities">
+ <li ng-repeat="testcase in ctrl.cases" ng-show="(ctrl.testStatus == 'passed' && testcase.pass != 0) || (ctrl.testStatus == 'not passed' && testcase.fail != 0) || ctrl.testStatus == 'total'">
+
+ <a ng-click="testcase.folder = !testcase.folder">
+ {{ testcase.build_tag.split('-').pop() }}
+ <span ng-if="ctrl.testStatus == 'total'" ng-class="{'text-success': testcase.total == testcase.pass, 'text-warning': (testcase.pass < testcase.total && testcase.pass > 0), 'text-danger': testcase.pass == 0}">[{{ testcase.pass }}/{{ testcase.total }}]</span>
+ <span ng-if="ctrl.testStatus == 'passed'" class="text-success">[{{ testcase.pass }}]</span>
+ <span ng-if="ctrl.testStatus == 'not passed'" class="text-danger">[{{ testcase.fail }}]</span>
+ </a>
+
+ <ul class="list-unstyled" uib-collapse="testcase.folder">
+ <li ng-if="!testcase.details.success">
+ <span ng-class="{'glyphicon glyphicon-ok text-success':testcase.criteria == 'PASS'}" aria-hidden="true"></span>
+ <span ng-class="{'glyphicon glyphicon-remove text-warning':testcase.criteria != 'PASS'}"></span>
+ {{ testcase.case_name }}
+ </li>
+
+ <li ng-repeat="sub in testcase.details.success" ng-if="testcase.details.success && ctrl.testStatus != 'not passed'">
+ <span class="glyphicon glyphicon-ok text-success" aria-hidden="true"></span>
+ <a ng-click="ctrl.gotoDoc(sub)">{{ sub }}</a>
+ </li>
+
+ <li ng-repeat="sub in testcase.details.errors" ng-if="testcase.details.errors && ctrl.testStatus != 'passed'">
+ <span class="glyphicon glyphicon-remove text-warning"></span>
+ <a ng-click="ctrl.gotoDoc(sub)">{{ sub }}</a>
+ </li>
+ </ul>
+ </li>
+ </ol>
+</uib-accordion-group>
diff --git a/cvp/3rd_party/static/testapi-ui/components/results-report/resultsReport.html b/cvp/3rd_party/static/testapi-ui/components/results-report/resultsReport.html
new file mode 100644
index 00000000..537a3460
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/results-report/resultsReport.html
@@ -0,0 +1,46 @@
+<h3>Test Run Results</h3>
+
+<div ng-show="ctrl.testId" class="container-fluid">
+ <div class="row">
+ <div class="pull-left">
+ <div class="test-report">
+ <strong>Test ID:</strong> {{ctrl.testId}}<br />
+ </div>
+ </div>
+ </div>
+</div>
+
+<strong>Total: {{ctrl.total}}, Pass: {{ ctrl.mandatory_pass + ctrl.optional_pass }}, Rate: {{ (ctrl.mandatory_pass + ctrl.optional_pass) / ctrl.total * 100 | number:2 }}%</strong></br>
+<strong>Mandatory Total: {{ctrl.mandatory_total}}, Pass: {{ ctrl.mandatory_pass }}, Rate: {{ ctrl.mandatory_pass / ctrl.mandatory_total * 100 | number:2 }}%</strong></br>
+<strong>Optional Total: {{ctrl.optional_total}}, Pass: {{ ctrl.optional_pass }}, Rate: {{ ctrl.optional_pass / ctrl.optional_total * 100 | number:2 }}%</strong></br>
+
+<div ng-show="ctrl.cases">
+ <hr >
+
+ <div ng-show="ctrl.cases">
+
+ <hr>
+ <h4>Test Result Overview</h4>
+
+ <uib-accordion close-others=false>
+ <!-- The ng-repeat is used to pass in a local variable to the template. -->
+ <ng-include
+ src="ctrl.detailsTemplate"
+ onload="isOpen = true">
+ </ng-include>
+ <br />
+ </uib-accordion>
+ </div>
+</div>
+
+<!--
+<div class="loading">
+ <div cg-busy="{promise:resultsRequest,message:'Loading results'}"></div>
+</div>
+
+<div ng-show="ctrl.showError" class="alert alert-danger" role="alert">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
+ <span class="sr-only">Error:</span>
+ {{ctrl.error}}
+</div>
+-->
diff --git a/cvp/3rd_party/static/testapi-ui/components/results-report/resultsReportController.js b/cvp/3rd_party/static/testapi-ui/components/results-report/resultsReportController.js
new file mode 100644
index 00000000..5f8cac8e
--- /dev/null
+++ b/cvp/3rd_party/static/testapi-ui/components/results-report/resultsReportController.js
@@ -0,0 +1,182 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+ 'use strict';
+
+ angular
+ .module('testapiApp')
+ .controller('ResultsReportController', ResultsReportController);
+
+ ResultsReportController.$inject = [
+ '$http', '$stateParams', '$window',
+ '$uibModal', 'testapiApiUrl', 'raiseAlert'
+ ];
+
+ /**
+ * TestAPI Results Report Controller
+ * This controller is for the '/results/<test run ID>' page where a user can
+ * view details for a specific test run.
+ */
+ function ResultsReportController($http, $stateParams, $window,
+ $uibModal, testapiApiUrl, raiseAlert) {
+
+ var ctrl = this;
+
+ ctrl.getResults = getResults;
+ ctrl.gotoDoc = gotoDoc;
+ ctrl.openAll = openAll;
+ ctrl.folderAll = folderAll;
+
+ /** The testID extracted from the URL route. */
+ ctrl.testId = $stateParams.testID;
+ ctrl.innerId = $stateParams.innerID;
+
+ /** The HTML template that all accordian groups will use. */
+ ctrl.detailsTemplate = 'testapi-ui/components/results-report/partials/' +
+ 'reportDetails.html';
+
+ ctrl.total = 0;
+ ctrl.mandatory_total = 0;
+ ctrl.mandatory_pass = 0;
+ ctrl.mandatory_fail = 0;
+ ctrl.optional_total = 0;
+ ctrl.optional_pass = 0;
+ ctrl.optional_fail = 0;
+
+ ctrl.testStatus = 'total';
+
+
+ /**
+ * Retrieve results from the TestAPI API server based on the test
+ * run id in the URL. This function is the first function that will
+ * be called from the controller. Upon successful retrieval of results,
+ * the function that gets the version list will be called.
+ */
+ function getResults() {
+ ctrl.cases = {};
+ $http.get(testapiApiUrl + '/tests/' + ctrl.innerId).success(function(test_data){
+ var results = test_data.results;
+ angular.forEach(results, function(ele){
+ var content_url = testapiApiUrl + '/results/' + ele;
+ ctrl.resultsRequest =
+ $http.get(content_url).success(function(data) {
+ var result_case = data;
+ if(result_case.project_name == 'yardstick'){
+ yardstickHandler(result_case);
+ }else{
+ functestHandler(result_case);
+ }
+ result_case.folder = true;
+ ctrl.cases[result_case._id] = result_case;
+ count(result_case);
+ }).error(function (error) {
+ ctrl.showError = true;
+ ctrl.resultsData = null;
+ ctrl.error = 'Error retrieving results from server: ' +
+ angular.toJson(error);
+ });
+ });
+ });
+ }
+
+ function functestHandler(result_case){
+ result_case.total = 0;
+ result_case.pass = 0;
+ result_case.fail = 0;
+ if(result_case.details.success && result_case.details.success.length != 0){
+ var sub_cases = result_case.details.success;
+ if(result_case.case_name != 'refstack_defcore'){
+ angular.forEach(sub_cases, function(ele, index){
+ sub_cases[index] = ele.split(' ')[ele.split(' ').length - 1];
+ });
+ }
+ result_case.details.success = sub_cases;
+ result_case.total += sub_cases.length;
+ result_case.pass += sub_cases.length;
+ }
+ if(result_case.details.errors && result_case.details.errors.length != 0){
+ var sub_cases = result_case.details.errors;
+ if(result_case.case_name != 'refstack_defcore'){
+ angular.forEach(sub_cases, function(ele, index){
+ sub_cases[index] = ele.split(' ')[ele.split(' ').length - 1];
+ });
+ }
+ result_case.details.errors = sub_cases;
+ result_case.total += sub_cases.length;
+ result_case.fail += sub_cases.length;
+ }
+ if(result_case.total == 0){
+ result_case.total = 1;
+ if(result_case.criteria == 'PASS'){
+ result_case.pass = 1;
+ }else{
+ result_case.fail = 1;
+ }
+ }
+ }
+
+ function yardstickHandler(result_case){
+ result_case.total = 0;
+ result_case.pass = 0;
+ result_case.fail = 0;
+ angular.forEach(result_case.details.results, function(ele){
+ if(ele.benchmark){
+ result_case.total = 1;
+ if(ele.benchmark.data.sla_pass == 1){
+ result_case.criteria = 'PASS';
+ result_case.pass = 1;
+ }else{
+ result_case.criteria = 'FAILED';
+ result_case.fail = 1;
+ }
+ return false;
+ }
+ });
+ }
+
+ function count(result_case){
+ var build_tag = result_case.build_tag;
+ var tag = build_tag.split('-').pop().split('.')[1];
+ ctrl.total += result_case.total;
+ if(tag == 'ha' || tag == 'defcore' || tag == 'vping'){
+ ctrl.mandatory_total += result_case.total;
+ ctrl.mandatory_pass += result_case.pass;
+ ctrl.mandatory_fail += result_case.fail;
+ }else{
+ ctrl.optional_total += result_case.total;
+ ctrl.optional_pass += result_case.pass;
+ ctrl.optional_fail += result_case.fail;
+ }
+ }
+
+ function gotoDoc(sub_case){
+ }
+
+ function openAll(){
+ angular.forEach(ctrl.cases, function(id, ele){
+ ele.folder = false;
+ });
+ }
+
+ function folderAll(){
+ angular.forEach(ctrl.cases, function(id, ele){
+ ele.folder = true;
+ });
+ }
+
+ getResults();
+ }
+
+})();