From: mei mei Date: Wed, 6 Dec 2017 02:57:36 +0000 (+0000) Subject: Merge "Don't verify Danube and verify Euphrates" X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=commitdiff_plain;h=24e8cc66450544a30f031d40ed53f94154f2a349;hp=8c2105649d96563cf8d84c7beee6592f8bb5f917;p=releng.git Merge "Don't verify Danube and verify Euphrates" --- diff --git a/.gitignore b/.gitignore index eeabaeb63..4309e8e26 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,6 @@ node_modules/ cover/ coverage.xml nosetests.xml -testapi_venv/ .cache .tox *.retry diff --git a/INFO b/INFO index 38ac5b3d2..18c8cf2ce 100644 --- a/INFO +++ b/INFO @@ -9,7 +9,7 @@ Jira Project Prefix: RELENG Mailing list tag: [releng] IRC: Server:freenode.net Channel:#opnfv-octopus Repository: releng -Other Repositories: releng-xci +Other Repositories: releng-xci, releng-testresults Committers: Fatih Degirmenci (Ericsson, fatih.degirmenci@ericsson.com) diff --git a/docs/ci/index.rst b/docs/ci/index.rst new file mode 100644 index 000000000..da6fc7de1 --- /dev/null +++ b/docs/ci/index.rst @@ -0,0 +1,18 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _ci-overview: + +======== +OPNFV CI +======== + +TBD + +.. toctree:: + :numbered: + :maxdepth: 2 + + user-guide + resources diff --git a/docs/ci/resources.rst b/docs/ci/resources.rst new file mode 100644 index 000000000..572852c48 --- /dev/null +++ b/docs/ci/resources.rst @@ -0,0 +1,61 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _ci-resources: + +============ +CI Resources +============ + +CI for OPNFV requires a range of resources in order to meet testing and +verification needs. Each resource must meet a set of criteria in order +to be part of CI for an OPNFV release. There are three types of +resources: + + - Baremetal PODs (PODs) + - Virtual PODs (vPODs) + - Build Servers + +-------------- +Baremetal PODs +-------------- + +TBD + +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Baremetal PODs Requirements +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In order of a POD to be considered CI-Ready the following requirements +must be met: + + #. Pharos Compliant and has a PDF + #. Connected to Jenkins + #. 24/7 Uptime + #. No Development + #. No manual intervention + +------------ +Virtual PODS +------------ + +TBD + +~~~~~~~~~~~~ +Requirements +~~~~~~~~~~~~ + +TBD + +------------- +Build Servers +------------- + +TBD + +~~~~~~~~~~~~ +Requirements +~~~~~~~~~~~~ + +TBD diff --git a/docs/ci/user-guide.rst b/docs/ci/user-guide.rst new file mode 100644 index 000000000..9c9b74a41 --- /dev/null +++ b/docs/ci/user-guide.rst @@ -0,0 +1,11 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _ci-user-guide: + +============= +CI User Guide +============= + +TBD diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 000000000..62a828adf --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,17 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _releng: + +=================== +Release Engineering +=================== + +.. toctree:: + :numbered: + :maxdepth: 2 + + release/index + ci/index + infra/index diff --git a/docs/infra/artifacts/docker-hub.rst b/docs/infra/artifacts/docker-hub.rst new file mode 100644 index 000000000..1da6c474a --- /dev/null +++ b/docs/infra/artifacts/docker-hub.rst @@ -0,0 +1,12 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _docker-hub: + +========== +Docker Hub +========== + +TBD + diff --git a/docs/infra/artifacts/index.rst b/docs/infra/artifacts/index.rst new file mode 100644 index 000000000..28b3b45fb --- /dev/null +++ b/docs/infra/artifacts/index.rst @@ -0,0 +1,11 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _artifact-repository: + +=================== +Artifact Repository +=================== + +TBD diff --git a/docs/infra/gerrit/user-guide.rst b/docs/infra/gerrit/user-guide.rst new file mode 100644 index 000000000..3b1c3f807 --- /dev/null +++ b/docs/infra/gerrit/user-guide.rst @@ -0,0 +1,9 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _gerrit: + +================= +Gerrit User Guide +================= diff --git a/docs/infra/index.rst b/docs/infra/index.rst new file mode 100644 index 000000000..50c971e75 --- /dev/null +++ b/docs/infra/index.rst @@ -0,0 +1,93 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _software-infrastructure: + +======================= +Software Infrastructure +======================= + +OPNFV Software Infrastructure consists of set of components and tools that +realize OPNFV Continuous Integration (CI) and provide means for community to +contribute to OPNFV in most efficient way. OPNFV Software Infrastructure +enables and orchestrates development, integration and testing activities for +the components OPNFV consumes from upstream communities and for the development +work done in scope of OPNFV. Apart from orchestration aspects, providing timely +feedback that is fit for purpose to the OPNFV community is one of its missions. + +CI is the top priority for OPNFV Software Infrastructure. Due to the importance +the OPNFV community puts into it, the resulting CI machinery is highly +powerful, capable and runs against distributed hardware infrastructure managed +by OPNFV Pharos_ Project. The hardware infrastructure OPNFV CI relies on is +located in 3 different continents, 5+ different countries and 10+ different +member companies. + +OPNFV CI is continuously evolved in order to fulfill the needs and match the +expectations of the OPNFV community. + +OPNFV Software Infrastructure is developed, maintained and operated by OPNFV +Releng_ Project with the support from Linux Foundation. + +Continuous Integration Server +----------------------------- + +Jenkins + +.. toctree:: + :maxdepth: 1 + + jenkins/connect-to-jenkins + jenkins/user-guide + jenkins/jjb-usage + jenkins/labels + +Source Control and Code Review +------------------------------ + +Gerrit + +.. toctree:: + :maxdepth: 1 + + gerrit/user-guide + +Artifact and Image Repositories +------------------------------- + +Google Storage & Docker Hub + +.. toctree:: + :maxdepth: 1 + + artifacts/index + artifacts/docker-hub + + +Issue and Bug Tracking +---------------------- + +JIRA + +.. toctree:: + :maxdepth: + + jira/user-guide + + +Dashboards and Analytics +------------------------ + + - `Pharos Dashboard`_ + + - `Test Results`_ + + - `Bitergia Dashboard`_ + + +.. _Pharos: https://wiki.opnfv.org/display/pharos/Pharos+Home +.. _Releng: https://wiki.opnfv.org/display/releng/Releng + +.. _Bitergia Dashboard: https://opnfv.biterg.io/ +.. _Pharos Dashboard: https://labs.opnfv.org/ +.. _Test Results: https://testresults.opnfv.org/ diff --git a/docs/infra/jenkins/connect-to-jenkins.rst b/docs/infra/jenkins/connect-to-jenkins.rst new file mode 100644 index 000000000..e83cadada --- /dev/null +++ b/docs/infra/jenkins/connect-to-jenkins.rst @@ -0,0 +1,187 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _connect-to-jenkins: + +================================================ +Connecting OPNFV Community Labs to OPNFV Jenkins +================================================ + +.. contents:: Table of Contents + :backlinks: none + +Abstract +======== + +This document describes how to connect resources (servers) located in Linux Foundation (LF) lab +and labs provided by the OPNFV Community to OPNFV Jenkins. + +License +======= +Connecting OPNFV Community Labs to OPNFV Jenkins (c) by Fatih Degirmenci (Ericsson AB) and others. + +Connecting OPNFV Labs to OPNFV Jenkins document is licensed under a Creative Commons +Attribution 4.0 International License. + +You should have received a copy of the license along with this. If not, see . + + +Version History +=============== + ++------------+-------------+------------------+---------------------------------------+ +| **Date** | **Version** | **Author** | **Comment** | +| | | | | ++------------+-------------+------------------+---------------------------------------+ +| 2015-05-05 | 0.1.0 | Fatih Degirmenci | First draft | +| | | | | ++------------+-------------+------------------+---------------------------------------+ +| 2015-09-25 | 1.0.0 | Fatih Degirmenci | Instructions for the | +| | | | Arno SR1 release | ++------------+-------------+------------------+---------------------------------------+ +| 2016-01-25 | 1.1.0 | Jun Li | Change the format for | +| | | | new doc toolchain | ++------------+-------------+------------------+---------------------------------------+ +| 2016-01-27 | 1.2.0 | Fatih Degirmenci | Instructions for the | +| | | | Brahmaputra release | ++------------+-------------+------------------+---------------------------------------+ +| 2016-05-25 | 1.3.0 | Julien | Add an additional step after step9 to | +| | | | output the correct monit config file | ++------------+-------------+------------------+---------------------------------------+ + +Jenkins +======= + +Jenkins is an extensible open source Continuous Integration (CI) server. [1] + +Linux Foundation (LF) hosts and operates `OPNFV Jenkins `_. + +Jenkins Slaves +============== + +**Slaves** are computers that are set up to build projects for a **Jenkins Master**. [2] + +Jenkins runs a separate program called "**slave agent**" on slaves. +When slaves are registered to a master, the master starts distributing load to slaves by +scheduling jobs to run on slaves if the jobs are set to run on them. [2] + +Term **Node** is used to refer to all machines that are part of Jenkins grid, slaves and +master. [2] + +Two types of slaves are currently connected to OPNFV Jenkins and handling +different tasks depending on the purpose of connecting the slave. + +* Slaves hosted in `LF Lab `_ +* Slaves hosted in `Community Test Labs `_ + +The slaves connected to OPNFV Jenkins can be seen using this link: +https://build.opnfv.org/ci/computer/ + +Slaves without red cross next to computer icon are fully functional. + +Connecting Slaves to OPNFV Jenkins +================================== + +The method that is normally used for connecting slaves to Jenkins requires direct SSH access to +servers. +[3] This is the method that is used for connecting slaves hosted in LF Lab. + +Connecting slaves using direct SSH access can become a challenge given that OPNFV Project +has number of different labs provided by community as mentioned in previous section. +All these labs have different security requirements which can increase the effort +and the time needed for connecting slaves to Jenkins. +In order to reduce the effort and the time needed for connecting slaves and streamline the +process, it has been decided to connect slaves using +`Java Network Launch Protocol (JNLP) `_. + +Connecting Slaves from LF Lab to OPNFV Jenkins +---------------------------------------------- + +Slaves hosted in LF Lab are handled by LF. All the requests and questions regarding +these slaves should be submitted to `OPNFV LF Helpdesk `_. + +Connecting Slaves from Community Labs to OPNFV Jenkins +------------------------------------------------------ + +As noted in corresponding section, slaves from Community Labs are connected using JNLP. Via JNLP, +slaves open connection towards Jenkins Master instead of Jenkins Master accessing to them directly. + +Servers connecting to OPNFV Jenkins using this method must have access to internet. + +Please follow below steps to connect a slave to OPNFV Jenkins. + + 1. Create a user named **jenkins** on the machine you want to connect to OPNFV Jenkins and give the user sudo rights. + 2. Install needed software on the machine you want to connect to OPNFV Jenkins as slave. + - openjdk 8 + - monit + 3. If the slave will be used for running virtual deployments, Functest, and Yardstick, install below software and make jenkins user the member of the groups. + - docker + - libvirt + 4. Create slave root in Jenkins user home directory. + ``mkdir -p /home/jenkins/opnfv/slave_root`` + 5. Clone OPNFV Releng Git repository. + ``mkdir -p /home/jenkins/opnfv/repos`` + + ``cd /home/jenkins/opnfv/repos`` + + ``git clone https://gerrit.opnfv.org/gerrit/p/releng.git`` + 6. Contact LF by sending mail to `OPNFV LF Helpdesk `_ and request creation of a slave on OPNFV Jenkins. Include below information in your mail. + - Slave root (/home/jenkins/opnfv/slave_root) + - Public IP of the slave (You can get the IP by executing ``curl http://icanhazip.com/``) + - PGP Key (attached to the mail or exported to a key server) + 7. Once you get confirmation from LF stating that your slave is created on OPNFV Jenkins, check if the firewall on LF is open for the server you are trying to connect to Jenkins. + ``cp /home/jenkins/opnfv/repos/releng/utils/jenkins-jnlp-connect.sh /home/jenkins/`` + ``cd /home/jenkins/`` + ``sudo ./jenkins-jnlp-connect.sh -j /home/jenkins -u jenkins -n -s -f`` + + - If you receive an error, follow the steps listed on the command output. + 8. Run the same script with test(-t) on foreground in order to make sure no problem on connection. You should see **INFO: Connected** in the console log. + ``sudo ./jenkins-jnlp-connect.sh -j /home/jenkins -u jenkins -n -s -t`` + + - If you receive an error similar to the one shown `on this link `_, you need to check your firewall and allow outgoing connections for the port. + 9. Kill the Java slave.jar process. + 10. Run the same script normally without test(-t) in order to get monit script created. + ``sudo ./jenkins-jnlp-connect.sh -j /home/jenkins -u jenkins -n -s `` + 11. Edit monit configuration and enable http interface. The file to edit is /etc/monit/monitrc on Ubuntu systems. Uncomment below lines. + set httpd port 2812 and + use address localhost # only accept connection from localhost + allow localhost # allow localhost to connect to the server and + 12. Restart monit service. + - Without systemd: + + ``sudo service monit restart`` + - With systemd: you have to enable monit service first and then restart it. + + ``sudo systemctl enable monit`` + + ``sudo systemctl restart monit`` + 13. Check to see if jenkins comes up as managed service in monit. + ``sudo monit status`` + 14. Connect slave to OPNFV Jenkins using monit. + ``sudo monit start jenkins`` + 15. Check slave on OPNFV Jenkins to verify the slave is reported as connected. + - The slave on OPNFV Jenkins should have some executors in “Idle” state if the connection is successful. + +Notes +========== + +PGP Key Instructions +-------------------- + +Public PGP Key can be uploaded to public key server so it can be taken from +there using your mail address. Example command to upload the key to key server is + + ``gpg --keyserver hkp://keys.gnupg.net:80 --send-keys XXXXXXX`` + +The Public PGP Key can also be attached to the email by storing the key in a file and then +attaching it to the email. + + ``gpg --export -a '' > pgp.pubkey`` + +References +========== + +* `What is Jenkins `_ +* `Jenkins Terminology `_ +* `Jenkins SSH Slaves Plugin `_ diff --git a/docs/jenkins-job-builder/opnfv-jjb-usage.rst b/docs/infra/jenkins/jjb-usage.rst similarity index 69% rename from docs/jenkins-job-builder/opnfv-jjb-usage.rst rename to docs/infra/jenkins/jjb-usage.rst index f34833f5c..2be2598d9 100644 --- a/docs/jenkins-job-builder/opnfv-jjb-usage.rst +++ b/docs/infra/jenkins/jjb-usage.rst @@ -1,3 +1,9 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _jjb: + =========================================== Creating/Configuring/Verifying Jenkins Jobs =========================================== @@ -16,9 +22,9 @@ Make changes:: remote: Processing changes: new: 1, refs: 1, done remote: remote: New Changes: - remote: https://gerrit.opnfv.org/gerrit/51 + remote: https://gerrit.opnfv.org/gerrit/ remote: - To ssh://agardner@gerrit.opnfv.org:29418/releng.git + To ssh://YOU@gerrit.opnfv.org:29418/releng.git * [new branch] HEAD -> refs/publish/master Test with tox:: @@ -29,12 +35,12 @@ Submit the change to gerrit:: git review -v -Follow the link to gerrit https://gerrit.opnfv.org/gerrit/51 in a few moments -the verify job will have completed and you will see Verified +1 jenkins-ci in -the gerrit ui. +Follow the link given in the stdoutput to gerrit eg: +``https://gerrit.opnfv.org/gerrit/`` the verify job will +have completed and you will see Verified +1 jenkins-ci in the gerrit ui. If the changes pass the verify job -https://build.opnfv.org/ci/view/builder/job/builder-verify-jjb/ , +https://build.opnfv.org/ci/job/releng-verify-jjb/ , the patch can be submitited by a committer. Job Types @@ -65,24 +71,13 @@ it will reset the verified status to 0. If you want to keep the verified status, use **recheck-experimental** in commit message to trigger both verify and experimental jobs. -You can add below persons as reviewers to your patch in order to get it -reviewed and submitted. - -* fatih.degirmenci@ericsson.com -* agardner@linuxfoundation.org -* trozet@redhat.com -* morgan.richomme@orange.com -* vlaza@cloudbasesolutions.com -* matthew.lijun@huawei.com -* meimei@huawei.com -* jose.lausuch@ericsson.com -* koffirodrigue@gmail.com -* r-mibu@cq.jp.nec.com -* tbramwell@linuxfoundation.org +You can look in the releng/INFO file for a list of current committers to +add as reviewers to your patch in order to get it reviewed and +submitted. Or Add the group releng-contributors -Or just email a request for submission to opnfv-helpdesk@rt.linuxfoundation.org +Or just email a request for review to helpdesk@opnfv.org The Current merge and verify jobs for jenkins job builder can be found in `releng-jobs.yaml`_. diff --git a/docs/infra/jenkins/labels.rst b/docs/infra/jenkins/labels.rst new file mode 100644 index 000000000..6327518af --- /dev/null +++ b/docs/infra/jenkins/labels.rst @@ -0,0 +1,11 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _jenkins-labels: + +=================== +Jenkins Node Labels +=================== + +TBD diff --git a/docs/infra/jenkins/user-guide.rst b/docs/infra/jenkins/user-guide.rst new file mode 100644 index 000000000..60236416a --- /dev/null +++ b/docs/infra/jenkins/user-guide.rst @@ -0,0 +1,11 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _jenkins-user-guide: + +================== +Jenkins User Guide +================== + +TBD diff --git a/docs/infra/jira/user-guide.rst b/docs/infra/jira/user-guide.rst new file mode 100644 index 000000000..5009bc1b0 --- /dev/null +++ b/docs/infra/jira/user-guide.rst @@ -0,0 +1,11 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _jira-user-guide: + +=============== +JIRA User Guide +=============== + +TBD diff --git a/docs/jenkins-job-builder/index.rst b/docs/jenkins-job-builder/index.rst deleted file mode 100644 index 4d23ade38..000000000 --- a/docs/jenkins-job-builder/index.rst +++ /dev/null @@ -1,9 +0,0 @@ -=========================== -Release Engineering Project -=========================== - -.. toctree:: - :numbered: - :maxdepth: 2 - - opnfv-jjb-usage diff --git a/docs/release/index.rst b/docs/release/index.rst new file mode 100644 index 000000000..d7d8acd39 --- /dev/null +++ b/docs/release/index.rst @@ -0,0 +1,17 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _release: + +=============== +Releasing OPNFV +=============== + +.. toctree:: + :numbered: + :maxdepth: 2 + + release-process + stable-branch-guide + versioning diff --git a/docs/release/release-process.rst b/docs/release/release-process.rst new file mode 100644 index 000000000..b88832f95 --- /dev/null +++ b/docs/release/release-process.rst @@ -0,0 +1,11 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _release-process: + +=============== +Release Process +=============== + +TBD diff --git a/docs/release/stable-branch-guide.rst b/docs/release/stable-branch-guide.rst new file mode 100644 index 000000000..a4710f656 --- /dev/null +++ b/docs/release/stable-branch-guide.rst @@ -0,0 +1,11 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _stable-branch: + +============= +Stable Branch +============= + +TBD diff --git a/docs/release/versioning.rst b/docs/release/versioning.rst new file mode 100644 index 000000000..3257d3bea --- /dev/null +++ b/docs/release/versioning.rst @@ -0,0 +1,11 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. SPDX-License-Identifier: CC-BY-4.0 +.. (c) Open Platform for NFV Project, Inc. and its contributors + +.. _versioning: + +========== +Versioning +========== + +TBD diff --git a/jjb/apex/apex-project-jobs.yml b/jjb/apex/apex-project-jobs.yml index 58072865d..b12b1015c 100644 --- a/jjb/apex/apex-project-jobs.yml +++ b/jjb/apex/apex-project-jobs.yml @@ -46,6 +46,10 @@ branch: '{branch}' - apex-parameter: gs-pathname: '{gs-pathname}' + - string: + name: GERRIT_REFSPEC + default: 'refs/heads/{branch}' + description: "JJB configured GERRIT_REFSPEC parameter" scm: - git-scm-gerrit diff --git a/jjb/apex/apex-verify-jobs.yml b/jjb/apex/apex-verify-jobs.yml new file mode 100644 index 000000000..c57ac1d60 --- /dev/null +++ b/jjb/apex/apex-verify-jobs.yml @@ -0,0 +1,364 @@ +--- +- project: + name: 'apex-verify-jobs' + project: 'apex' + jobs: + - 'apex-verify-{stream}' + - 'apex-verify-gate-{stream}' + - 'apex-verify-unit-tests-{stream}' + stream: + - master: &master + branch: '{stream}' + gs-pathname: '' + verify-scenario: 'os-odl-nofeature-ha' + disabled: false + - danube: &danube + branch: 'stable/{stream}' + gs-pathname: '/{stream}' + verify-scenario: 'os-odl_l3-nofeature-ha' + disabled: true + - euphrates: &euphrates + branch: 'stable/{stream}' + gs-pathname: '/{stream}' + verify-scenario: 'os-odl-nofeature-ha' + disabled: false + +# Unit Test +- job-template: + name: 'apex-verify-unit-tests-{stream}' + + node: 'apex-build-{stream}' + + concurrent: true + + disabled: '{obj:disabled}' + + parameters: + - apex-parameter: + gs-pathname: '{gs-pathname}' + - project-parameter: + project: '{project}' + branch: '{branch}' + + scm: + - git-scm-gerrit + + triggers: + - gerrit: + server-name: 'gerrit.opnfv.org' + trigger-on: + - patchset-created-event: + exclude-drafts: 'false' + exclude-trivial-rebase: 'false' + exclude-no-code-change: 'true' + - draft-published-event + - comment-added-contains-event: + comment-contains-value: 'recheck' + - comment-added-contains-event: + comment-contains-value: 'reverify' + projects: + - project-compare-type: 'ANT' + project-pattern: 'apex' + branches: + - branch-compare-type: 'ANT' + branch-pattern: '**/{branch}' + disable-strict-forbidden-file-verification: 'false' + file-paths: + - compare-type: ANT + pattern: 'apex/tests/**' + forbidden-file-paths: + - compare-type: ANT + pattern: '*' + - compare-type: ANT + pattern: 'apex/*' + - compare-type: ANT + pattern: 'build/**' + - compare-type: ANT + pattern: 'lib/**' + - compare-type: ANT + pattern: 'config/**' + - compare-type: ANT + pattern: 'apex/build/**' + - compare-type: ANT + pattern: 'apex/common/**' + - compare-type: ANT + pattern: 'apex/inventory/**' + - compare-type: ANT + pattern: 'apex/network/**' + - compare-type: ANT + pattern: 'apex/overcloud/**' + - compare-type: ANT + pattern: 'apex/settings/**' + - compare-type: ANT + pattern: 'apex/undercloud/**' + - compare-type: ANT + pattern: 'apex/virtual/**' + + properties: + - logrotate-default + - throttle: + max-per-node: 1 + max-total: 10 + option: 'project' + + builders: + - apex-unit-test + +# Verify +- job-template: + name: 'apex-verify-{stream}' + + node: 'apex-virtual-master' + + concurrent: true + + disabled: '{obj:disabled}' + + project-type: 'multijob' + + parameters: + - apex-parameter: + gs-pathname: '{gs-pathname}/dev' + - project-parameter: + project: '{project}' + branch: '{branch}' + - string: + name: ARTIFACT_VERSION + default: dev + description: "Used for overriding the ARTIFACT_VERSION" + scm: + - git-scm-gerrit + + triggers: + - gerrit: + server-name: 'gerrit.opnfv.org' + trigger-on: + - patchset-created-event: + exclude-drafts: 'false' + exclude-trivial-rebase: 'false' + exclude-no-code-change: 'true' + - draft-published-event + - comment-added-contains-event: + comment-contains-value: 'recheck' + - comment-added-contains-event: + comment-contains-value: 'reverify' + projects: + - project-compare-type: 'ANT' + project-pattern: 'apex' + branches: + - branch-compare-type: 'ANT' + branch-pattern: '**/{branch}' + disable-strict-forbidden-file-verification: 'true' + file-paths: + - compare-type: ANT + pattern: '*' + - compare-type: ANT + pattern: 'apex/*' + - compare-type: ANT + pattern: 'build/**' + - compare-type: ANT + pattern: 'lib/**' + - compare-type: ANT + pattern: 'config/**' + - compare-type: ANT + pattern: 'apex/build/**' + - compare-type: ANT + pattern: 'apex/common/**' + - compare-type: ANT + pattern: 'apex/inventory/**' + - compare-type: ANT + pattern: 'apex/network/**' + - compare-type: ANT + pattern: 'apex/overcloud/**' + - compare-type: ANT + pattern: 'apex/settings/**' + - compare-type: ANT + pattern: 'apex/undercloud/**' + - compare-type: ANT + pattern: 'apex/virtual/**' + forbidden-file-paths: + - compare-type: ANT + pattern: 'apex/tests/**' + - compare-type: ANT + pattern: 'docs/**' + + properties: + - logrotate-default + - throttle: + max-per-node: 3 + max-total: 10 + option: 'project' + + builders: + - description-setter: + description: "Built on $NODE_NAME" + - multijob: + name: basic + condition: SUCCESSFUL + projects: + - name: 'apex-verify-unit-tests-{stream}' + current-parameters: false + predefined-parameters: | + GERRIT_BRANCH=$GERRIT_BRANCH + GERRIT_REFSPEC=$GERRIT_REFSPEC + GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER + GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE + node-parameters: false + kill-phase-on: FAILURE + abort-all-job: true + git-revision: true + - multijob: + name: build + condition: SUCCESSFUL + projects: + - name: 'apex-build-{stream}' + current-parameters: false + predefined-parameters: | + ARTIFACT_VERSION=$ARTIFACT_VERSION + GERRIT_BRANCH=$GERRIT_BRANCH + GERRIT_REFSPEC=$GERRIT_REFSPEC + GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER + GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE + node-parameters: false + kill-phase-on: FAILURE + abort-all-job: true + git-revision: true + - multijob: + name: deploy-virtual + condition: SUCCESSFUL + projects: + - name: 'apex-virtual-{stream}' + current-parameters: false + predefined-parameters: | + ARTIFACT_VERSION=$ARTIFACT_VERSION + DEPLOY_SCENARIO={verify-scenario} + OPNFV_CLEAN=yes + GERRIT_BRANCH=$GERRIT_BRANCH + GERRIT_REFSPEC=$GERRIT_REFSPEC + GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER + GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE + node-parameters: false + kill-phase-on: FAILURE + abort-all-job: true + git-revision: true + +# Verify Scenario Gate +- job-template: + name: 'apex-verify-gate-{stream}' + + node: 'apex-build-{stream}' + + concurrent: true + + disabled: '{obj:disabled}' + + project-type: 'multijob' + + parameters: + - apex-parameter: + gs-pathname: '{gs-pathname}/dev' + - project-parameter: + project: '{project}' + branch: '{branch}' + - string: + name: GIT_BASE + default: https://gerrit.opnfv.org/gerrit/$PROJECT + description: "Used for overriding the GIT URL coming from parameters macro." + - string: + name: ARTIFACT_VERSION + default: dev + description: "Used for overriding the ARTIFACT_VERSION" + + scm: + - git-scm-gerrit + + triggers: + - gerrit: + server-name: 'gerrit.opnfv.org' + trigger-on: + - comment-added-contains-event: + comment-contains-value: '^Patch Set [0-9]+: Code-Review\+2.*start-gate-scenario:.*' + projects: + - project-compare-type: 'ANT' + project-pattern: 'apex' + branches: + - branch-compare-type: 'ANT' + branch-pattern: '**/{branch}' + file-paths: + - compare-type: ANT + pattern: 'ci/**' + - compare-type: ANT + pattern: 'build/**' + - compare-type: ANT + pattern: 'lib/**' + - compare-type: ANT + pattern: 'config/**' + - compare-type: ANT + pattern: 'apex/**' + + properties: + - logrotate-default + - build-blocker: + use-build-blocker: true + block-level: 'NODE' + blocking-jobs: + - 'apex-verify.*' + - 'apex-virtual.*' + - throttle: + max-per-node: 1 + max-total: 10 + option: 'project' + + builders: + - multijob: + name: deploy-virtual + condition: SUCCESSFUL + projects: + - name: 'apex-deploy-virtual-{stream}' + current-parameters: false + predefined-parameters: | + ARTIFACT_VERSION=$ARTIFACT_VERSION + DEPLOY_SCENARIO=gate + OPNFV_CLEAN=yes + GERRIT_BRANCH=$GERRIT_BRANCH + GERRIT_REFSPEC=$GERRIT_REFSPEC + GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER + GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE + GERRIT_EVENT_COMMENT_TEXT=$GERRIT_EVENT_COMMENT_TEXT + node-parameters: true + kill-phase-on: FAILURE + abort-all-job: true + git-revision: true + # yamllint disable rule:line-length + - shell: | + echo DEPLOY_SCENARIO=$(echo $GERRIT_EVENT_COMMENT_TEXT | grep start-gate-scenario | grep -Eo 'os-.*') > detected_scenario + # yamllint enable rule:line-length + - inject: + properties-file: detected_scenario + - multijob: + name: functest-smoke + condition: SUCCESSFUL + projects: + - name: 'functest-apex-virtual-suite-{stream}' + current-parameters: false + predefined-parameters: | + DEPLOY_SCENARIO=$DEPLOY_SCENARIO + FUNCTEST_MODE=tier + FUNCTEST_TIER=healthcheck + GERRIT_BRANCH=$GERRIT_BRANCH + GERRIT_REFSPEC=$GERRIT_REFSPEC + GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER + GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE + node-parameters: true + kill-phase-on: NEVER + abort-all-job: true + git-revision: false + +######################## +# builder macros +######################## +- builder: + name: apex-unit-test + builders: + - shell: + !include-raw: ./apex-unit-test.sh diff --git a/jjb/apex/apex.yml b/jjb/apex/apex.yml index 4ec6efbd4..43e234ce1 100644 --- a/jjb/apex/apex.yml +++ b/jjb/apex/apex.yml @@ -3,9 +3,6 @@ name: 'apex' project: 'apex' jobs: - - 'apex-verify-{stream}' - - 'apex-verify-gate-{stream}' - - 'apex-verify-unit-tests-{stream}' - 'apex-runner-cperf-{stream}' - 'apex-virtual-{stream}' - 'apex-deploy-{platform}-{stream}' @@ -29,7 +26,7 @@ baremetal-slave: 'apex-baremetal-master' verify-scenario: 'os-odl-nofeature-ha' scenario_stream: 'master' - disable_daily: true + disable_daily: false - euphrates: &euphrates branch: 'stable/euphrates' gs-pathname: '/euphrates' @@ -161,10 +158,6 @@ <<: *euphrates - 'os-nosdn-fdio-ha': <<: *euphrates - - 'os-odl-fdio-noha': - <<: *euphrates - - 'os-odl-fdio-ha': - <<: *euphrates - 'os-nosdn-bar-ha': <<: *euphrates - 'os-nosdn-bar-noha': @@ -183,10 +176,6 @@ <<: *euphrates - 'os-odl-sfc-ha': <<: *euphrates - - 'os-odl-fdio_dvr-noha': - <<: *euphrates - - 'os-odl-fdio_dvr-ha': - <<: *euphrates - 'os-nosdn-calipso-noha': <<: *euphrates @@ -194,332 +183,6 @@ - 'baremetal' - 'virtual' -# Unit Test -- job-template: - name: 'apex-verify-unit-tests-{stream}' - - node: '{build-slave}' - - concurrent: true - - parameters: - - apex-parameter: - gs-pathname: '{gs-pathname}' - - project-parameter: - project: '{project}' - branch: '{branch}' - - scm: - - git-scm-gerrit - - triggers: - - gerrit: - server-name: 'gerrit.opnfv.org' - trigger-on: - - patchset-created-event: - exclude-drafts: 'false' - exclude-trivial-rebase: 'false' - exclude-no-code-change: 'true' - - draft-published-event - - comment-added-contains-event: - comment-contains-value: 'recheck' - - comment-added-contains-event: - comment-contains-value: 'reverify' - projects: - - project-compare-type: 'ANT' - project-pattern: 'apex' - branches: - - branch-compare-type: 'ANT' - branch-pattern: '**/{branch}' - disable-strict-forbidden-file-verification: 'false' - file-paths: - - compare-type: ANT - pattern: 'apex/tests/**' - forbidden-file-paths: - - compare-type: ANT - pattern: '*' - - compare-type: ANT - pattern: 'apex/*' - - compare-type: ANT - pattern: 'build/**' - - compare-type: ANT - pattern: 'lib/**' - - compare-type: ANT - pattern: 'config/**' - - compare-type: ANT - pattern: 'apex/build/**' - - compare-type: ANT - pattern: 'apex/common/**' - - compare-type: ANT - pattern: 'apex/inventory/**' - - compare-type: ANT - pattern: 'apex/network/**' - - compare-type: ANT - pattern: 'apex/overcloud/**' - - compare-type: ANT - pattern: 'apex/settings/**' - - compare-type: ANT - pattern: 'apex/undercloud/**' - - compare-type: ANT - pattern: 'apex/virtual/**' - - properties: - - logrotate-default - - throttle: - max-per-node: 1 - max-total: 10 - option: 'project' - - builders: - - shell: - !include-raw-escape: ./apex-unit-test.sh - -# Verify -- job-template: - name: 'apex-verify-{stream}' - - node: '{virtual-slave}' - - concurrent: true - - project-type: 'multijob' - - parameters: - - apex-parameter: - gs-pathname: '{gs-pathname}/dev' - - project-parameter: - project: '{project}' - branch: '{branch}' - - string: - name: ARTIFACT_VERSION - default: dev - description: "Used for overriding the ARTIFACT_VERSION" - scm: - - git-scm-gerrit - - triggers: - - gerrit: - server-name: 'gerrit.opnfv.org' - trigger-on: - - patchset-created-event: - exclude-drafts: 'false' - exclude-trivial-rebase: 'false' - exclude-no-code-change: 'true' - - draft-published-event - - comment-added-contains-event: - comment-contains-value: 'recheck' - - comment-added-contains-event: - comment-contains-value: 'reverify' - projects: - - project-compare-type: 'ANT' - project-pattern: 'apex' - branches: - - branch-compare-type: 'ANT' - branch-pattern: '**/{branch}' - disable-strict-forbidden-file-verification: 'true' - file-paths: - - compare-type: ANT - pattern: '*' - - compare-type: ANT - pattern: 'apex/*' - - compare-type: ANT - pattern: 'build/**' - - compare-type: ANT - pattern: 'lib/**' - - compare-type: ANT - pattern: 'config/**' - - compare-type: ANT - pattern: 'apex/build/**' - - compare-type: ANT - pattern: 'apex/common/**' - - compare-type: ANT - pattern: 'apex/inventory/**' - - compare-type: ANT - pattern: 'apex/network/**' - - compare-type: ANT - pattern: 'apex/overcloud/**' - - compare-type: ANT - pattern: 'apex/settings/**' - - compare-type: ANT - pattern: 'apex/undercloud/**' - - compare-type: ANT - pattern: 'apex/virtual/**' - forbidden-file-paths: - - compare-type: ANT - pattern: 'apex/tests/**' - - compare-type: ANT - pattern: 'docs/**' - - properties: - - logrotate-default - - throttle: - max-per-node: 3 - max-total: 10 - option: 'project' - - builders: - - description-setter: - description: "Built on $NODE_NAME" - - multijob: - name: basic - condition: SUCCESSFUL - projects: - - name: 'apex-verify-unit-tests-{stream}' - current-parameters: false - predefined-parameters: | - GERRIT_BRANCH=$GERRIT_BRANCH - GERRIT_REFSPEC=$GERRIT_REFSPEC - GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER - GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE - node-parameters: false - kill-phase-on: FAILURE - abort-all-job: true - git-revision: true - - multijob: - name: build - condition: SUCCESSFUL - projects: - - name: 'apex-build-{stream}' - current-parameters: false - predefined-parameters: | - ARTIFACT_VERSION=$ARTIFACT_VERSION - GERRIT_BRANCH=$GERRIT_BRANCH - GERRIT_REFSPEC=$GERRIT_REFSPEC - GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER - GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE - node-parameters: false - kill-phase-on: FAILURE - abort-all-job: true - git-revision: true - - multijob: - name: deploy-virtual - condition: SUCCESSFUL - projects: - - name: 'apex-virtual-{stream}' - current-parameters: false - predefined-parameters: | - ARTIFACT_VERSION=$ARTIFACT_VERSION - DEPLOY_SCENARIO={verify-scenario} - OPNFV_CLEAN=yes - GERRIT_BRANCH=$GERRIT_BRANCH - GERRIT_REFSPEC=$GERRIT_REFSPEC - GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER - GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE - node-parameters: true - kill-phase-on: FAILURE - abort-all-job: true - git-revision: true - -# Verify Scenario Gate -- job-template: - name: 'apex-verify-gate-{stream}' - - node: '{virtual-slave}' - - concurrent: true - - project-type: 'multijob' - - parameters: - - apex-parameter: - gs-pathname: '{gs-pathname}/dev' - - project-parameter: - project: '{project}' - branch: '{branch}' - - string: - name: GIT_BASE - default: https://gerrit.opnfv.org/gerrit/$PROJECT - description: "Used for overriding the GIT URL coming from parameters macro." - - string: - name: ARTIFACT_VERSION - default: dev - description: "Used for overriding the ARTIFACT_VERSION" - - scm: - - git-scm-gerrit - - triggers: - - gerrit: - server-name: 'gerrit.opnfv.org' - trigger-on: - - comment-added-contains-event: - comment-contains-value: '^Patch Set [0-9]+: Code-Review\+2.*start-gate-scenario:.*' - projects: - - project-compare-type: 'ANT' - project-pattern: 'apex' - branches: - - branch-compare-type: 'ANT' - branch-pattern: '**/{branch}' - file-paths: - - compare-type: ANT - pattern: 'ci/**' - - compare-type: ANT - pattern: 'build/**' - - compare-type: ANT - pattern: 'lib/**' - - compare-type: ANT - pattern: 'config/**' - - compare-type: ANT - pattern: 'apex/**' - - properties: - - logrotate-default - - build-blocker: - use-build-blocker: true - block-level: 'NODE' - blocking-jobs: - - 'apex-verify.*' - - 'apex-virtual.*' - - throttle: - max-per-node: 1 - max-total: 10 - option: 'project' - - builders: - - multijob: - name: deploy-virtual - condition: SUCCESSFUL - projects: - - name: 'apex-deploy-virtual-{stream}' - current-parameters: false - predefined-parameters: | - ARTIFACT_VERSION=$ARTIFACT_VERSION - DEPLOY_SCENARIO=gate - OPNFV_CLEAN=yes - GERRIT_BRANCH=$GERRIT_BRANCH - GERRIT_REFSPEC=$GERRIT_REFSPEC - GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER - GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE - GERRIT_EVENT_COMMENT_TEXT=$GERRIT_EVENT_COMMENT_TEXT - node-parameters: true - kill-phase-on: FAILURE - abort-all-job: true - git-revision: true - # yamllint disable rule:line-length - - shell: | - echo DEPLOY_SCENARIO=$(echo $GERRIT_EVENT_COMMENT_TEXT | grep start-gate-scenario | grep -Eo 'os-.*') > detected_scenario - # yamllint enable rule:line-length - - inject: - properties-file: detected_scenario - - multijob: - name: functest-smoke - condition: SUCCESSFUL - projects: - - name: 'functest-apex-virtual-suite-{stream}' - current-parameters: false - predefined-parameters: | - DEPLOY_SCENARIO=$DEPLOY_SCENARIO - FUNCTEST_MODE=tier - FUNCTEST_TIER=healthcheck - GERRIT_BRANCH=$GERRIT_BRANCH - GERRIT_REFSPEC=$GERRIT_REFSPEC - GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER - GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE - node-parameters: true - kill-phase-on: NEVER - abort-all-job: true - git-revision: false - - job-template: name: 'apex-runner-cperf-{stream}' @@ -650,6 +313,8 @@ - job-template: name: 'apex-virtual-{stream}' + node: 'apex-virtual-master' + project-type: 'multijob' disabled: false @@ -1871,22 +1536,6 @@ kill-phase-on: NEVER abort-all-job: true git-revision: false - - name: 'apex-os-odl-fdio-noha-baremetal-euphrates' - node-parameters: false - current-parameters: false - predefined-parameters: | - OPNFV_CLEAN=yes - kill-phase-on: NEVER - abort-all-job: true - git-revision: false - - name: 'apex-os-odl-fdio-ha-baremetal-euphrates' - node-parameters: false - current-parameters: false - predefined-parameters: | - OPNFV_CLEAN=yes - kill-phase-on: NEVER - abort-all-job: true - git-revision: false - name: 'apex-os-nosdn-bar-ha-baremetal-euphrates' node-parameters: false current-parameters: false @@ -1959,22 +1608,6 @@ kill-phase-on: NEVER abort-all-job: true git-revision: false - - name: 'apex-os-odl-fdio_dvr-noha-baremetal-euphrates' - node-parameters: false - current-parameters: false - predefined-parameters: | - OPNFV_CLEAN=yes - kill-phase-on: NEVER - abort-all-job: true - git-revision: false - - name: 'apex-os-odl-fdio_dvr-ha-baremetal-euphrates' - node-parameters: false - current-parameters: false - predefined-parameters: | - OPNFV_CLEAN=yes - kill-phase-on: NEVER - abort-all-job: true - git-revision: false - name: 'apex-os-nosdn-calipso-noha-baremetal-euphrates' node-parameters: false current-parameters: false @@ -1983,12 +1616,6 @@ kill-phase-on: NEVER abort-all-job: true git-revision: false -- builder: - name: 'apex-unit-test' - builders: - - shell: - !include-raw: ./apex-unit-test.sh - - builder: name: 'apex-upload-artifact' builders: @@ -2013,12 +1640,12 @@ - trigger: name: 'apex-master' triggers: - - timed: '0 3 1 1 7' + - timed: '0 0 1-31/2 * *' - trigger: name: 'apex-euphrates' triggers: - - timed: '0 12 * * *' + - timed: '0 0 2-30/2 * *' - trigger: name: 'apex-danube' diff --git a/jjb/apex/apex.yml.j2 b/jjb/apex/apex.yml.j2 index 31415499c..6cd9de282 100644 --- a/jjb/apex/apex.yml.j2 +++ b/jjb/apex/apex.yml.j2 @@ -3,9 +3,6 @@ name: 'apex' project: 'apex' jobs: - - 'apex-verify-{stream}' - - 'apex-verify-gate-{stream}' - - 'apex-verify-unit-tests-{stream}' - 'apex-runner-cperf-{stream}' - 'apex-virtual-{stream}' - 'apex-deploy-{platform}-{stream}' @@ -29,7 +26,7 @@ baremetal-slave: 'apex-baremetal-master' verify-scenario: 'os-odl-nofeature-ha' scenario_stream: 'master' - disable_daily: true + disable_daily: false - euphrates: &euphrates branch: 'stable/euphrates' gs-pathname: '/euphrates' @@ -62,332 +59,6 @@ - 'baremetal' - 'virtual' -# Unit Test -- job-template: - name: 'apex-verify-unit-tests-{stream}' - - node: '{build-slave}' - - concurrent: true - - parameters: - - apex-parameter: - gs-pathname: '{gs-pathname}' - - project-parameter: - project: '{project}' - branch: '{branch}' - - scm: - - git-scm-gerrit - - triggers: - - gerrit: - server-name: 'gerrit.opnfv.org' - trigger-on: - - patchset-created-event: - exclude-drafts: 'false' - exclude-trivial-rebase: 'false' - exclude-no-code-change: 'true' - - draft-published-event - - comment-added-contains-event: - comment-contains-value: 'recheck' - - comment-added-contains-event: - comment-contains-value: 'reverify' - projects: - - project-compare-type: 'ANT' - project-pattern: 'apex' - branches: - - branch-compare-type: 'ANT' - branch-pattern: '**/{branch}' - disable-strict-forbidden-file-verification: 'false' - file-paths: - - compare-type: ANT - pattern: 'apex/tests/**' - forbidden-file-paths: - - compare-type: ANT - pattern: '*' - - compare-type: ANT - pattern: 'apex/*' - - compare-type: ANT - pattern: 'build/**' - - compare-type: ANT - pattern: 'lib/**' - - compare-type: ANT - pattern: 'config/**' - - compare-type: ANT - pattern: 'apex/build/**' - - compare-type: ANT - pattern: 'apex/common/**' - - compare-type: ANT - pattern: 'apex/inventory/**' - - compare-type: ANT - pattern: 'apex/network/**' - - compare-type: ANT - pattern: 'apex/overcloud/**' - - compare-type: ANT - pattern: 'apex/settings/**' - - compare-type: ANT - pattern: 'apex/undercloud/**' - - compare-type: ANT - pattern: 'apex/virtual/**' - - properties: - - logrotate-default - - throttle: - max-per-node: 1 - max-total: 10 - option: 'project' - - builders: - - shell: - !include-raw-escape: ./apex-unit-test.sh - -# Verify -- job-template: - name: 'apex-verify-{stream}' - - node: '{virtual-slave}' - - concurrent: true - - project-type: 'multijob' - - parameters: - - apex-parameter: - gs-pathname: '{gs-pathname}/dev' - - project-parameter: - project: '{project}' - branch: '{branch}' - - string: - name: ARTIFACT_VERSION - default: dev - description: "Used for overriding the ARTIFACT_VERSION" - scm: - - git-scm-gerrit - - triggers: - - gerrit: - server-name: 'gerrit.opnfv.org' - trigger-on: - - patchset-created-event: - exclude-drafts: 'false' - exclude-trivial-rebase: 'false' - exclude-no-code-change: 'true' - - draft-published-event - - comment-added-contains-event: - comment-contains-value: 'recheck' - - comment-added-contains-event: - comment-contains-value: 'reverify' - projects: - - project-compare-type: 'ANT' - project-pattern: 'apex' - branches: - - branch-compare-type: 'ANT' - branch-pattern: '**/{branch}' - disable-strict-forbidden-file-verification: 'true' - file-paths: - - compare-type: ANT - pattern: '*' - - compare-type: ANT - pattern: 'apex/*' - - compare-type: ANT - pattern: 'build/**' - - compare-type: ANT - pattern: 'lib/**' - - compare-type: ANT - pattern: 'config/**' - - compare-type: ANT - pattern: 'apex/build/**' - - compare-type: ANT - pattern: 'apex/common/**' - - compare-type: ANT - pattern: 'apex/inventory/**' - - compare-type: ANT - pattern: 'apex/network/**' - - compare-type: ANT - pattern: 'apex/overcloud/**' - - compare-type: ANT - pattern: 'apex/settings/**' - - compare-type: ANT - pattern: 'apex/undercloud/**' - - compare-type: ANT - pattern: 'apex/virtual/**' - forbidden-file-paths: - - compare-type: ANT - pattern: 'apex/tests/**' - - compare-type: ANT - pattern: 'docs/**' - - properties: - - logrotate-default - - throttle: - max-per-node: 3 - max-total: 10 - option: 'project' - - builders: - - description-setter: - description: "Built on $NODE_NAME" - - multijob: - name: basic - condition: SUCCESSFUL - projects: - - name: 'apex-verify-unit-tests-{stream}' - current-parameters: false - predefined-parameters: | - GERRIT_BRANCH=$GERRIT_BRANCH - GERRIT_REFSPEC=$GERRIT_REFSPEC - GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER - GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE - node-parameters: false - kill-phase-on: FAILURE - abort-all-job: true - git-revision: true - - multijob: - name: build - condition: SUCCESSFUL - projects: - - name: 'apex-build-{stream}' - current-parameters: false - predefined-parameters: | - ARTIFACT_VERSION=$ARTIFACT_VERSION - GERRIT_BRANCH=$GERRIT_BRANCH - GERRIT_REFSPEC=$GERRIT_REFSPEC - GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER - GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE - node-parameters: false - kill-phase-on: FAILURE - abort-all-job: true - git-revision: true - - multijob: - name: deploy-virtual - condition: SUCCESSFUL - projects: - - name: 'apex-virtual-{stream}' - current-parameters: false - predefined-parameters: | - ARTIFACT_VERSION=$ARTIFACT_VERSION - DEPLOY_SCENARIO={verify-scenario} - OPNFV_CLEAN=yes - GERRIT_BRANCH=$GERRIT_BRANCH - GERRIT_REFSPEC=$GERRIT_REFSPEC - GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER - GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE - node-parameters: true - kill-phase-on: FAILURE - abort-all-job: true - git-revision: true - -# Verify Scenario Gate -- job-template: - name: 'apex-verify-gate-{stream}' - - node: '{virtual-slave}' - - concurrent: true - - project-type: 'multijob' - - parameters: - - apex-parameter: - gs-pathname: '{gs-pathname}/dev' - - project-parameter: - project: '{project}' - branch: '{branch}' - - string: - name: GIT_BASE - default: https://gerrit.opnfv.org/gerrit/$PROJECT - description: "Used for overriding the GIT URL coming from parameters macro." - - string: - name: ARTIFACT_VERSION - default: dev - description: "Used for overriding the ARTIFACT_VERSION" - - scm: - - git-scm-gerrit - - triggers: - - gerrit: - server-name: 'gerrit.opnfv.org' - trigger-on: - - comment-added-contains-event: - comment-contains-value: '^Patch Set [0-9]+: Code-Review\+2.*start-gate-scenario:.*' - projects: - - project-compare-type: 'ANT' - project-pattern: 'apex' - branches: - - branch-compare-type: 'ANT' - branch-pattern: '**/{branch}' - file-paths: - - compare-type: ANT - pattern: 'ci/**' - - compare-type: ANT - pattern: 'build/**' - - compare-type: ANT - pattern: 'lib/**' - - compare-type: ANT - pattern: 'config/**' - - compare-type: ANT - pattern: 'apex/**' - - properties: - - logrotate-default - - build-blocker: - use-build-blocker: true - block-level: 'NODE' - blocking-jobs: - - 'apex-verify.*' - - 'apex-virtual.*' - - throttle: - max-per-node: 1 - max-total: 10 - option: 'project' - - builders: - - multijob: - name: deploy-virtual - condition: SUCCESSFUL - projects: - - name: 'apex-deploy-virtual-{stream}' - current-parameters: false - predefined-parameters: | - ARTIFACT_VERSION=$ARTIFACT_VERSION - DEPLOY_SCENARIO=gate - OPNFV_CLEAN=yes - GERRIT_BRANCH=$GERRIT_BRANCH - GERRIT_REFSPEC=$GERRIT_REFSPEC - GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER - GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE - GERRIT_EVENT_COMMENT_TEXT=$GERRIT_EVENT_COMMENT_TEXT - node-parameters: true - kill-phase-on: FAILURE - abort-all-job: true - git-revision: true - # yamllint disable rule:line-length - - shell: | - echo DEPLOY_SCENARIO=$(echo $GERRIT_EVENT_COMMENT_TEXT | grep start-gate-scenario | grep -Eo 'os-.*') > detected_scenario - # yamllint enable rule:line-length - - inject: - properties-file: detected_scenario - - multijob: - name: functest-smoke - condition: SUCCESSFUL - projects: - - name: 'functest-apex-virtual-suite-{stream}' - current-parameters: false - predefined-parameters: | - DEPLOY_SCENARIO=$DEPLOY_SCENARIO - FUNCTEST_MODE=tier - FUNCTEST_TIER=healthcheck - GERRIT_BRANCH=$GERRIT_BRANCH - GERRIT_REFSPEC=$GERRIT_REFSPEC - GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER - GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE - node-parameters: true - kill-phase-on: NEVER - abort-all-job: true - git-revision: false - - job-template: name: 'apex-runner-cperf-{stream}' @@ -518,6 +189,8 @@ - job-template: name: 'apex-virtual-{stream}' + node: 'apex-virtual-master' + project-type: 'multijob' disabled: false @@ -1293,12 +966,6 @@ {%- endfor %} {% endfor -%} -- builder: - name: 'apex-unit-test' - builders: - - shell: - !include-raw: ./apex-unit-test.sh - - builder: name: 'apex-upload-artifact' builders: @@ -1323,12 +990,12 @@ - trigger: name: 'apex-master' triggers: - - timed: '0 3 1 1 7' + - timed: '0 0 1-31/2 * *' - trigger: name: 'apex-euphrates' triggers: - - timed: '0 12 * * *' + - timed: '0 0 2-30/2 * *' - trigger: name: 'apex-danube' diff --git a/jjb/apex/scenarios.yaml.hidden b/jjb/apex/scenarios.yaml.hidden index 3b6b48502..98b698dd8 100644 --- a/jjb/apex/scenarios.yaml.hidden +++ b/jjb/apex/scenarios.yaml.hidden @@ -29,8 +29,6 @@ euphrates: - 'os-ovn-nofeature-noha' - 'os-nosdn-fdio-noha' - 'os-nosdn-fdio-ha' - - 'os-odl-fdio-noha' - - 'os-odl-fdio-ha' - 'os-nosdn-bar-ha' - 'os-nosdn-bar-noha' - 'os-nosdn-nofeature-ha-ipv6' @@ -40,8 +38,6 @@ euphrates: - 'os-nosdn-kvm_ovs_dpdk-ha' - 'os-odl-sfc-noha' - 'os-odl-sfc-ha' - - 'os-odl-fdio_dvr-noha' - - 'os-odl-fdio_dvr-ha' - 'os-nosdn-calipso-noha' danube: - 'os-nosdn-nofeature-noha' diff --git a/jjb/barometer/barometer-build.sh b/jjb/barometer/barometer-build.sh index e40841bc2..5f78aae7a 100644 --- a/jjb/barometer/barometer-build.sh +++ b/jjb/barometer/barometer-build.sh @@ -11,6 +11,7 @@ echo cd ci ./install_dependencies.sh ./build_rpm.sh +cp utility/rpms_list $WORKSPACE cd $WORKSPACE # save information regarding artifact into file diff --git a/jjb/barometer/barometer-upload-artifact.sh b/jjb/barometer/barometer-upload-artifact.sh index 0f639b5d9..f05dc2af8 100644 --- a/jjb/barometer/barometer-upload-artifact.sh +++ b/jjb/barometer/barometer-upload-artifact.sh @@ -2,7 +2,7 @@ set -o nounset set -o pipefail -RPM_LIST=$WORKSPACE/ci/utilities/rpms_list +RPM_LIST=$WORKSPACE/rpms_list RPM_WORKDIR=$WORKSPACE/rpmbuild RPM_DIR=$RPM_WORKDIR/RPMS/x86_64/ cd $WORKSPACE/ diff --git a/jjb/ci_gate_security/anteater-clone-all-repos.sh b/jjb/ci_gate_security/anteater-clone-all-repos.sh deleted file mode 100755 index 8a9e73d85..000000000 --- a/jjb/ci_gate_security/anteater-clone-all-repos.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -# SPDX-license-identifier: Apache-2.0 -set -o errexit -set -o pipefail -set -o nounset -export PATH=$PATH:/usr/local/bin/ - - -#WORKSPACE="$(pwd)" - -cd $WORKSPACE -if [ ! -d "$WORKSPACE/allrepos" ]; then - mkdir $WORKSPACE/allrepos -fi - -cd $WORKSPACE/allrepos - -declare -a PROJECT_LIST -EXCLUDE_PROJECTS="All-Projects|All-Users|securedlab" - -PROJECT_LIST=($(ssh gerrit.opnfv.org -p 29418 gerrit ls-projects | egrep -v $EXCLUDE_PROJECTS)) -echo "PROJECT_LIST=(${PROJECT_LIST[*]})" > $WORKSPACE/opnfv-projects.sh - -for PROJECT in ${PROJECT_LIST[@]}; do - echo "> Cloning $PROJECT" - if [ ! -d "$PROJECT" ]; then - git clone "https://gerrit.opnfv.org/gerrit/$PROJECT.git" - else - pushd "$PROJECT" > /dev/null - git pull -f - popd > /dev/null - fi -done diff --git a/jjb/ci_gate_security/anteater-security-audit-weekly.sh b/jjb/ci_gate_security/anteater-security-audit-weekly.sh index 11909636a..6caa13117 100644 --- a/jjb/ci_gate_security/anteater-security-audit-weekly.sh +++ b/jjb/ci_gate_security/anteater-security-audit-weekly.sh @@ -1,37 +1,50 @@ #!/bin/bash # SPDX-license-identifier: Apache-2.0 +############################################################################## +# Copyright (c) 2017 The Linux Foundation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +ANTEATER_SCAN_PATCHSET="${ANTEATER_SCAN_PATCHSET:-true}" + +cd $WORKSPACE +REPORTDIR='.reports' +mkdir -p $REPORTDIR +# Ensure any user can read the reports directory +chmod 777 $REPORTDIR + +ANTEATER_FILES="--patchset /home/opnfv/anteater/$PROJECT/patchset" + +if [[ "$ANTEATER_SCAN_PATCHSET" == "true" ]]; then + echo "Generating patchset file to list changed files" + git diff HEAD^1 --name-only | sed "s#^#/home/opnfv/anteater/$PROJECT/#" > $WORKSPACE/patchset + echo "Changed files are" + echo "--------------------------------------------------------" + cat $WORKSPACE/patchset + echo "--------------------------------------------------------" +else + echo "Checking full project $PROJECT" + ANTEATER_FILES="--path /home/opnfv/anteater/$PROJECT" +fi + +vols="-v $WORKSPACE:/home/opnfv/anteater/$PROJECT -v $WORKSPACE/$REPORTDIR:/home/opnfv/anteater/$REPORTDIR" +envs="-e PROJECT=$PROJECT" -echo "--------------------------------------------------------" -vols="-v $WORKSPACE/allrepos/:/home/opnfv/anteater/allrepos/" echo "Pulling releng-anteater docker image" echo "--------------------------------------------------------" docker pull opnfv/releng-anteater echo "--------------------------------------------------------" -cmd="docker run -id $vols opnfv/releng-anteater /bin/bash" -echo "Running docker command $cmd" -container_id=$($cmd) -echo "Container ID is $container_id" -source $WORKSPACE/opnfv-projects.sh -for project in "${PROJECT_LIST[@]}" - -do - cmd="/home/opnfv/venv/bin/anteater --project testproj --path /home/opnfv/anteater/allrepos/$project" - echo "Executing command inside container" - echo "$cmd" - echo "--------------------------------------------------------" - docker exec $container_id $cmd > $WORKSPACE/"$project".securityaudit.log 2>&1 -done +cmd="docker run -i $envs $vols --rm opnfv/releng-anteater \ +/home/opnfv/venv/bin/anteater --project $PROJECT $ANTEATER_FILES" +echo "Running docker container" +echo "$cmd" +$cmd > $WORKSPACE/securityaudit.log 2>&1 exit_code=$? echo "--------------------------------------------------------" -echo "Stopping docker container with ID $container_id" -docker stop $container_id - - -#gsutil cp $WORKSPACE/securityaudit.log \ -# gs://$GS_URL/$PROJECT-securityaudit-weekly.log 2>&1 -# -#gsutil -m setmeta \ -# -h "Content-Type:text/html" \ -# -h "Cache-Control:private, max-age=0, no-transform" \ -# gs://$GS_URL/$PROJECT-securityaudit-weekly.log > /dev/null 2>&1 +echo "Docker container exited with code: $exit_code" +echo "--------------------------------------------------------" +exit 0 diff --git a/jjb/ci_gate_security/opnfv-ci-gate-security.yml b/jjb/ci_gate_security/opnfv-ci-gate-security.yml index e09339a4b..ef0da7f3a 100644 --- a/jjb/ci_gate_security/opnfv-ci-gate-security.yml +++ b/jjb/ci_gate_security/opnfv-ci-gate-security.yml @@ -9,9 +9,76 @@ project: anteaterfw + repo: + - apex + - apex-os-net-config + - apex-puppet-tripleo + - apex-tripleo-heat-templates + - armband + - auto + - availability + - bamboo + - barometer + - bottlenecks + - calipso + - clover + - compass-containers + - compass4nfv + - conductor + - container4nfv + - copper + - cperf + - daisy + - doctor + - domino + - dovetail + - dpacc + - enfv + - fastpathmetrics + - fds + - fuel + - functest + - ipv6 + - joid + - kvmfornfv + - models + - moon + - multisite + - netready + - nfvbench + - octopus + - onosfw + - openretriever + - opera + - opnfvdocs + - orchestra + - ovn4nfv + - ovno + - ovsnfv + - parser + - pharos + - pharos-tools + - promise + - qtip + - releng + - releng-anteater + - releng-testresults + - releng-utils + - releng-xci + - samplevnf + - sdnvpn + - securityscanning + - sfc + - snaps + - stor4nfv + - storperf + - ves + - vswitchperf + - yardstick + jobs: - 'opnfv-security-audit-verify-{stream}' - - 'opnfv-security-audit-weekly-{stream}' + - 'opnfv-security-audit-{repo}-weekly-{stream}' stream: - master: @@ -23,18 +90,26 @@ # job templates ######################## - job-template: - name: 'opnfv-security-audit-weekly-{stream}' + name: 'opnfv-security-audit-{repo}-weekly-{stream}' disabled: '{obj:disabled}' parameters: - - label: - name: SLAVE_LABEL - default: 'ericsson-build3' - description: 'Slave label on Jenkins' + - ericsson-build3-defaults + - string: + name: ANTEATER_SCAN_PATCHSET + default: "false" + description: "Have anteater scan patchsets (true) or full project (false)" - project-parameter: - project: releng + project: '{repo}' branch: '{branch}' + - string: + name: GERRIT_REFSPEC + default: 'refs/heads/{stream}' + description: "Default Gerrit ref git HEAD should point to" + + scm: + - git-scm-gerrit triggers: - timed: '@weekly' @@ -42,6 +117,13 @@ builders: - anteater-security-audit-weekly + publishers: + # defined in jjb/global/releng-macros.yml + - 'email-{repo}-ptl': + subject: 'OPNFV Security Scan Result: {repo}' + - workspace-cleanup: + fail-build: false + - job-template: name: 'opnfv-security-audit-verify-{stream}' @@ -81,7 +163,7 @@ comment-contains-value: 'reverify' projects: - project-compare-type: 'REG_EXP' - project-pattern: 'apex|armband|bamboo|barometer|bottlenecks|calipso|compass4nfv|conductor|cooper|cperf|daisy|doctor|dovetail|dpacc|enfv|escalator|fds|fuel|functest|octopus|pharos|releng|sandbox|yardstick' + project-pattern: 'apex|armband|bamboo|barometer|bottlenecks|calipso|compass4nfv|conductor|cooper|cperf|daisy|doctor|dovetail|dpacc|enfv|escalator|fds|fuel|functest|octopus|pharos|releng|sandbox|yardstick|infra|ipv6|kvmfornfv|lsoapi|models|moon|multisite|netready' branches: - branch-compare-type: 'ANT' branch-pattern: '**/{branch}' @@ -117,12 +199,8 @@ - shell: !include-raw: ./anteater-report-to-gerrit.sh -# yamllint disable rule:indentation - builder: name: anteater-security-audit-weekly builders: - shell: - !include-raw: - - ./anteater-clone-all-repos.sh - - ./anteater-security-audit-weekly.sh -# yamllint enable rule:indentation + !include-raw: ./anteater-security-audit-weekly.sh diff --git a/jjb/compass4nfv/compass-ci-jobs.yml b/jjb/compass4nfv/compass-ci-jobs.yml index 4adfc2a3f..446d0717a 100644 --- a/jjb/compass4nfv/compass-ci-jobs.yml +++ b/jjb/compass4nfv/compass-ci-jobs.yml @@ -13,7 +13,7 @@ gs-pathname: '' ppa-pathname: '/{stream}' disabled: false - openstack-version: ocata + openstack-version: pike euphrates: &euphrates stream: euphrates branch: 'stable/{stream}' diff --git a/jjb/container4nfv/container4nfv-project.yml b/jjb/container4nfv/container4nfv-project.yml index ffdbf9551..58070e1c5 100644 --- a/jjb/container4nfv/container4nfv-project.yml +++ b/jjb/container4nfv/container4nfv-project.yml @@ -31,6 +31,12 @@ - project-parameter: project: '{project}' branch: '{branch}' + # yamllint disable rule:line-length + - string: + name: GIT_BASE + default: https://gerrit.opnfv.org/gerrit/$PROJECT + description: "Used for overriding the GIT URL coming from Global Jenkins configuration in case if the stuff is done on none-LF HW." + # yamllint enable rule:line-length - 'opnfv-build-ubuntu-defaults' scm: @@ -78,10 +84,19 @@ properties: - logrotate-default + wrappers: + - fix-workspace-permissions + parameters: - project-parameter: project: '{project}' branch: '{branch}' + # yamllint disable rule:line-length + - string: + name: GIT_BASE + default: https://gerrit.opnfv.org/gerrit/$PROJECT + description: "Used for overriding the GIT URL coming from Global Jenkins configuration in case if the stuff is done on none-LF HW." + # yamllint enable rule:line-length - node: name: SLAVE_NAME description: 'Slave name on Jenkins' @@ -97,6 +112,6 @@ - timed: '@midnight' builders: - - shell: + - shell: | cd $WORKSPACE/ci ./deploy.sh diff --git a/jjb/daisy4nfv/daisy-daily-jobs.yml b/jjb/daisy4nfv/daisy-daily-jobs.yml index f2626db1c..090d2e1f2 100644 --- a/jjb/daisy4nfv/daisy-daily-jobs.yml +++ b/jjb/daisy4nfv/daisy-daily-jobs.yml @@ -93,7 +93,9 @@ - build-blocker: use-build-blocker: true blocking-jobs: + - 'daisy-os-.*?-{pod}-daily-.*?' - 'daisy-daily-.*' + - 'daisy-kolla-build-.*' block-level: 'NODE' wrappers: @@ -177,6 +179,7 @@ use-build-blocker: true blocking-jobs: - 'daisy.*-deploy-({pod})?-daily-.*' + - 'daisy-kolla-build-.*' block-level: 'NODE' parameters: diff --git a/jjb/daisy4nfv/daisy-project-jobs.yml b/jjb/daisy4nfv/daisy-project-jobs.yml index b6e9526e3..006153f6f 100644 --- a/jjb/daisy4nfv/daisy-project-jobs.yml +++ b/jjb/daisy4nfv/daisy-project-jobs.yml @@ -37,6 +37,72 @@ jobs: - '{installer}-daily-{stream}' - '{installer}-{phase}-daily-{stream}' + - '{installer}-kolla-build-{stream}' + +############################# +# docker build job templates +############################# +- job-template: + name: '{installer}-kolla-build-{stream}' + disabled: false + concurrent: true + + properties: + - logrotate-default + - throttle: + enabled: true + max-total: 4 + option: 'project' + - build-blocker: + use-build-blocker: true + # Note: Need to block all jobs which may create daisy VM. + blocking-jobs: + - '{installer}-kolla-build-.*' + - 'daisy-deploy-.*' + - 'daisy-daily-.*' + block-level: 'NODE' + + scm: + - git-scm + + triggers: + - 'daisy-kolla-build-{stream}-trigger' + + parameters: + - project-parameter: + project: '{project}' + branch: '{branch}' + - 'daisy-virtual-defaults' + - '{installer}-defaults' + - '{installer}-project-parameter': + gs-pathname: '{gs-pathname}' + + wrappers: + - ssh-agent-wrapper + - timeout: + timeout: 720 + fail: true + + builders: + - description-setter: + description: "Built on $NODE_NAME" + - shell: + !include-raw-escape: ./daisy4nfv-build-kolla-image.sh + + publishers: + - '{installer}-recipients' + - email-jenkins-admins-on-failure + +- trigger: + name: 'daisy-kolla-build-euphrates-trigger' + triggers: + - timed: '0 0 * * 0' + +- trigger: + name: 'daisy-kolla-build-master-trigger' + triggers: + - timed: '0 12 * * 0' + ######################## # job templates @@ -60,6 +126,7 @@ use-build-blocker: true blocking-jobs: - '{installer}-daily-.*' + - '{installer}-kolla-build-.*' - 'daisy4nfv-merge-build-.*' - 'daisy4nfv-verify-build-.*' block-level: 'NODE' diff --git a/jjb/daisy4nfv/daisy4nfv-build-kolla-image.sh b/jjb/daisy4nfv/daisy4nfv-build-kolla-image.sh new file mode 100755 index 000000000..9a1e2fc20 --- /dev/null +++ b/jjb/daisy4nfv/daisy4nfv-build-kolla-image.sh @@ -0,0 +1,94 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2016 ZTE Coreporation and others. +# hu.zhijiang@zte.com.cn +# sun.jing22@zte.com.cn +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + +set -o errexit +set -o nounset +set -o pipefail + +importkey () { + # clone releng repository + echo "Cloning releng repository..." + [ -d releng ] && rm -rf releng + git clone https://gerrit.opnfv.org/gerrit/releng ./releng/ &> /dev/null + #this is where we import the siging key + if [ -f ./releng/utils/gpg_import_key.sh ]; then + source ./releng/utils/gpg_import_key.sh + fi +} + +upload_image_to_opnfv () { + image=$1 + + importkey + if gpg2 --list-keys | grep "opnfv-helpdesk@rt.linuxfoundation.org"; then + echo "Signing Key avaliable" + SIGN_ARTIFACT="true" + fi + + if [[ -n "$SIGN_ARTIFACT" && "$SIGN_ARTIFACT" == "true" ]]; then + gpg2 -vvv --batch --yes --no-tty \ + --default-key opnfv-helpdesk@rt.linuxfoundation.org \ + --passphrase besteffort \ + --detach-sig $image + gsutil cp $image.sig gs://$GS_URL/upstream/$image.sig + echo "Image signature upload complete!" + fi + + sha512sum -b $image > $image.sha512sum + gsutil cp $image.sha512sum gs://$GS_URL/upstream/$image.sha512sum + + echo "Uploading $INSTALLER_TYPE artifact. This could take some time..." + echo + gsutil cp $image gs://$GS_URL/upstream/$image + gsutil -m setmeta \ + -h "Cache-Control:private, max-age=0, no-transform" \ + gs://$GS_URL/upstream/$image + + # check if we uploaded the file successfully to see if things are fine + gsutil ls gs://$GS_URL/upstream/$image + if [[ $? -ne 0 ]]; then + echo "Problem while uploading artifact!" + exit 1 + fi +} + + + +echo "--------------------------------------------------------" +echo "This is diasy4nfv kolla image build job!" +echo "--------------------------------------------------------" + +# start the build +cd $WORKSPACE +rm -rf docker_build_dir +mkdir -p docker_build_dir + +# -j is for deciding which branch will be used when building, +# only for OPNFV +sudo -E ./ci/kolla-build.sh -j $JOB_NAME -w $WORKSPACE/docker_build_dir + +if [ $? -ne 0 ]; then + echo + echo "Kolla build failed!" + deploy_ret=1 +else + echo + echo "--------------------------------------------------------" + echo "Kolla build done!" +fi + +image=$(ls $WORKSPACE/docker_build_dir/kolla-build-output/kolla-image-*.tgz) +upload_image_to_opnfv $image + +echo +echo "--------------------------------------------------------" +echo "All done!" diff --git a/jjb/doctor/doctor.yml b/jjb/doctor/doctor.yml index 6a04c5fbc..e0de9aa2e 100644 --- a/jjb/doctor/doctor.yml +++ b/jjb/doctor/doctor.yml @@ -25,6 +25,12 @@ # slave-label: 'ool-virtual3' # pod: 'ool-virtual3' + phase: + - 'build-x86_64': + slave-label: 'doctor-{installer}-verify' + - 'build-aarch64': + slave-label: 'doctor-{installer}-{phase}-verify' + inspector: - 'sample' - 'congress' @@ -37,22 +43,23 @@ auto-trigger-name: 'doctor-verify' is-python: true - pod: - - armband-baremetal: - slave-label: '{pod}' - - armband-virtual: - slave-label: '{pod}' + exclude: + - installer: 'apex' + phase: 'build-aarch64' jobs: - 'doctor-verify-{stream}' - - 'doctor-{task}-{installer}-{inspector}-{pod}-{stream}' - - 'doctor-{task}-{installer}-{inspector}-{stream}' + - 'doctor-verify-unit-test-{stream}' + - 'doctor-{task}-{inspector}-{stream}' + - 'doctor-{task}-{installer}-{inspector}-{phase}-{stream}' - job-template: name: 'doctor-verify-{stream}' disabled: '{obj:disabled}' + project-type: 'multijob' + parameters: - project-parameter: project: '{project}' @@ -86,50 +93,63 @@ pattern: 'doctor_tests/**' builders: - - shell: "[ -e tests/run.sh ] && bash -n ./tests/run.sh" + - shell: | + #!/bin/bash + # we do nothing here as the main stuff will be done + # in phase jobs + echo "Triggering phase jobs!" + - multijob: + name: 'doctor-build-and-unittest' + execution-type: PARALLEL + projects: + - name: 'doctor-verify-unit-test-{stream}' + current-parameters: false + predefined-parameters: | + GERRIT_BRANCH=$GERRIT_BRANCH + GERRIT_REFSPEC=$GERRIT_REFSPEC + GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER + GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE + git-revision: true + node-parameters: false + kill-phase-on: FAILURE + abort-all-job: false - job-template: - name: 'doctor-{task}-{installer}-{inspector}-{pod}-{stream}' - - node: '{slave-label}' - + name: 'doctor-verify-unit-test-{stream}' disabled: '{obj:disabled}' - + wrappers: + - ssh-agent-wrapper + - build-timeout: + timeout: 60 parameters: - project-parameter: project: '{project}' branch: '{branch}' - 'opnfv-build-ubuntu-defaults' - scm: - git-scm-gerrit - - - triggers: - - '{auto-trigger-name}': - project: '{project}' - branch: '{branch}' - files: 'doctor_tests/**' - builders: - - shell: "[ -e tests/run.sh ] && bash -n ./tests/run.sh" + - 'doctor-verify-unit-test-builders-macro' + publishers: + - 'doctor-verify-unit-test-publishers-macro' - job-template: - name: 'doctor-{task}-{installer}-{inspector}-{stream}' + name: 'doctor-{task}-{inspector}-{stream}' - node: '{slave-label}' + disabled: '{obj:disabled}' + + project-type: 'multijob' parameters: - project-parameter: project: '{project}' branch: '{branch}' + - 'opnfv-build-ubuntu-defaults' - string: name: OS_CREDS default: /home/jenkins/openstack.creds description: 'OpenStack credentials' - - '{slave-label}-defaults' - - '{installer}-defaults' - string: name: DOCKER_TAG default: '{docker-tag}' @@ -151,13 +171,17 @@ default: 'doctor-notification' - string: name: TESTCASE_OPTIONS + # yamllint disable rule:line-length default: '-e INSPECTOR_TYPE={inspector} -e PYTHON_ENABLE={is-python} -v $WORKSPACE:/home/opnfv/repos/doctor' + # yamllint enable rule:line-length description: 'Addtional parameters specific to test case(s)' # functest-parameter - string: name: GS_PATHNAME default: '{gs-pathname}' + # yamllint disable rule:line-length description: "Version directory where the opnfv documents will be stored in gs repository" + # yamllint enable rule:line-length - string: name: FUNCTEST_REPO_DIR default: "/home/opnfv/repos/functest" @@ -180,8 +204,91 @@ branch: '{branch}' files: 'doctor_tests/**' + builders: + - shell: | + #!/bin/bash + # we do nothing here as the main stuff will be done + # in phase jobs + echo "Triggering phase jobs!" + - multijob: + name: 'doctor-verify-apex-inspector' + execution-type: PARALLEL + projects: + - name: 'doctor-{task}-apex-{inspector}-build-x86_64-{stream}' + current-parameters: false + predefined-parameters: | + GERRIT_BRANCH=$GERRIT_BRANCH + GERRIT_REFSPEC=$GERRIT_REFSPEC + GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER + GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE + git-revision: true + node-parameters: false + kill-phase-on: FAILURE + abort-all-job: false + - multijob: + name: 'doctor-verify-fuel-inspector' + execution-type: PARALLEL + projects: + - name: 'doctor-{task}-fuel-{inspector}-build-x86_64-{stream}' + current-parameters: false + predefined-parameters: | + GERRIT_BRANCH=$GERRIT_BRANCH + GERRIT_REFSPEC=$GERRIT_REFSPEC + GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER + GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE + git-revision: true + node-parameters: false + kill-phase-on: FAILURE + abort-all-job: false + - multijob: + name: 'doctor-verify-fuel-inspector' + execution-type: PARALLEL + projects: + - name: 'doctor-{task}-fuel-{inspector}-build-aarch64-{stream}' + current-parameters: false + predefined-parameters: | + GERRIT_BRANCH=$GERRIT_BRANCH + GERRIT_REFSPEC=$GERRIT_REFSPEC + GERRIT_CHANGE_NUMBER=$GERRIT_CHANGE_NUMBER + GERRIT_CHANGE_COMMIT_MESSAGE=$GERRIT_CHANGE_COMMIT_MESSAGE + git-revision: true + node-parameters: false + kill-phase-on: FAILURE + abort-all-job: false + +- job-template: + name: 'doctor-{task}-{installer}-{inspector}-{phase}-{stream}' + disabled: '{obj:disabled}' + node: '{slave-label}' + wrappers: + - ssh-agent-wrapper + - build-timeout: + timeout: 30 + parameters: + - project-parameter: + project: '{project}' + branch: '{branch}' + - '{installer}-defaults' + - '{slave-label}-defaults' + scm: + - git-scm-gerrit + builders: + - 'doctor-verify-installer-inspector-builders-macro' + publishers: + - 'doctor-verify-publishers-macro' +# ------------------------------- +# builder macros +# ------------------------------- + +- builder: + name: 'doctor-verify-unit-test-builders-macro' + builders: + - shell: "[ -e tests/run.sh ] && bash -n ./tests/run.sh" +- builder: + name: 'doctor-verify-installer-inspector-builders-macro' builders: - 'clean-workspace-log' + # yamllint disable rule:line-length - shell: | # NOTE: Create symbolic link, so that we can archive file outside # of $WORKSPACE . @@ -200,14 +307,23 @@ # NOTE: checking the test result, as the previous job could return # 0 regardless the result of doctor test scenario. grep -e 'doctor test successfully' $functest_log || exit 1 + # yamllint enable rule:line-length +# ------------------------------- +# publisher macros +# ------------------------------- +- publisher: + name: 'doctor-verify-publishers-macro' publishers: - archive: artifacts: 'doctor_tests/*.log' - archive: artifacts: 'functest_results/$FUNCTEST_SUITE_NAME.log' - email-jenkins-admins-on-failure - +- publisher: + name: 'doctor-verify-unit-test-publishers-macro' + publishers: + - email-jenkins-admins-on-failure ##################################### # trigger macros diff --git a/jjb/dovetail/dovetail-ci-jobs.yml b/jjb/dovetail/dovetail-ci-jobs.yml index 6efe12820..99867c327 100644 --- a/jjb/dovetail/dovetail-ci-jobs.yml +++ b/jjb/dovetail/dovetail-ci-jobs.yml @@ -25,7 +25,13 @@ branch: 'stable/{stream}' dovetail-branch: master gs-pathname: '/{stream}' - docker-tag: 'cvp.0.8.0' + docker-tag: 'cvp.0.9.0' + euphrates: &euphrates + stream: euphrates + branch: 'stable/{stream}' + dovetail-branch: master + gs-pathname: '/{stream}' + docker-tag: 'cvp.0.9.0' # ---------------------------------- # POD, PLATFORM, AND BRANCH MAPPING @@ -60,6 +66,16 @@ SUT: fuel auto-trigger-name: 'daily-trigger-disabled' <<: *danube + - baremetal: + slave-label: fuel-baremetal + SUT: fuel + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates + - virtual: + slave-label: fuel-virtual + SUT: fuel + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates # compass CI PODs - baremetal: slave-label: compass-baremetal @@ -81,6 +97,16 @@ SUT: compass auto-trigger-name: 'daily-trigger-disabled' <<: *danube + - baremetal: + slave-label: compass-baremetal + SUT: compass + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates + - virtual: + slave-label: compass-virtual + SUT: compass + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates # ------------------------------- # Installers not using labels # CI PODs @@ -108,6 +134,16 @@ SUT: apex auto-trigger-name: 'daily-trigger-disabled' <<: *danube + - virtual: + slave-label: apex-virtual-master + SUT: apex + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates + - baremetal: + slave-label: apex-baremetal-master + SUT: apex + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates # armband CI PODs - armband-baremetal: slave-label: armband-baremetal @@ -129,6 +165,16 @@ SUT: fuel auto-trigger-name: 'daily-trigger-disabled' <<: *danube + - armband-baremetal: + slave-label: armband-baremetal + SUT: fuel + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates + - armband-virtual: + slave-label: armband-virtual + SUT: fuel + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates # ------------------------------- # None-CI PODs # ------------------------------- @@ -172,10 +218,29 @@ SUT: compass auto-trigger-name: 'daily-trigger-disabled' <<: *danube + - zte-pod1: + slave-label: zte-pod1 + SUT: fuel + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates + - zte-pod3: + slave-label: zte-pod3 + SUT: fuel + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates + - huawei-pod4: + slave-label: huawei-pod4 + SUT: apex + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates + - huawei-pod7: + slave-label: huawei-pod7 + SUT: compass + auto-trigger-name: 'daily-trigger-disabled' + <<: *euphrates # ------------------------------- testsuite: - - 'compliance_set' - 'proposed_tests' jobs: diff --git a/jjb/dovetail/dovetail-run.sh b/jjb/dovetail/dovetail-run.sh index 2cbb94766..e084e4bd0 100755 --- a/jjb/dovetail/dovetail-run.sh +++ b/jjb/dovetail/dovetail-run.sh @@ -24,6 +24,7 @@ mkdir -p ${DOVETAIL_CONFIG} sshkey="" # The path of openrc.sh is defined in fetch_os_creds.sh OPENRC=${DOVETAIL_CONFIG}/env_config.sh +CACERT=${DOVETAIL_CONFIG}/os_cacert if [[ ${INSTALLER_TYPE} == 'apex' ]]; then instack_mac=$(sudo virsh domiflist undercloud | grep default | \ grep -Eo "[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+") @@ -56,12 +57,22 @@ if [[ ${INSTALLER_TYPE} != 'joid' ]]; then echo "dovetail branch is $BRANCH" BRANCH_BACKUP=$BRANCH export BRANCH=$SUT_BRANCH - ${releng_repo}/utils/fetch_os_creds.sh -d ${OPENRC} -i ${INSTALLER_TYPE} -a ${INSTALLER_IP} >${redirect} + ${releng_repo}/utils/fetch_os_creds.sh -d ${OPENRC} -i ${INSTALLER_TYPE} -a ${INSTALLER_IP} -o ${CACERT} >${redirect} export BRANCH=$BRANCH_BACKUP fi if [[ -f $OPENRC ]]; then echo "INFO: openstack credentials path is $OPENRC" + if [[ ! "${SUT_BRANCH}" =~ "danube" && ${INSTALLER_TYPE} == "compass" ]]; then + if [[ -f ${CACERT} ]]; then + echo "INFO: ${INSTALLER_TYPE} openstack cacert file is ${CACERT}" + echo "export OS_CACERT=${CACERT}" >> ${OPENRC} + else + echo "ERROR: Can't find ${INSTALLER_TYPE} openstack cacert file. Please check if it is existing." + sudo ls -al ${DOVETAIL_CONFIG} + exit 1 + fi + fi cat $OPENRC else echo "ERROR: cannot find file $OPENRC. Please check if it is existing." @@ -69,37 +80,51 @@ else exit 1 fi -set +e - -sudo pip install virtualenv - -cd ${releng_repo}/modules -sudo virtualenv venv -source venv/bin/activate -sudo pip install -e ./ >/dev/null -sudo pip install netaddr +if [[ ! "${SUT_BRANCH}" =~ "danube" && ${INSTALLER_TYPE} == "compass" ]]; then + cat << EOF >${DOVETAIL_CONFIG}/pod.yaml +nodes: +- {ip: 10.1.0.52, name: node1, password: root, role: controller, user: root} +- {ip: 10.1.0.51, name: node2, password: root, role: controller, user: root} +- {ip: 10.1.0.50, name: node3, password: root, role: controller, user: root} +- {ip: 10.1.0.54, name: node4, password: root, role: compute, user: root} +- {ip: 10.1.0.53, name: node5, password: root, role: compute, user: root} -if [[ ${INSTALLER_TYPE} == compass ]]; then - options="-u root -p root" -elif [[ ${INSTALLER_TYPE} == fuel ]]; then - options="-u root -p r00tme" -elif [[ ${INSTALLER_TYPE} == apex ]]; then - options="-u stack -k /root/.ssh/id_rsa" -else - echo "Don't support to generate pod.yaml on ${INSTALLER_TYPE} currently." - echo "HA test cases may not run properly." +EOF fi -cmd="sudo python ${releng_repo}/utils/create_pod_file.py -t ${INSTALLER_TYPE} \ - -i ${INSTALLER_IP} ${options} -f ${DOVETAIL_CONFIG}/pod.yaml" -echo ${cmd} -${cmd} +if [[ ! -f ${DOVETAIL_CONFIG}/pod.yaml ]]; then + set +e + + sudo pip install virtualenv + + cd ${releng_repo}/modules + sudo virtualenv venv + source venv/bin/activate + sudo pip install -e ./ >/dev/null + sudo pip install netaddr + + if [[ ${INSTALLER_TYPE} == compass ]]; then + options="-u root -p root" + elif [[ ${INSTALLER_TYPE} == fuel ]]; then + options="-u root -p r00tme" + elif [[ ${INSTALLER_TYPE} == apex ]]; then + options="-u stack -k /root/.ssh/id_rsa" + else + echo "Don't support to generate pod.yaml on ${INSTALLER_TYPE} currently." + echo "HA test cases may not run properly." + fi -deactivate + cmd="sudo python ${releng_repo}/utils/create_pod_file.py -t ${INSTALLER_TYPE} \ + -i ${INSTALLER_IP} ${options} -f ${DOVETAIL_CONFIG}/pod.yaml" + echo ${cmd} + ${cmd} -set -e + deactivate -cd ${WORKSPACE} + set -e + + cd ${WORKSPACE} +fi if [ -f ${DOVETAIL_CONFIG}/pod.yaml ]; then echo "file ${DOVETAIL_CONFIG}/pod.yaml:" diff --git a/jjb/functest/functest-alpine.sh b/jjb/functest/functest-alpine.sh index bd2bdf4a8..735ca6f7f 100755 --- a/jjb/functest/functest-alpine.sh +++ b/jjb/functest/functest-alpine.sh @@ -4,10 +4,30 @@ set -e set +u set +o pipefail +check_os_deployment() { + FUNCTEST_IMAGE=opnfv/functest-healthcheck:${DOCKER_TAG} + cmd="docker run --rm --privileged=true ${volumes} ${FUNCTEST_IMAGE} check_deployment" + eval ${cmd} + ret_value=$? + if [ ${ret_value} != 0 ]; then + echo "ERROR: Problem while checking OpenStack deployment." + exit 1 + else + echo "OpenStack deployment OK." + fi + +} + + run_tiers() { tiers=$1 - cmd_opt="prepare_env start && run_tests -r -t all" - [[ $BUILD_TAG =~ "suite" ]] && cmd_opt="prepare_env start && run_tests -t all" + if [[ ${BRANCH##*/} == "master" ]]; then + cmd_opt="run_tests -r -t all" + [[ $BUILD_TAG =~ "suite" ]] && cmd_opt="run_tests -t all" + else + cmd_opt="prepare_env start && run_tests -r -t all" + [[ $BUILD_TAG =~ "suite" ]] && cmd_opt="prepare_env start && run_tests -t all" + fi ret_val_file="${HOME}/opnfv/functest/results/${BRANCH##*/}/return_value" echo 0 > ${ret_val_file} @@ -15,7 +35,7 @@ run_tiers() { FUNCTEST_IMAGE=opnfv/functest-${tier}:${DOCKER_TAG} echo "Functest: Pulling Functest Docker image ${FUNCTEST_IMAGE} ..." docker pull ${FUNCTEST_IMAGE}>/dev/null - cmd="docker run --privileged=true ${envs} ${volumes} ${TESTCASE_OPTIONS} ${FUNCTEST_IMAGE} /bin/bash -c '${cmd_opt}'" + cmd="docker run --rm --privileged=true ${envs} ${volumes} ${TESTCASE_OPTIONS} ${FUNCTEST_IMAGE} /bin/bash -c '${cmd_opt}'" echo "Running Functest tier '${tier}'. CMD: ${cmd}" eval ${cmd} ret_value=$? @@ -31,21 +51,24 @@ run_tiers() { run_test() { test_name=$1 - cmd_opt="prepare_env start && run_tests -t ${test_name}" - [[ $BUILD_TAG =~ "suite" ]] && cmd_opt="prepare_env start && run_tests -t ${test_name}" + if [[ ${BRANCH##*/} == "master" ]]; then + cmd_opt="run_tests -t ${test_name}" + else + cmd_opt="prepare_env start && run_tests -t ${test_name}" + fi ret_val_file="${HOME}/opnfv/functest/results/${BRANCH##*/}/return_value" echo 0 > ${ret_val_file} # Determine which Functest image should be used for the test case case ${test_name} in connection_check|api_check|snaps_health_check) FUNCTEST_IMAGE=opnfv/functest-healthcheck:${DOCKER_TAG} ;; - vping_ssh|vping_userdata|tempest_smoke_serial|rally_sanity|refstack_defcore|odl|odl_netvirt|fds|snaps_smoke) + vping_ssh|vping_userdata|tempest_smoke_serial|rally_sanity|refstack_defcore|odl|odl_netvirt|snaps_smoke) FUNCTEST_IMAGE=opnfv/functest-smoke:${DOCKER_TAG} ;; - tempest_full_parallel|tempest_custom|rally_full) + tempest_full_parallel|rally_full) FUNCTEST_IMAGE=opnfv/functest-components:${DOCKER_TAG} ;; cloudify_ims|orchestra_openims|orchestra_clearwaterims|vyos_vrouter) FUNCTEST_IMAGE=opnfv/functest-vnf:${DOCKER_TAG} ;; - promise|doctor-notification|bgpvpn|functest-odl-sfc|domino-multinode|barometercollectd) + promise|doctor-notification|bgpvpn|functest-odl-sfc|domino-multinode|barometercollectd|fds) FUNCTEST_IMAGE=opnfv/functest-features:${DOCKER_TAG} ;; parser-basics) FUNCTEST_IMAGE=opnfv/functest-parser:${DOCKER_TAG} ;; @@ -56,7 +79,7 @@ run_test() { esac echo "Functest: Pulling Functest Docker image ${FUNCTEST_IMAGE} ..." docker pull ${FUNCTEST_IMAGE}>/dev/null - cmd="docker run --privileged=true ${envs} ${volumes} ${TESTCASE_OPTIONS} ${FUNCTEST_IMAGE} /bin/bash -c '${cmd_opt}'" + cmd="docker run --rm --privileged=true ${envs} ${volumes} ${TESTCASE_OPTIONS} ${FUNCTEST_IMAGE} /bin/bash -c '${cmd_opt}'" echo "Running Functest test case '${test_name}'. CMD: ${cmd}" eval ${cmd} ret_value=$? @@ -71,7 +94,7 @@ FUNCTEST_DIR=/home/opnfv/functest DEPLOY_TYPE=baremetal [[ $BUILD_TAG =~ "virtual" ]] && DEPLOY_TYPE=virt HOST_ARCH=$(uname -m) -DOCKER_TAG=${DOCKER_TAG:-latest} +DOCKER_TAG=`[[ ${BRANCH##*/} == "master" ]] && echo "latest" || echo ${BRANCH##*/}` # Prepare OpenStack credentials volume rc_file=${HOME}/opnfv-openrc.sh @@ -132,6 +155,7 @@ set +e if [[ ${DEPLOY_SCENARIO} =~ ^os-.* ]]; then + [[ ${BRANCH##*/} == "master" ]] && check_os_deployment if [ ${FUNCTEST_MODE} == 'testcase' ]; then echo "FUNCTEST_MODE=testcase, FUNCTEST_SUITE_NAME=${FUNCTEST_SUITE_NAME}" run_test ${FUNCTEST_SUITE_NAME} diff --git a/jjb/functest/functest-cleanup.sh b/jjb/functest/functest-cleanup.sh index fc277b9ed..c21b543a6 100755 --- a/jjb/functest/functest-cleanup.sh +++ b/jjb/functest/functest-cleanup.sh @@ -3,11 +3,7 @@ [[ $CI_DEBUG == true ]] && redirect="/dev/stdout" || redirect="/dev/null" echo "Cleaning up docker containers/images..." -HOST_ARCH=$(uname -m) FUNCTEST_IMAGE=opnfv/functest -if [ "$HOST_ARCH" = "aarch64" ]; then - FUNCTEST_IMAGE="${FUNCTEST_IMAGE}_${HOST_ARCH}" -fi # Remove containers along with image opnfv/functest*: dangling_images=($(docker images -f "dangling=true" | grep $FUNCTEST_IMAGE | awk '{print $3}')) diff --git a/jjb/functest/functest-daily-jobs.yml b/jjb/functest/functest-daily-jobs.yml index 2fc70b916..2d5d397ae 100644 --- a/jjb/functest/functest-daily-jobs.yml +++ b/jjb/functest/functest-daily-jobs.yml @@ -14,12 +14,10 @@ stream: master branch: '{stream}' gs-pathname: '' - docker-tag: 'latest' euphrates: &euphrates stream: euphrates branch: 'stable/{stream}' gs-pathname: '/{stream}' - docker-tag: 'stable' # ------------------------------- # POD, INSTALLER, AND BRANCH MAPPING # ------------------------------- @@ -233,10 +231,6 @@ - string: name: DEPLOY_SCENARIO default: 'os-odl_l2-nofeature-ha' - - string: - name: DOCKER_TAG - default: '{docker-tag}' - description: 'Tag to pull docker image' - string: name: CLEAN_DOCKER_IMAGES default: 'false' @@ -399,8 +393,7 @@ !include-raw: - ./functest-env-presetup.sh - ../../utils/fetch_os_creds.sh - - ./set-functest-env.sh - - ./functest-loop.sh + - ./functest-alpine.sh # yamllint enable rule:indentation - builder: diff --git a/jjb/functest/functest-loop.sh b/jjb/functest/functest-loop.sh deleted file mode 100755 index a590d9f95..000000000 --- a/jjb/functest/functest-loop.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set +e - -[[ "$PUSH_RESULTS_TO_DB" == "true" ]] && flags+="-r" -cmd="run_tests -t all ${flags}" - -container_id=$(docker ps -a | grep opnfv/functest | awk '{print $1}' | head -1) -docker exec $container_id $cmd - -ret_value=$? -ret_val_file="${HOME}/opnfv/functest/results/${BRANCH##*/}/return_value" -echo ${ret_value}>${ret_val_file} - -exit 0 diff --git a/jjb/functest/functest-weekly-jobs.yml b/jjb/functest/functest-weekly-jobs.yml index 6826e4151..5d572aacc 100644 --- a/jjb/functest/functest-weekly-jobs.yml +++ b/jjb/functest/functest-weekly-jobs.yml @@ -118,12 +118,10 @@ # yamllint disable rule:indentation - shell: !include-raw: - - ./functest-env-presetup.sh - - ../../utils/fetch_os_creds.sh - - ./set-functest-env.sh + - ./functest-env-presetup.sh + - ../../utils/fetch_os_creds.sh + - ./functest-alpine.sh # yamllint enable rule:indentation - - shell: - !include-raw: ./functest-loop.sh - shell: !include-raw: ../../utils/push-test-logs.sh - shell: diff --git a/jjb/functest/set-functest-env.sh b/jjb/functest/set-functest-env.sh deleted file mode 100755 index b116a8528..000000000 --- a/jjb/functest/set-functest-env.sh +++ /dev/null @@ -1,111 +0,0 @@ -#!/bin/bash - -set -e -set +u -set +o pipefail - -[[ $CI_DEBUG == true ]] && redirect="/dev/stdout" || redirect="/dev/null" - -DEPLOY_TYPE=baremetal -[[ $BUILD_TAG =~ "virtual" ]] && DEPLOY_TYPE=virt -HOST_ARCH=$(uname -m) - -# Prepare OpenStack credentials volume -rc_file_vol="-v ${HOME}/opnfv-openrc.sh:/home/opnfv/functest/conf/openstack.creds" - -if [[ ${INSTALLER_TYPE} == 'joid' ]]; then - rc_file_vol="-v $LAB_CONFIG/admin-openrc:/home/opnfv/functest/conf/openstack.creds" -elif [[ ${INSTALLER_TYPE} == 'compass' && ${BRANCH} == 'master' ]]; then - cacert_file_vol="-v ${HOME}/os_cacert:/home/opnfv/functest/conf/os_cacert" - echo "export OS_CACERT=/home/opnfv/functest/conf/os_cacert" >> ${HOME}/opnfv-openrc.sh -elif [[ ${INSTALLER_TYPE} == 'fuel' && ${DEPLOY_TYPE} == 'baremetal' ]]; then - cacert_file_vol="-v ${HOME}/os_cacert:/etc/ssl/certs/mcp_os_cacert" -fi - - -# Set iptables rule to allow forwarding return traffic for container -if ! sudo iptables -C FORWARD -j RETURN 2> ${redirect} || ! sudo iptables -L FORWARD | awk 'NR==3' | grep RETURN 2> ${redirect}; then - sudo iptables -I FORWARD -j RETURN -fi - -echo "Functest: Start Docker and prepare environment" - -if [ "$BRANCH" != 'stable/danube' ]; then - echo "Functest: Download images that will be used by test cases" - images_dir="${HOME}/opnfv/functest/images" - chmod +x ${WORKSPACE}/functest/ci/download_images.sh - ${WORKSPACE}/functest/ci/download_images.sh ${images_dir} > ${redirect} - images_vol="-v ${images_dir}:/home/opnfv/functest/images" - echo "Functest: Images successfully downloaded" -fi - -dir_result="${HOME}/opnfv/functest/results/${BRANCH##*/}" -mkdir -p ${dir_result} -sudo rm -rf ${dir_result}/* -results_vol="-v ${dir_result}:/home/opnfv/functest/results" -custom_params= -test -f ${HOME}/opnfv/functest/custom/params_${DOCKER_TAG} && custom_params=$(cat ${HOME}/opnfv/functest/custom/params_${DOCKER_TAG}) -echo "Functest: custom parameters successfully retrieved: ${custom_params}" - -envs="-e INSTALLER_TYPE=${INSTALLER_TYPE} -e INSTALLER_IP=${INSTALLER_IP} \ - -e NODE_NAME=${NODE_NAME} -e DEPLOY_SCENARIO=${DEPLOY_SCENARIO} \ - -e BUILD_TAG=${BUILD_TAG} -e CI_DEBUG=${CI_DEBUG} -e DEPLOY_TYPE=${DEPLOY_TYPE}" - -ssh_options="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" - -if [ "${INSTALLER_TYPE}" == 'fuel' ] && [ "$BRANCH" != 'stable/danube' ]; then - COMPUTE_ARCH=$(ssh -l ubuntu ${INSTALLER_IP} -i ${SSH_KEY} ${ssh_options} \ - "sudo salt 'cmp*' grains.get cpuarch --out yaml | awk '{print \$2; exit}'") - envs="${envs} -e POD_ARCH=${COMPUTE_ARCH}" -fi - -if [[ ${INSTALLER_TYPE} == 'compass' && ${DEPLOY_SCENARIO} == *'os-nosdn-openo-ha'* ]]; then - openo_msb_port=${openo_msb_port:-80} - openo_msb_endpoint="$(sshpass -p'root' ssh 2>/dev/null $ssh_options root@${installer_ip} \ - 'mysql -ucompass -pcompass -Dcompass -e "select package_config from cluster;" \ - | sed s/,/\\n/g | grep openo_ip | cut -d \" -f 4'):$openo_msb_port" - - envs=${env}" -e OPENO_MSB_ENDPOINT=${openo_msb_endpoint}" -fi - -if [ "$BRANCH" != 'stable/danube' ]; then - volumes="${images_vol} ${results_vol} ${sshkey_vol} ${stackrc_vol} ${rc_file_vol} ${cacert_file_vol}" -else - volumes="${results_vol} ${sshkey_vol} ${stackrc_vol} ${rc_file_vol}" -fi - -echo "Functest: volumes defined" - -FUNCTEST_IMAGE="opnfv/functest" -if [ "$HOST_ARCH" = "aarch64" ]; then - FUNCTEST_IMAGE="${FUNCTEST_IMAGE}_${HOST_ARCH}" -fi - -echo "Functest: Pulling Functest Docker image ${FUNCTEST_IMAGE}:${DOCKER_TAG}" -docker pull ${FUNCTEST_IMAGE}:$DOCKER_TAG >/dev/null - -cmd="sudo docker run --privileged=true -id ${envs} ${volumes} \ - ${custom_params} ${TESTCASE_OPTIONS} \ - ${FUNCTEST_IMAGE}:${DOCKER_TAG} /bin/bash" -echo "Functest: Running docker run command: ${cmd}" -${cmd} >${redirect} -sleep 5 -container_id=$(docker ps | grep "${FUNCTEST_IMAGE}:${DOCKER_TAG}" | awk '{print $1}' | head -1) -echo "Container ID=${container_id}" -if [ -z ${container_id} ]; then - echo "Cannot find opnfv/functest container ID ${container_id}. Please check if it is existing." - docker ps -a - exit 1 -fi -echo "Starting the container: docker start ${container_id}" -docker start ${container_id} -sleep 5 -docker ps >${redirect} -if [ $(docker ps | grep "${FUNCTEST_IMAGE}:${DOCKER_TAG}" | wc -l) == 0 ]; then - echo "The container ${FUNCTEST_IMAGE} with ID=${container_id} has not been properly started. Exiting..." - exit 1 -fi - -cmd="prepare_env start" -echo "Executing command inside the docker: ${cmd}" -docker exec ${container_id} ${cmd} diff --git a/jjb/global/releng-macros.yml b/jjb/global/releng-macros.yml index e00047ba0..86f4c4265 100644 --- a/jjb/global/releng-macros.yml +++ b/jjb/global/releng-macros.yml @@ -195,17 +195,6 @@ #!/bin/bash sudo chown -R $USER:$USER $WORKSPACE || exit 1 -- builder: - name: build-html-and-pdf-docs-output - builders: - - shell: | - #!/bin/bash - set -o errexit - set -o xtrace - export PATH=$PATH:/usr/local/bin/ - git clone ssh://gerrit.opnfv.org:29418/opnfvdocs docs_build/_opnfvdocs - GERRIT_COMMENT=gerrit_comment.txt ./docs_build/_opnfvdocs/scripts/docs-build.sh - - builder: name: upload-under-review-docs-to-opnfv-artifacts builders: @@ -217,7 +206,7 @@ export PATH=$PATH:/usr/local/bin/ [[ $GERRIT_CHANGE_NUMBER =~ .+ ]] - [[ -d docs_output ]] || exit 0 + [[ -d docs/_build/ ]] || exit 0 echo echo "###########################" @@ -230,7 +219,7 @@ local_path="upload/$GERRIT_CHANGE_NUMBER" mkdir -p upload - mv docs_output "$local_path" + mv docs/_build/html/ "$local_path" gsutil -m cp -r "$local_path" "gs://$gs_base" gsutil -m setmeta \ @@ -242,46 +231,6 @@ find "$local_path" | grep -e 'index.html$' -e 'pdf$' | \ sed -e "s|^$local_path| http://$gs_path|" >> gerrit_comment.txt -- builder: - name: upload-generated-docs-to-opnfv-artifacts - builders: - - shell: | - #!/bin/bash - set -o errexit - set -o pipefail - set -o xtrace - export PATH=$PATH:/usr/local/bin/ - - [[ -d docs_output ]] || exit 0 - - echo - echo "########################" - echo "UPLOADING GENERATED DOCS" - echo "########################" - echo - - echo "gs_path="$GS_URL/docs"" - echo "local_path="upload/docs"" - - gs_path="$GS_URL/docs" - local_path="upload/docs" - - mkdir -p upload - mv docs_output "$local_path" - ls "$local_path" - - echo "gsutil -m cp -r "$local_path"/* "gs://$gs_path"" - gsutil -m cp -r "$local_path"/* "gs://$gs_path" - - gsutil -m setmeta \ - -h "Content-Type:text/html" \ - -h "Cache-Control:private, max-age=0, no-transform" \ - "gs://$gs_path"/**.html > /dev/null 2>&1 - - echo "Document link(s):" >> gerrit_comment.txt - find "$local_path" | grep -e 'index.html$' -e 'pdf$' | \ - sed -e "s|^$local_path| http://$gs_path|" >> gerrit_comment.txt - # To take advantage of this macro, have your build write # out the file 'gerrit_comment.txt' with information to post # back to gerrit and include this macro in the list of builders. @@ -334,28 +283,6 @@ gsutil -m rm -r "gs://$gs_path" fi -- builder: - name: build-and-upload-artifacts-json-api - builders: - - shell: | - #!/bin/bash - set -o errexit - set -o pipefail - export PATH=$PATH:/usr/local/bin/ - - virtualenv -p python2.7 $WORKSPACE/releng_artifacts - source $WORKSPACE/releng_artifacts/bin/activate - - # install python packages - pip install google-api-python-client - - # generate and upload index file - echo "Generating Artifacts API ..." - python $WORKSPACE/utils/opnfv-artifacts.py > index.json - gsutil cp index.json gs://artifacts.opnfv.org/index.json - - deactivate - - builder: name: lint-python-code builders: @@ -431,18 +358,9 @@ - builder: name: upload-review-docs builders: - - build-html-and-pdf-docs-output - upload-under-review-docs-to-opnfv-artifacts - report-build-result-to-gerrit -- builder: - name: upload-merged-docs - builders: - - build-html-and-pdf-docs-output - - upload-generated-docs-to-opnfv-artifacts - - report-build-result-to-gerrit - - remove-old-docs-from-opnfv-artifacts - - builder: name: check-bash-syntax builders: @@ -459,23 +377,29 @@ export PATH=$PATH:/usr/local/bin/ # install python packages - pip install "yamllint==1.6.0" + sudo pip install "yamllint==1.8.2" # generate and upload lint log echo "Running yaml code on $PROJECT ..." + # Get list of yaml files + YAML_FILES=$(git --no-pager diff --diff-filter=MCRAT --name-only HEAD^1 | egrep "ya?ml$") || true + + #If YAML_FILES is none exit with 0 + if [ -z "$YAML_FILES" ]; then + exit 0 + fi + # Ensure we start with a clean environment rm -f yaml-violation.log lint.log - # Get number of yaml violations. If none, this will be an - # empty string: "" - find . \ - -type f -name "*.yml" -print \ - -o -name "*.yaml" -print | \ - xargs yamllint > yaml-violation.log || true + # Yamllint files only in patchset + for yamlfile in $YAML_FILES; do + yamllint $yamlfile >> yaml-violation.log || true + done if [ -s "yaml-violation.log" ]; then - SHOWN=$(cat yaml-violation.log| grep -v "^$" |wc -l) + SHOWN=$(grep -c -v "^$" yaml-violation.log) echo -e "First $SHOWN shown\n---" > lint.log cat yaml-violation.log >> lint.log sed -r -i '4,$s/^/ /g' lint.log @@ -539,3 +463,501 @@ failure: true send-to: - recipients + +# Email PTL publishers +- email_ptl_defaults: &email_ptl_defaults + name: 'email_ptl_defaults' + content-type: text + attach-build-log: true + attachments: '*.log' + compress-log: true + always: true + subject: '{subject}' + +- publisher: &email_apex_ptl_defaults + name: 'email-apex-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + trozet@redhat.com +- publisher: + name: 'email-apex-os-net-config-ptl' + <<: *email_apex_ptl_defaults +- publisher: + name: 'email-apex-puppet-tripleo-ptl' + <<: *email_apex_ptl_defaults +- publisher: + name: 'email-apex-tripleo-heat-templates-ptl' + <<: *email_apex_ptl_defaults + +- publisher: + name: 'email-armband-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + bob.monkman@arm.com + +- publisher: + name: 'email-auto-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + tina.tsou@arm.com + +- publisher: + name: 'email-availability-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + fuqiao@chinamobile.com + +- publisher: + name: 'email-bamboo-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + donaldh@cisco.com + +- publisher: + name: 'email-barometer-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + aasmith@redhat.com + +- publisher: + name: 'email-bottlenecks-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + gabriel.yuyang@huawei.com + +- publisher: + name: 'email-calipso-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + korlev@cisco.com + +- publisher: + name: 'email-clover-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + stephen.wong1@huawei.com + +- publisher: &email_compass4nfv_ptl_defaults + name: 'email-compass4nfv-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + chigang@huawei.com +- publisher: + name: 'email-compass-containers-ptl' + <<: *email_compass4nfv_ptl_defaults + +- publisher: + name: 'email-conductor-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + limingjiang@huawei.com + +- publisher: + name: 'email-container4nfv-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + jiaxuan@chinamobile.com + +- publisher: + name: 'email-copper-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + aimeeu.opensource@gmail.com + +- publisher: + name: 'email-cperf-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + matt.welch@intel.com + +- publisher: + name: 'email-daisy-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + hu.zhijiang@zte.com.cn + +- publisher: + name: 'email-doctor-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + r-mibu@cq.jp.nec.com + +- publisher: + name: 'email-domino-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + ulas.kozat@huawei.com + +- publisher: + name: 'email-dovetail-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + hongbo.tianhongbo@huawei.com + +- publisher: + name: 'email-dpacc-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + denglingli@chinamobile.com + +- publisher: + name: 'email-enfv-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + JBuchanan@advaoptical.com + +- publisher: + name: 'email-escalator-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + kong.wei2@zte.com.cn + +- publisher: + name: 'email-fastpathmetrics-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + maryam.tahhan@intel.com + +- publisher: + name: 'email-fds-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + fbrockne@cisco.com + +- publisher: + name: 'email-fuel-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + gelkinbard@mirantis.com + +- publisher: + name: 'email-functest-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + cedric.ollivier@orange.com + +- publisher: + name: 'email-ipv6-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + bh526r@att.com + +- publisher: + name: 'email-joid-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + artur.tyloch@canonical.com + +- publisher: + name: 'email-kvmfornfv-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + raghuveer.reddy@intel.com + +- publisher: + name: 'email-models-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + bs3131@att.com + +- publisher: + name: 'email-moon-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + ruan.he@orange.com + +- publisher: + name: 'email-multisite-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + joehuang@huawei.com + +- publisher: + name: 'email-netready-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + georg.kunz@ericsson.com + +- publisher: + name: 'email-nfvbench-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + ahothan@cisco.com + +- publisher: + name: 'email-octopus-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + ulrich.kleber@huawei.com + +- publisher: + name: 'email-onosfw-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + su.wei@huawei.com + +- publisher: + name: 'email-openretriever-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + jiaxuan@chinamobile.com + +- publisher: + name: 'email-opera-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + Yingjun.li@huawei.com + +- publisher: + name: 'email-opnfvdocs-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + sofia.wallin@ericsson.com + +- publisher: + name: 'email-orchestra-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + giuseppe.carella@fokus.fraunhofer.de + +- publisher: + name: 'email-ovn4nfv-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + trinath.somanchi@gmail.com + +- publisher: + name: 'email-ovno-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + wsmackie@juniper.net + +- publisher: + name: 'email-ovsnfv-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + MarkD.Graymark.d.gray@intel.com + +- publisher: + name: 'email-parser-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + shang.xiaodong@zte.com.cn + +- publisher: &email_pharos_ptl_defaults + name: 'email-pharos-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + jack.morgan@intel.com +- publisher: + name: 'email-pharos-tools-ptl' + <<: *email_pharos_ptl_defaults + +- publisher: + name: 'email-promise-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + kunzmann@docomolab-euro.com + +- publisher: + name: 'email-qtip-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + wu.zhihui1@zte.com.cn + +- publisher: &email_releng_ptl_defaults + name: 'email-releng-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + fatih.degirmenci@ericsson.com +- publisher: + name: 'email-releng-anteater-ptl' + <<: *email_releng_ptl_defaults +- publisher: + name: 'email-releng-testresults-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + fatih.degirmenci@ericsson.com + feng.xiaowei@zte.com.cn +- publisher: + name: 'email-releng-utils-ptl' + <<: *email_releng_ptl_defaults +- publisher: + name: 'email-releng-xci-ptl' + <<: *email_releng_ptl_defaults + +- publisher: + name: 'email-samplevnf-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + deepak.s@intel.com + +- publisher: + name: 'email-sdnvpn-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + tim.irnich@ericsson.com + +- publisher: + name: 'email-securityscanning-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + lhinds@redhat.com + +- publisher: + name: 'email-sfc-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + ManuelBuilmbuil@suse.com + +- publisher: + name: 'email-snaps-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + s.pisarski@cablelabs.com + +- publisher: + name: 'email-stor4nfv-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + shane.wang@intel.com + +- publisher: + name: 'email-storperf-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + mark.beierl@emc.com + +- publisher: + name: 'email-ves-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + bryan.sullivan@att.com + +- publisher: + name: 'email-vswitchperf-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + sridhar.rao@spirent.com + +- publisher: + name: 'email-yardstick-ptl' + publishers: + - email-ext: + <<: *email_ptl_defaults + recipients: > + ross.b.brattain@intel.com diff --git a/jjb/global/slave-params.yml b/jjb/global/slave-params.yml index 0ea37d941..c645de60e 100644 --- a/jjb/global/slave-params.yml +++ b/jjb/global/slave-params.yml @@ -456,6 +456,18 @@ default: $WORKSPACE/build_output description: "Directory where the build artifact will be located upon the completion of the build." +- parameter: + name: 'ericsson-build3-defaults' + parameters: + - label: + name: SLAVE_LABEL + default: 'ericsson-build3' + description: 'Slave label on Jenkins' + - string: + name: GIT_BASE + default: https://gerrit.opnfv.org/gerrit/$PROJECT + description: 'Git URL to use on this Jenkins Slave' + - parameter: name: 'huawei-build-defaults' parameters: @@ -756,6 +768,21 @@ default: https://gerrit.opnfv.org/gerrit/$PROJECT description: 'Git URL to use on this Jenkins Slave' +- parameter: + name: zte-virtual6-defaults + parameters: + - node: + name: SLAVE_NAME + description: 'Slave name on Jenkins' + allowed-slaves: + - zte-virtual6 + default-slaves: + - zte-virtual6 + - string: + name: GIT_BASE + default: https://gerrit.opnfv.org/gerrit/$PROJECT + description: 'Git URL to use on this Jenkins Slave' + - parameter: name: 'juniper-pod1-defaults' parameters: @@ -930,6 +957,12 @@ - 'doctor-defaults': default-slave: 'doctor-fuel-verify' +- parameter: + name: 'doctor-fuel-build-aarch64-verify-defaults' + parameters: + - 'doctor-defaults': + default-slave: 'doctor-fuel-build-aarch64-verify' + - parameter: name: 'doctor-joid-verify-defaults' parameters: diff --git a/jjb/joid/joid-daily-jobs.yml b/jjb/joid/joid-daily-jobs.yml index 569bff293..947b2f1ab 100644 --- a/jjb/joid/joid-daily-jobs.yml +++ b/jjb/joid/joid-daily-jobs.yml @@ -18,6 +18,11 @@ branch: 'stable/{stream}' disabled: false gs-pathname: '/{stream}' + master: &master + stream: master + branch: '{stream}' + disabled: false + gs-pathname: '' # ------------------------------- # POD, INSTALLER, AND BRANCH MAPPING # ------------------------------- @@ -27,7 +32,9 @@ - baremetal: slave-label: joid-baremetal <<: *euphrates - + - baremetal: + slave-label: joid-baremetal + <<: *master # ------------------------------- # scenarios # ------------------------------- @@ -56,6 +63,14 @@ auto-trigger-name: 'joid-{scenario}-{pod}-{stream}-trigger' - 'os-nosdn-openbaton-ha': auto-trigger-name: 'joid-{scenario}-{pod}-{stream}-trigger' + - 'k8-canal-lb-noha': + auto-trigger-name: 'joid-{scenario}-{pod}-{stream}-trigger' + - 'k8-nosdn-lb_ceph-noha': + auto-trigger-name: 'joid-{scenario}-{pod}-{stream}-trigger' + - 'k8-multus-lb-noha': + auto-trigger-name: 'daily-trigger-disabled' + - 'os-ovn-nofeature-ha': + auto-trigger-name: 'daily-trigger-disabled' jobs: - 'joid-{scenario}-{pod}-daily-{stream}' @@ -222,53 +237,148 @@ name: 'joid-os-nosdn-nofeature-ha-baremetal-euphrates-trigger' triggers: - timed: '5 2 * * *' +# os-nosdn-nofeature-ha trigger - branch: master +- trigger: + name: 'joid-os-nosdn-nofeature-ha-baremetal-master-trigger' + triggers: + - timed: '5 2 * * *' # os-odl_l2-nofeature-ha trigger - branch: euphrates - trigger: name: 'joid-os-odl_l2-nofeature-ha-baremetal-euphrates-trigger' triggers: - timed: '5 7 * * *' +# os-odl_l2-nofeature-ha trigger - branch: master +- trigger: + name: 'joid-os-odl_l2-nofeature-ha-baremetal-master-trigger' + triggers: + - timed: '5 7 * * *' # os-nosdn-lxd-noha trigger - branch: euphrates - trigger: name: 'joid-os-nosdn-lxd-noha-baremetal-euphrates-trigger' triggers: - timed: '5 22 * * *' +# os-nosdn-lxd-noha trigger - branch: master +- trigger: + name: 'joid-os-nosdn-lxd-noha-baremetal-master-trigger' + triggers: + - timed: '5 22 * * *' # os-nosdn-lxd-ha trigger - branch: euphrates - trigger: name: 'joid-os-nosdn-lxd-ha-baremetal-euphrates-trigger' triggers: - timed: '5 10 * * *' +# os-nosdn-lxd-ha trigger - branch: master +- trigger: + name: 'joid-os-nosdn-lxd-ha-baremetal-master-trigger' + triggers: + - timed: '5 10 * * *' # os-nosdn-nofeature-noha trigger - branch: euphrates - trigger: name: 'joid-os-nosdn-nofeature-noha-baremetal-euphrates-trigger' triggers: - timed: '5 4 * * *' +# os-nosdn-nofeature-noha trigger - branch: master +- trigger: + name: 'joid-os-nosdn-nofeature-noha-baremetal-master-trigger' + triggers: + - timed: '5 4 * * *' # k8-nosdn-nofeature-noha trigger - branch: euphrates - trigger: name: 'joid-k8-nosdn-nofeature-noha-baremetal-euphrates-trigger' triggers: - timed: '5 15 * * *' +# k8-nosdn-nofeature-noha trigger - branch: master +- trigger: + name: 'joid-k8-nosdn-nofeature-noha-baremetal-master-trigger' + triggers: + - timed: '5 15 * * *' # k8-nosdn-lb-noha trigger - branch: euphrates - trigger: name: 'joid-k8-nosdn-lb-noha-baremetal-euphrates-trigger' triggers: - timed: '5 20 * * *' +# k8-nosdn-lb-noha trigger - branch: master +- trigger: + name: 'joid-k8-nosdn-lb-noha-baremetal-master-trigger' + triggers: + - timed: '5 20 * * *' # k8-ovn-lb-noha trigger - branch: euphrates - trigger: name: 'joid-k8-ovn-lb-noha-baremetal-euphrates-trigger' triggers: - timed: '5 17 * * *' +# k8-ovn-lb-noha trigger - branch: master +- trigger: + name: 'joid-k8-ovn-lb-noha-baremetal-master-trigger' + triggers: + - timed: '5 17 * * *' # os-nosdn-openbaton-ha trigger - branch: euphrates - trigger: name: 'joid-os-nosdn-openbaton-ha-baremetal-euphrates-trigger' triggers: - - timed: '5 25 * * *' + - timed: '5 23 * * *' +# os-nosdn-openbaton-ha trigger - branch: master +- trigger: + name: 'joid-os-nosdn-openbaton-ha-baremetal-master-trigger' + triggers: + - timed: '5 23 * * *' # os-ocl-nofeature-ha trigger - branch: euphrates - trigger: name: 'joid-os-ocl-nofeature-ha-baremetal-euphrates-trigger' triggers: - timed: '5 13 * * *' -# os-ocl-nofeature-ha trigger - branch: euphrates +# os-ocl-nofeature-ha trigger - branch: master +- trigger: + name: 'joid-os-ocl-nofeature-ha-baremetal-master-trigger' + triggers: + - timed: '5 13 * * *' +# os-ocl-nofeature-noha trigger - branch: euphrates - trigger: name: 'joid-os-ocl-nofeature-noha-baremetal-euphrates-trigger' triggers: - - timed: '5 17 * * *' + - timed: '5 16 * * *' +# os-ocl-nofeature-noha trigger - branch: master +- trigger: + name: 'joid-os-ocl-nofeature-noha-baremetal-master-trigger' + triggers: + - timed: '5 16 * * *' +# k8-canal-lb-noha trigger - branch: euphrates +- trigger: + name: 'joid-k8-canal-lb-noha-baremetal-euphrates-trigger' + triggers: + - timed: '5 14 * * *' +# k8-canal-lb-noha trigger - branch: master +- trigger: + name: 'joid-k8-canal-lb-noha-baremetal-master-trigger' + triggers: + - timed: '5 14 * * *' +# k8-multus-lb-noha trigger - branch: euphrates +- trigger: + name: 'joid-k8-multus-lb-noha-baremetal-euphrates-trigger' + triggers: + - timed: '5 18 * * *' +# k8-multus-lb-noha trigger - branch: master +- trigger: + name: 'joid-k8-multus-lb-noha-baremetal-master-trigger' + triggers: + - timed: '5 18 * * *' +# k8-nosdn-lb_ceph-noha trigger - branch: euphrates +- trigger: + name: 'joid-k8-nosdn-lb_ceph-noha-baremetal-euphrates-trigger' + triggers: + - timed: '5 18 * * *' +# k8-nosdn-lb_ceph-noha trigger - branch: master +- trigger: + name: 'joid-k8-nosdn-lb_ceph-noha-baremetal-master-trigger' + triggers: + - timed: '5 18 * * *' +# os-ovn-nofeature-ha trigger - branch: euphrates +- trigger: + name: 'joid-os-ovn-nofeature-ha-baremetal-euphrates-trigger' + triggers: + - timed: '5 19 * * *' +# os-ovn-nofeature-ha trigger - branch: master +- trigger: + name: 'joid-os-ovn-nofeature-ha-baremetal-master-trigger' + triggers: + - timed: '5 19 * * *' diff --git a/jjb/kvmfornfv/kvmfornfv.yml b/jjb/kvmfornfv/kvmfornfv.yml index aae6e028e..ad497e97d 100644 --- a/jjb/kvmfornfv/kvmfornfv.yml +++ b/jjb/kvmfornfv/kvmfornfv.yml @@ -8,7 +8,7 @@ - master: branch: '{stream}' gs-pathname: '' - disabled: true + disabled: false - euphrates: branch: 'stable/{stream}' gs-pathname: '/{stream}' diff --git a/jjb/opnfvdocs/docs-rtd.yaml b/jjb/opnfvdocs/docs-rtd.yaml index e15b09812..28f9354fa 100644 --- a/jjb/opnfvdocs/docs-rtd.yaml +++ b/jjb/opnfvdocs/docs-rtd.yaml @@ -38,6 +38,7 @@ files: 'docs/**/*.*' builders: + - 'remove-old-docs-from-opnfv-artifacts' - shell: | if [ $GERRIT_BRANCH == "master" ]; then RTD_BUILD_VERSION=latest @@ -91,4 +92,6 @@ pip install --upgrade pip pip freeze pip install tox + sed -i s,\-b\ html,\-b\ singlehtml,g tox.ini tox -edocs + - 'upload-review-docs' diff --git a/jjb/opnfvdocs/opnfvdocs.yml b/jjb/opnfvdocs/opnfvdocs.yml index 95bc8a9dd..3dfb9d155 100644 --- a/jjb/opnfvdocs/opnfvdocs.yml +++ b/jjb/opnfvdocs/opnfvdocs.yml @@ -11,7 +11,6 @@ jobs: - 'opnfvdocs-verify-shellcheck-{stream}' - 'opnfvdocs-merge-shellcheck-{stream}' - - 'opnfvdocs-daily-{stream}' stream: - master: @@ -109,31 +108,3 @@ builders: - check-bash-syntax - -- job-template: - name: 'opnfvdocs-daily-{stream}' - - disabled: true - - parameters: - - project-parameter: - project: '{project}' - branch: '{branch}' - - string: - name: GS_URL - default: '$GS_BASE{gs-pathname}' - description: "Directory where the build artifact will be located upon the completion of the build." - - string: - name: GIT_CLONE_BASE - default: ssh://gerrit.opnfv.org:29418 - description: "Used for overriding the GIT URL coming from parameters macro." - - scm: - - git-scm - - triggers: - - timed: '0 H/6 * * *' - - builders: - - build-html-and-pdf-docs-output -# - upload-generated-docs-to-opnfv-artifacts diff --git a/jjb/ovn4nfv/ovn4nfv-project-jobs.yml b/jjb/ovn4nfv/ovn4nfv-project-jobs.yml index b5e078ca6..97d1baefd 100644 --- a/jjb/ovn4nfv/ovn4nfv-project-jobs.yml +++ b/jjb/ovn4nfv/ovn4nfv-project-jobs.yml @@ -4,7 +4,6 @@ project: '{name}' - stream: - master: branch: '{stream}' @@ -33,10 +32,11 @@ max-per-node: 1 option: 'project' - parametert: + parameters: - project-parameter: project: '{project}' branch: '{branch}' + - opnfv-build-defaults scm: - git-scm diff --git a/jjb/pharos/check-jinja2.yml b/jjb/pharos/check-jinja2.yml new file mode 100644 index 000000000..cfc123e4c --- /dev/null +++ b/jjb/pharos/check-jinja2.yml @@ -0,0 +1,85 @@ +--- +######################## +# Job configuration to validate jinja2 files +######################## +- project: + + name: validate-pdf-templates + + project: 'pharos' + + jobs: + - 'validate-pdf-jinja2-templates-{stream}' + + stream: + - master: + branch: '{stream}' + disabled: false + - euphrates: + branch: 'stable/{stream}' + disabled: false + +######################## +# job templates +######################## + +- job-template: + name: 'validate-pdf-jinja2-templates-{stream}' + + disabled: '{obj:disabled}' + + concurrent: true + + parameters: + - project-parameter: + project: $GERRIT_PROJECT + branch: '{branch}' + - node: + name: SLAVE_NAME + description: Slave to execute jnija template test + default-slaves: + - lf-build1 + allowed-multiselect: true + ignore-offline-nodes: true + + scm: + - git-scm-gerrit + + triggers: + - gerrit: + server-name: 'gerrit.opnfv.org' + trigger-on: + - patchset-created-event: + exclude-drafts: 'false' + exclude-trivial-rebase: 'false' + exclude-no-code-change: 'false' + - draft-published-event + - comment-added-contains-event: + comment-contains-value: 'recheck' + - comment-added-contains-event: + comment-contains-value: 'reverify' + projects: + - project-compare-type: 'REG_EXP' + project-pattern: '{project}' + branches: + - branch-compare-type: 'ANT' + branch-pattern: '**/{branch}' + file-paths: + - compare-type: ANT + pattern: '**/*.yaml' + - compare-type: ANT + pattern: 'check-jinja2.sh' + skip-vote: + successful: true + failed: true + unstable: true + notbuilt: true + + builders: + - check-pdf-jinja + +- builder: + name: check-pdf-jinja + builders: + - shell: | + $WORKSPACE/config/utils/check-jinja2.sh diff --git a/jjb/qtip/qtip-experimental-jobs.yml b/jjb/qtip/qtip-experimental-jobs.yml index fdfed2601..103069fb7 100644 --- a/jjb/qtip/qtip-experimental-jobs.yml +++ b/jjb/qtip/qtip-experimental-jobs.yml @@ -7,7 +7,7 @@ name: qtip-experimental-jobs project: qtip jobs: - - 'qtip-experimental-{stream}' + - 'qtip-experimental-{pod}-{stream}' stream: - master: branch: '{stream}' @@ -18,12 +18,17 @@ gs-pathname: '/{stream}' disabled: false + pod: + - zte-virtual6: + installer: fuel + pod: zte-virtual6 + ################################ ## job templates ################################# - job-template: - name: 'qtip-experimental-{stream}' + name: 'qtip-experimental-{pod}-{stream}' disabled: '{obj:disabled}' @@ -31,9 +36,8 @@ - project-parameter: project: '{project}' branch: '{branch}' - # Pin the tests on zte-pod4 with apex deployment - - apex-defaults - - zte-virtual5-defaults + - '{installer}-defaults' + - '{pod}-defaults' scm: - git-scm-gerrit diff --git a/jjb/qtip/qtip-validate-jobs.yml b/jjb/qtip/qtip-validate-jobs.yml index febe28619..d9d3e72e6 100644 --- a/jjb/qtip/qtip-validate-jobs.yml +++ b/jjb/qtip/qtip-validate-jobs.yml @@ -40,18 +40,22 @@ installer: apex pod: zte-virtual5 <<: *euphrates + - compute: + installer: fuel + pod: zte-virtual6 + <<: *master # ------------------------------- # JOB LIST # ------------------------------- jobs: - - 'qtip-{qpi}-{installer}-{stream}' + - 'qtip-{qpi}-{installer}-{pod}-{stream}' ################################ # job templates ################################ - job-template: - name: 'qtip-{qpi}-{installer}-{stream}' + name: 'qtip-{qpi}-{installer}-{pod}-{stream}' disabled: false parameters: @@ -85,7 +89,7 @@ wrappers: - timeout: - timeout: 15 + timeout: 30 abort: true - timestamps diff --git a/jjb/releng/automate.yml b/jjb/releng/automate.yml index de7fcd6c0..afeb35821 100644 --- a/jjb/releng/automate.yml +++ b/jjb/releng/automate.yml @@ -19,7 +19,7 @@ - '{module}-automate-{phase}-{stream}' - '{module}-verify-{stream}' - project: 'releng' + project: 'releng-testresults' - job: name: 'testapi-mongodb-backup' @@ -30,11 +30,11 @@ default: 'testresults' description: 'Slave label on Jenkins' - project-parameter: - project: 'releng' + project: 'releng-testresults' branch: 'master' - string: name: GIT_BASE - default: https://gerrit.opnfv.org/gerrit/releng + default: https://gerrit.opnfv.org/gerrit/releng-testresults description: 'Git URL to use on this Jenkins Slave' scm: @@ -79,11 +79,11 @@ branch-pattern: '**/{branch}' file-paths: - compare-type: 'ANT' - pattern: 'utils/test/{module}/**' + pattern: '{module}/**' builders: - shell: | - cd ./utils/test/{module}/ + cd {module}/ tox if [ -e *.xml ];then cp *.xml $WORKSPACE @@ -143,7 +143,7 @@ branch-pattern: '**/{branch}' file-paths: - compare-type: 'ANT' - pattern: 'utils/test/{module}/**' + pattern: '{module}/**' builders: - description-setter: @@ -208,8 +208,8 @@ - builder: name: 'docker-update' builders: - - shell: - !include-raw: ./docker-update.sh + - shell: | + bash ./ci/docker-update.sh - builder: name: 'testapi-automate-generate-doc-macro' @@ -221,13 +221,13 @@ name: 'testapi-doc-build' builders: - shell: | - bash ./jjb/releng/htmlize/doc-build.sh + bash ./ci/htmlize/doc-build.sh - builder: name: 'upload-doc-artifact' builders: - shell: | - bash ./jjb/releng/htmlize/push-doc-artifact.sh + bash ./ci/htmlize/push-doc-artifacts.sh - builder: name: 'reporting-automate-generate-doc-macro' @@ -238,7 +238,7 @@ name: 'testapi-automate-docker-deploy-macro' builders: - shell: | - sudo bash ./jjb/releng/docker-deploy.sh "sudo docker run -dti --name testapi -p 8082:8000 + sudo bash ./ci/docker-deploy.sh "sudo docker run -dti --name testapi -p 8082:8000 -e mongodb_url=mongodb://172.17.0.1:27017 -e base_url=http://testresults.opnfv.org/test opnfv/testapi" \ "http://testresults.opnfv.org/test/" "testapi" @@ -247,14 +247,15 @@ name: 'reporting-automate-docker-deploy-macro' builders: - shell: | - sudo bash ./jjb/releng/docker-deploy.sh "sudo docker run -itd --name reporting -p 8084:8000 opnfv/reporting" \ + sudo bash ./ci/docker-deploy.sh \ + "sudo docker run -itd --name reporting -p 8084:8000 opnfv/reporting" \ "http://testresults.opnfv.org/reporting/index.html" "reporting" - builder: name: mongodb-backup builders: - - shell: | - bash ./jjb/releng/testapi-backup-mongodb.sh + - shell: + bash ./ci/testapi-backup-mongodb.sh ################################ # job publishers diff --git a/jjb/releng/compass4nfv-docker.yml b/jjb/releng/compass4nfv-docker.yml new file mode 100644 index 000000000..299908d66 --- /dev/null +++ b/jjb/releng/compass4nfv-docker.yml @@ -0,0 +1,177 @@ +--- +############################################## +# job configuration for docker build and push +############################################## +- project: + + name: compass-docker + + project: compass-containers + + stream: + - master: + branch: '{stream}' + disabled: false + - euphrates: + branch: 'stable/{stream}' + disabled: true + + arch_tag: + - 'amd64': + slave_label: 'opnfv-build-ubuntu' + + # yamllint disable rule:key-duplicates + image: + - 'tasks' + - 'cobbler' + - 'db' + - 'deck' + - 'tasks-k8s' + - 'tasks-osa' + + # settings for jobs run in multijob phases + build-job-settings: &build-job-settings + current-parameters: false + git-revision: true + node-parameters: false + predefined-parameters: | + PUSH_IMAGE=$PUSH_IMAGE + COMMIT_ID=$COMMIT_ID + RELEASE_VERSION=$RELEASE_VERSION + DOCKERFILE=$DOCKERFILE + kill-phase-on: FAILURE + abort-all-jobs: false + + # yamllint enable rule:key-duplicates + jobs: + - "compass-docker-{stream}" + - "compass-{image}-build-{arch_tag}-{stream}" + +######################## +# job templates +######################## +- job-template: + name: 'compass-docker-{stream}' + + project-type: multijob + + disabled: '{obj:disabled}' + + parameters: + - compass-job-parameters: + project: '{project}' + branch: '{branch}' + slave_label: 'opnfv-build-ubuntu' + arch_tag: 'amd64' + + properties: + - throttle: + max-per-node: 1 + option: 'project' + + scm: + - git-scm + + triggers: + - pollscm: + cron: "*/30 * * * *" + + builders: + - multijob: + name: 'build compass-tasks images' + execution-type: PARALLEL + projects: + - name: 'compass-tasks-build-amd64-{stream}' + <<: *build-job-settings + - multijob: + name: 'build all compass images' + condition: SUCCESSFUL + execution-type: PARALLEL + projects: + - name: 'compass-cobbler-build-amd64-{stream}' + <<: *build-job-settings + - name: 'compass-db-build-amd64-{stream}' + <<: *build-job-settings + - name: 'compass-deck-build-amd64-{stream}' + <<: *build-job-settings + - name: 'compass-tasks-k8s-build-amd64-{stream}' + <<: *build-job-settings + - name: 'compass-tasks-osa-build-amd64-{stream}' + <<: *build-job-settings + + publishers: + - 'compass-amd64-recipients' + +- job-template: + name: 'compass-{image}-build-{arch_tag}-{stream}' + disabled: '{obj:disabled}' + parameters: + - compass-job-parameters: + project: '{project}' + branch: '{branch}' + slave_label: '{slave_label}' + arch_tag: '{arch_tag}' + - string: + name: DOCKER_REPO_NAME + default: "opnfv/compass-{image}" + description: "Dockerhub repo to be pushed to." + - string: + name: DOCKER_DIR + default: "compass-{image}" + description: "Directory containing files needed by the Dockerfile" + scm: + - git-scm + builders: + - shell: + !include-raw-escape: ./opnfv-docker.sh + +# parameter macro +- parameter: + name: compass-job-parameters + parameters: + - project-parameter: + project: '{project}' + branch: '{branch}' + - label: + name: SLAVE_LABEL + default: '{slave_label}' + description: 'Slave label on Jenkins' + - string: + name: GIT_BASE + default: https://gerrit.opnfv.org/gerrit/$PROJECT + description: 'Git URL to use on this Jenkins Slave' + - string: + name: PUSH_IMAGE + default: "true" + description: "To enable/disable pushing the image to Dockerhub." + - string: + name: COMMIT_ID + default: "" + description: "commit id to make a snapshot docker image" + - string: + name: RELEASE_VERSION + default: "" + description: "Docker tag to be built, e.g. 5.0.0, opnfv-5.0.0, 5.0.RC1" + - string: + name: DOCKERFILE + default: "Dockerfile" + description: "Dockerfile to use for creating the image." + - string: + name: ARCH_TAG + default: "" + description: "If set, this value will be added to the docker image tag as a prefix" + - string: + name: PROJECT + default: "{project}" + description: "Project name used to enable job conditions" + +# publisher macros +- publisher: + name: 'compass-amd64-recipients' + publishers: + - email: + recipients: > + chigang@huawei.com + huangxiangyui5@huawei.com + xueyifei@huawei.com + wutianwei1@huawei.com diff --git a/jjb/releng/docker-deploy.sh b/jjb/releng/docker-deploy.sh deleted file mode 100644 index 1e8357717..000000000 --- a/jjb/releng/docker-deploy.sh +++ /dev/null @@ -1,152 +0,0 @@ -#!/bin/bash -# Licensed to the Apache Software Foundation (ASF) under one * -# or more contributor license agreements. See the NOTICE file * -# distributed with this work for additional information * -# regarding copyright ownership. The ASF licenses this file * -# to you 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. * - - -command=$1 -url=$2 -module=$3 - -REPO="opnfv" -latest_image=$REPO/$module:latest -old_image=$REPO/$module:old -latest_container_name=$module -old_container_name=$module"_old" -latest_container_id= -old_container_id= -new_start_container= - -function DEBUG() { - echo `date "+%Y-%m-%d %H:%M:%S.%N"` ": $1" -} - -function check_connectivity() { - # check update status via test the connectivity of provide url - sleep 5 - cmd=`curl -s --head --request GET ${url} | grep '200 OK' > /dev/null` - rc=$? - DEBUG $rc - if [[ $rc == 0 ]]; then - return 0 - else - return 1 - fi -} - - -function pull_latest_image() { - DEBUG "pull latest image $latest_image" - docker pull $latest_image -} - -function get_latest_running_container() { - latest_container_id=`docker ps -q --filter name=^/$latest_container_name$` -} - -function get_old_running_container() { - old_container_id=`docker ps -q --filter name=^/$old_container_name$` -} - -function delete_old_image() { - DEBUG "delete old image: $old_image" - docker rmi -f $old_image -} - -function delete_old_container() { - DEBUG "delete old container: $old_container_name" - docker ps -a -q --filter name=^/$old_container_name$ | xargs docker rm -f &>/dev/null -} - -function delete_latest_container() { - DEBUG "delete latest container: $module" - docker ps -a -q --filter name=^/$latest_container_name$ | xargs docker rm -f &>/dev/null -} - -function delete_latest_image() { - DEBUG "delete latest image: $REPO/$module:latest" - docker rmi -f $latest_image -} - -function change_image_tag_2_old() { - DEBUG "change image tag 2 old" - docker tag $latest_image $old_image - docker rmi -f $latest_image -} - -function mark_latest_container_2_old() { - DEBUG "mark latest container to be old" - docker rename "$latest_container_name" "$old_container_name" -} - -function stop_old_container() { - DEBUG "stop old container" - docker stop "$old_container_name" -} - -function run_latest_image() { - new_start_container=`$command` - DEBUG "run latest image: $new_start_container" -} - -get_latest_running_container -get_old_running_container - -if [[ ! -z $latest_container_id ]]; then - DEBUG "latest container is running: $latest_container_id" - delete_old_container - delete_old_image - change_image_tag_2_old - mark_latest_container_2_old - pull_latest_image - stop_old_container - run_latest_image - -elif [[ ! -z $old_container_id ]]; then - DEBUG "old container is running: $old_container_id" - delete_latest_container - delete_latest_image - pull_latest_image - stop_old_container - run_latest_image -else - DEBUG "no container is running" - delete_old_container - delete_old_image - delete_latest_container - delete_latest_image - pull_latest_image - run_latest_image -fi - -if check_connectivity; then - DEBUG "CONGRATS: $module update successfully" -else - DEBUG "ATTENTION: $module update failed" - id=`docker ps -a -q --filter name=^/$old_container_name$` - if [[ ! -z $id ]]; then - DEBUG "start old container instead" - docker stop $new_start_container - docker start $id - fi - if ! check_connectivity; then - DEBUG "BIG ISSUE: no container is running normally" - fi - exit 1 -fi - -docker images -docker ps -a diff --git a/jjb/releng/docker-update.sh b/jjb/releng/docker-update.sh deleted file mode 100644 index 559ac835c..000000000 --- a/jjb/releng/docker-update.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -# Licensed to the Apache Software Foundation (ASF) under one * -# or more contributor license agreements. See the NOTICE file * -# distributed with this work for additional information * -# regarding copyright ownership. The ASF licenses this file * -# to you 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. * - -set -o errexit -set -o nounset - -cd $WORKSPACE/utils/test/$MODULE_NAME/docker/ - -# Remove previous containers -docker ps -a | grep "opnfv/$MODULE_NAME" | awk '{ print $1 }' | xargs -r docker rm -f - -# Remove previous images -docker images | grep "opnfv/$MODULE_NAME" | awk '{ print $3 }' | xargs -r docker rmi -f - -# Start build -docker build --no-cache -t opnfv/$MODULE_NAME:$DOCKER_TAG . - -# Push Image -docker push opnfv/$MODULE_NAME:$DOCKER_TAG diff --git a/jjb/releng/functest-docker.yml b/jjb/releng/functest-docker.yml new file mode 100644 index 000000000..acf381f88 --- /dev/null +++ b/jjb/releng/functest-docker.yml @@ -0,0 +1,289 @@ +--- +############################################## +# job configuration for docker build and push +############################################## +- project: + + name: functest-docker + + project: functest + + stream: + - master: + branch: '{stream}' + disabled: false + - euphrates: + branch: 'stable/{stream}' + disabled: false + + arch_tag: + - 'amd64': + slave_label: 'opnfv-build-ubuntu' + - 'arm64': + slave_label: 'opnfv-build-ubuntu-arm' + + # yamllint disable rule:key-duplicates + image: + - 'core' + - 'healthcheck' + - 'features' + - 'components' + - 'parser' + - 'smoke' + - 'vnf' + - 'restapi' + + # settings for jobs run in multijob phases + build-job-settings: &build-job-settings + current-parameters: false + git-revision: true + node-parameters: false + predefined-parameters: | + PUSH_IMAGE=$PUSH_IMAGE + COMMIT_ID=$COMMIT_ID + RELEASE_VERSION=$RELEASE_VERSION + DOCKERFILE=$DOCKERFILE + kill-phase-on: FAILURE + abort-all-jobs: false + + manifest-job-settings: &manifest-job-settings + current-parameters: false + git-revision: true + node-parameters: false + predefined-parameters: + RELEASE_VERSION=$RELEASE_VERSION + kill-phase-on: FAILURE + abort-all-jobs: false + + # yamllint enable rule:key-duplicates + jobs: + - "functest-docker-{stream}" + - "functest-{image}-build-{arch_tag}-{stream}" + - "functest-{image}-manifest-{stream}" + +######################## +# job templates +######################## +- job-template: + name: 'functest-docker-{stream}' + + project-type: multijob + + disabled: '{obj:disabled}' + + parameters: + - job-parameters: + project: '{project}' + branch: '{branch}' + slave_label: 'opnfv-build-ubuntu' + arch_tag: 'amd64' + + properties: + - throttle: + max-per-node: 1 + option: 'project' + + scm: + - git-scm + + triggers: + - pollscm: + cron: "*/30 * * * *" + + builders: + - multijob: + name: 'build functest-core images' + execution-type: PARALLEL + projects: + - name: 'functest-core-build-amd64-{stream}' + <<: *build-job-settings + - name: 'functest-core-build-arm64-{stream}' + <<: *build-job-settings + - multijob: + name: 'publish functest-core manifests' + execution-type: PARALLEL + projects: + - name: 'functest-core-manifest-{stream}' + <<: *manifest-job-settings + - multijob: + name: 'build all functest images' + condition: SUCCESSFUL + execution-type: PARALLEL + projects: + - name: 'functest-healthcheck-build-amd64-{stream}' + <<: *build-job-settings + - name: 'functest-healthcheck-build-arm64-{stream}' + <<: *build-job-settings + - name: 'functest-features-build-amd64-{stream}' + <<: *build-job-settings + - name: 'functest-features-build-arm64-{stream}' + <<: *build-job-settings + - name: 'functest-components-build-amd64-{stream}' + <<: *build-job-settings + - name: 'functest-components-build-arm64-{stream}' + <<: *build-job-settings + - name: 'functest-parser-build-amd64-{stream}' + <<: *build-job-settings + - name: 'functest-parser-build-arm64-{stream}' + <<: *build-job-settings + - name: 'functest-smoke-build-amd64-{stream}' + <<: *build-job-settings + - name: 'functest-smoke-build-arm64-{stream}' + <<: *build-job-settings + - name: 'functest-vnf-build-amd64-{stream}' + <<: *build-job-settings + - name: 'functest-restapi-build-amd64-{stream}' + <<: *build-job-settings + - multijob: + name: 'publish all manifests' + condition: SUCCESSFUL + execution-type: PARALLEL + projects: + - name: 'functest-healthcheck-manifest-{stream}' + <<: *manifest-job-settings + - name: 'functest-features-manifest-{stream}' + <<: *manifest-job-settings + - name: 'functest-components-manifest-{stream}' + <<: *manifest-job-settings + - name: 'functest-parser-manifest-{stream}' + <<: *manifest-job-settings + - name: 'functest-smoke-manifest-{stream}' + <<: *manifest-job-settings + - name: 'functest-vnf-manifest-{stream}' + <<: *manifest-job-settings + - name: 'functest-restapi-manifest-{stream}' + <<: *manifest-job-settings + + publishers: + - 'functest-amd64-recipients' + - 'functest-arm64-recipients' + +- job-template: + name: 'functest-{image}-build-{arch_tag}-{stream}' + disabled: '{obj:disabled}' + parameters: + - job-parameters: + project: '{project}' + branch: '{branch}' + slave_label: '{slave_label}' + arch_tag: '{arch_tag}' + scm: + - git-scm + builders: + - shell: | + #!/bin/bash -ex + case "{arch_tag}" in + "arm64") + sudo amd64_dirs= arm64_dirs=docker/{image} bash ./build.sh ;; + *) + sudo amd64_dirs=docker/{image} arm64_dirs= bash ./build.sh ;; + esac + exit $? + +- job-template: + name: 'functest-{image}-manifest-{stream}' + + parameters: + - project-parameter: + project: '{project}' + branch: '{branch}' + - label: + name: SLAVE_LABEL + default: 'opnfv-build-ubuntu' + description: 'Slave label on Jenkins' + - string: + name: PROJECT + default: "{project}" + description: "Project name used to enable job conditions" + - string: + name: RELEASE_VERSION + default: "" + description: "Docker tag to be built, e.g. 5.0.0, opnfv-5.0.0, 5.0.RC1" + - string: + name: GIT_BASE + default: https://gerrit.opnfv.org/gerrit/$PROJECT + description: 'Git URL to use on this Jenkins Slave' + + disabled: '{obj:disabled}' + + builders: + - shell: | + #!/bin/bash -ex + case "{stream}" in + "master") + tag="latest" ;; + *) + tag="{stream}" ;; + esac + case "{image}" in + "vnf"|"restapi") + sudo manifest-tool push from-args \ + --platforms linux/amd64 \ + --template opnfv/functest-{image}:ARCH-$tag \ + --target opnfv/functest-{image}:$tag ;; + *) + sudo manifest-tool push from-args \ + --platforms linux/amd64,linux/arm64 \ + --template opnfv/functest-{image}:ARCH-$tag \ + --target opnfv/functest-{image}:$tag ;; + esac + exit $? + +# parameter macro +- parameter: + name: job-parameters + parameters: + - project-parameter: + project: '{project}' + branch: '{branch}' + - label: + name: SLAVE_LABEL + default: '{slave_label}' + description: 'Slave label on Jenkins' + - string: + name: GIT_BASE + default: https://gerrit.opnfv.org/gerrit/$PROJECT + description: 'Git URL to use on this Jenkins Slave' + - string: + name: PUSH_IMAGE + default: "true" + description: "To enable/disable pushing the image to Dockerhub." + - string: + name: COMMIT_ID + default: "" + description: "commit id to make a snapshot docker image" + - string: + name: RELEASE_VERSION + default: "" + description: "Docker tag to be built, e.g. 5.0.0, opnfv-5.0.0, 5.0.RC1" + - string: + name: DOCKERFILE + default: "Dockerfile" + description: "Dockerfile to use for creating the image." + - string: + name: ARCH_TAG + default: "{arch_tag}" + description: "If set, this value will be added to the docker image tag as a prefix" + - string: + name: PROJECT + default: "{project}" + description: "Project name used to enable job conditions" + +# publisher macros +- publisher: + name: 'functest-arm64-recipients' + publishers: + - email: + recipients: > + cristina.pauna@enea.com + alexandru.avadanii@enea.com + delia.popescu@enea.com + +- publisher: + name: 'functest-amd64-recipients' + publishers: + - email: + recipients: > + jalausuch@suse.com morgan.richomme@orange.com + cedric.ollivier@orange.com feng.xiaowei@zte.com.cn + juha.kosonen@nokia.com wangwulin@huawei.com diff --git a/jjb/releng/htmlize/doc-build.sh b/jjb/releng/htmlize/doc-build.sh deleted file mode 100644 index b89baa8e6..000000000 --- a/jjb/releng/htmlize/doc-build.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -# Licensed to the Apache Software Foundation (ASF) under one * -# or more contributor license agreements. See the NOTICE file * -# distributed with this work for additional information * -# regarding copyright ownership. The ASF licenses this file * -# to you 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. * - -set -o errexit - -# Create virtual environment -virtualenv $WORKSPACE/testapi_venv -source $WORKSPACE/testapi_venv/bin/activate - -# Swgger Codegen Tool -url="http://repo1.maven.org/maven2/io/swagger/swagger-codegen-cli/2.2.1/swagger-codegen-cli-2.2.1.jar" - -# Check for jar file locally and in the repo -if [ ! -f swagger-codegen-cli.jar ]; -then - wget http://repo1.maven.org/maven2/io/swagger/swagger-codegen-cli/2.2.1/swagger-codegen-cli-2.2.1.jar -O swagger-codegen-cli.jar -fi - -# Install Pre-requistics -pip install requests - -python ./jjb/releng/htmlize/htmlize.py -o ${WORKSPACE}/ diff --git a/jjb/releng/htmlize/htmlize.py b/jjb/releng/htmlize/htmlize.py deleted file mode 100644 index da6a6cf91..000000000 --- a/jjb/releng/htmlize/htmlize.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python - -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 - -import argparse -import requests -import json -import os - - -def main(args): - - # Merging two specs - api_response = requests.get(args.api_declaration_url) - api_response = json.loads(api_response.content) - resource_response = requests.get(args.resource_listing_url) - resource_response = json.loads(resource_response.content) - resource_response['models'] = api_response['models'] - resource_response['apis'] = api_response['apis'] - - # Storing the swagger specs - with open('specs.json', 'w') as outfile: - json.dump(resource_response, outfile) - - # Generating html page - cmd = 'java -jar swagger-codegen-cli.jar generate \ - -i specs.json -l html2 -o %s' % (args.output_directory) - if os.system(cmd) == 0: - exit(0) - else: - exit(1) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Create \ - Swagger Spec documentation') - parser.add_argument('-ru', '--resource-listing-url', - type=str, - required=False, - default=('http://testresults.opnfv.org' - '/test/swagger/resources.json'), - help='Resource Listing Spec File') - parser.add_argument('-au', '--api-declaration-url', - type=str, - required=False, - default=('http://testresults.opnfv.org' - '/test/swagger/APIs'), - help='API Declaration Spec File') - parser.add_argument('-o', '--output-directory', - required=True, - default='./', - help='Output Directory where the \ - file should be stored') - main(parser.parse_args()) diff --git a/jjb/releng/htmlize/push-doc-artifact.sh b/jjb/releng/htmlize/push-doc-artifact.sh deleted file mode 100644 index 4cf1988b0..000000000 --- a/jjb/releng/htmlize/push-doc-artifact.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -export PATH=$PATH:/usr/local/bin/ - -project=$PROJECT -workspace=$WORKSPACE -artifact_dir="$project/docs" - -set +e -gsutil&>/dev/null -if [ $? != 0 ]; then - echo "Not possible to push results to artifact: gsutil not installed" - exit 1 -else - gsutil ls gs://artifacts.opnfv.org/"$project"/ &>/dev/null - if [ $? != 0 ]; then - echo "Not possible to push results to artifact: gsutil not installed." - exit 1 - else - echo "Uploading document to artifact $artifact_dir" - gsutil cp "$workspace"/index.html gs://artifacts.opnfv.org/"$artifact_dir"/testapi.html >/dev/null 2>&1 - echo "Document can be found at http://artifacts.opnfv.org/releng/docs/testapi.html" - fi -fi diff --git a/jjb/releng/opnfv-docker-arm.yml b/jjb/releng/opnfv-docker-arm.yml index b488592db..d1566b48d 100644 --- a/jjb/releng/opnfv-docker-arm.yml +++ b/jjb/releng/opnfv-docker-arm.yml @@ -15,11 +15,6 @@ stream: euphrates branch: 'stable/{stream}' disabled: false - functest-arm-receivers: &functest-arm-receivers - receivers: > - cristina.pauna@enea.com - alexandru.avadanii@enea.com - delia.popescu@enea.com dovetail-arm-receivers: &dovetail-arm-receivers receivers: > cristina.pauna@enea.com @@ -40,7 +35,7 @@ other-receivers: &other-receivers receivers: '' - dockerfile: "Dockerfile.aarch64" + dockerfile: "Dockerfile" dockerdir: "docker" docker_repo_name: "opnfv/{project}_aarch64" arch_tag: "" @@ -48,10 +43,6 @@ # yamllint disable rule:key-duplicates dockerrepo: # projects with jobs for master - - 'functest': - project: 'functest' - <<: *master - <<: *functest-arm-receivers - 'dovetail': project: 'dovetail' <<: *master @@ -59,7 +50,6 @@ - 'storperf-master': project: 'storperf' dockerdir: 'docker/storperf-master' - dockerfile: 'Dockerfile' docker_repo_name: 'opnfv/storperf-master' arch_tag: 'aarch64' <<: *master @@ -67,7 +57,6 @@ - 'storperf-graphite': project: 'storperf' dockerdir: 'docker/storperf-graphite' - dockerfile: 'Dockerfile' docker_repo_name: 'opnfv/storperf-graphite' arch_tag: 'aarch64' <<: *master @@ -75,7 +64,6 @@ - 'storperf-httpfrontend': project: 'storperf' dockerdir: 'docker/storperf-httpfrontend' - dockerfile: 'Dockerfile' docker_repo_name: 'opnfv/storperf-httpfrontend' arch_tag: 'aarch64' <<: *master @@ -83,7 +71,6 @@ - 'storperf-reporting': project: 'storperf' dockerdir: 'docker/storperf-reporting' - dockerfile: 'Dockerfile' docker_repo_name: 'opnfv/storperf-reporting' arch_tag: 'aarch64' <<: *master @@ -91,7 +78,6 @@ - 'storperf-swaggerui': project: 'storperf' dockerdir: 'docker/storperf-swaggerui' - dockerfile: 'Dockerfile' docker_repo_name: 'opnfv/storperf-swaggerui' arch_tag: 'aarch64' <<: *master @@ -101,10 +87,6 @@ <<: *master <<: *yardstick-arm-receivers # projects with jobs for stable/euphrates - - 'functest': - project: 'functest' - <<: *euphrates - <<: *functest-arm-receivers - 'dovetail': project: 'dovetail' <<: *euphrates @@ -112,7 +94,6 @@ - 'storperf-master': project: 'storperf' dockerdir: 'docker/storperf-master' - dockerfile: 'Dockerfile' docker_repo_name: 'opnfv/storperf-master' arch_tag: 'aarch64' <<: *euphrates @@ -120,7 +101,6 @@ - 'storperf-graphite': project: 'storperf' dockerdir: 'docker/storperf-graphite' - dockerfile: 'Dockerfile' docker_repo_name: 'opnfv/storperf-graphite' arch_tag: 'aarch64' <<: *euphrates @@ -128,7 +108,6 @@ - 'storperf-httpfrontend': project: 'storperf' dockerdir: 'docker/storperf-httpfrontend' - dockerfile: 'Dockerfile' docker_repo_name: 'opnfv/storperf-httpfrontend' arch_tag: 'aarch64' <<: *euphrates @@ -136,7 +115,6 @@ - 'storperf-reporting': project: 'storperf' dockerdir: 'docker/storperf-reporting' - dockerfile: 'Dockerfile' docker_repo_name: 'opnfv/storperf-reporting' arch_tag: 'aarch64' <<: *euphrates @@ -144,7 +122,6 @@ - 'storperf-swaggerui': project: 'storperf' dockerdir: 'docker/storperf-swaggerui' - dockerfile: 'Dockerfile' docker_repo_name: 'opnfv/storperf-swaggerui' arch_tag: 'aarch64' <<: *euphrates diff --git a/jjb/releng/opnfv-docker.sh b/jjb/releng/opnfv-docker.sh index 402099a91..ec7b3fda3 100644 --- a/jjb/releng/opnfv-docker.sh +++ b/jjb/releng/opnfv-docker.sh @@ -17,6 +17,36 @@ echo "Starting opnfv-docker for $DOCKER_REPO_NAME ..." echo "--------------------------------------------------------" echo +function remove_containers_images() +{ + # Remove previous running containers if exist + if [[ -n "$(docker ps -a | grep $DOCKER_REPO_NAME)" ]]; then + echo "Removing existing $DOCKER_REPO_NAME containers..." + docker ps -a | grep $DOCKER_REPO_NAME | awk '{print $1}' | xargs docker rm -f + t=60 + # Wait max 60 sec for containers to be removed + while [[ $t -gt 0 ]] && [[ -n "$(docker ps| grep $DOCKER_REPO_NAME)" ]]; do + sleep 1 + let t=t-1 + done + fi + + + # Remove existing images if exist + if [[ -n "$(docker images | grep $DOCKER_REPO_NAME)" ]]; then + echo "Docker images to remove:" + docker images | head -1 && docker images | grep $DOCKER_REPO_NAME + image_ids=($(docker images | grep $DOCKER_REPO_NAME | awk '{print $3}')) + for id in "${image_ids[@]}"; do + if [[ -n "$(docker images|grep $DOCKER_REPO_NAME|grep $id)" ]]; then + echo "Removing docker image $DOCKER_REPO_NAME:$id..." + docker rmi -f $id + fi + done + fi +} + + count=30 # docker build jobs might take up to ~30 min while [[ -n `ps -ef| grep 'docker build' | grep $DOCKER_REPO_NAME | grep -v grep` ]]; do echo "Build or cleanup of $DOCKER_REPO_NAME in progress. Waiting..." @@ -28,46 +58,16 @@ while [[ -n `ps -ef| grep 'docker build' | grep $DOCKER_REPO_NAME | grep -v grep fi done -# Remove previous running containers if exist -if [[ -n "$(docker ps -a | grep $DOCKER_REPO_NAME)" ]]; then - echo "Removing existing $DOCKER_REPO_NAME containers..." - docker ps -a | grep $DOCKER_REPO_NAME | awk '{print $1}' | xargs docker rm -f - t=60 - # Wait max 60 sec for containers to be removed - while [[ $t -gt 0 ]] && [[ -n "$(docker ps| grep $DOCKER_REPO_NAME)" ]]; do - sleep 1 - let t=t-1 - done -fi - +# Remove the existing containers and images before building +remove_containers_images -# Remove existing images if exist -if [[ -n "$(docker images | grep $DOCKER_REPO_NAME)" ]]; then - echo "Docker images to remove:" - docker images | head -1 && docker images | grep $DOCKER_REPO_NAME - image_ids=($(docker images | grep $DOCKER_REPO_NAME | awk '{print $3}')) - for id in "${image_ids[@]}"; do - if [[ -n "$(docker images|grep $DOCKER_REPO_NAME|grep $id)" ]]; then - echo "Removing docker image $DOCKER_REPO_NAME:$id..." - docker rmi -f $id - fi - done -fi - -cd $WORKSPACE/$DOCKER_DIR -HOST_ARCH=$(uname -m) -if [ ! -f "${DOCKERFILE}" ]; then - # If this is expected to be a Dockerfile for other arch than x86 - # and it does not exist, but there is a patch for the said arch, - # then apply the patch and create the Dockerfile.${HOST_ARCH} file - if [[ "${DOCKERFILE}" == *"${HOST_ARCH}" && \ - -f "Dockerfile.${HOST_ARCH}.patch" ]]; then - patch -o Dockerfile."${HOST_ARCH}" Dockerfile \ - Dockerfile."${HOST_ARCH}".patch - else - echo "ERROR: No Dockerfile or ${HOST_ARCH} patch found." - exit 1 - fi +cd "$WORKSPACE/$DOCKER_DIR" || exit 1 +HOST_ARCH="$(uname -m)" +#If there is a patch for other arch then x86, apply the patch and +#replace Dockerfile file +dockerfile_patch="Dockerfile.${HOST_ARCH}.patch" +if [[ -f "${dockerfile_patch}" ]]; then + patch -f Dockerfile -p1 < "${dockerfile_patch}" fi # Get tag version @@ -107,7 +107,6 @@ echo "Building docker image: $DOCKER_REPO_NAME:$DOCKER_TAG" echo "--------------------------------------------------------" echo cmd="docker build --no-cache -t $DOCKER_REPO_NAME:$DOCKER_TAG --build-arg BRANCH=$BUILD_BRANCH - $ARCH_BUILD_ARG -f $DOCKERFILE ." echo ${cmd} @@ -125,3 +124,6 @@ if [[ "$PUSH_IMAGE" == "true" ]]; then echo docker push $DOCKER_REPO_NAME:$DOCKER_TAG fi + +# Remove the existing containers and images after building +remove_containers_images diff --git a/jjb/releng/opnfv-docker.yml b/jjb/releng/opnfv-docker.yml index 862e77ac8..1a2756218 100644 --- a/jjb/releng/opnfv-docker.yml +++ b/jjb/releng/opnfv-docker.yml @@ -19,11 +19,6 @@ stream: euphrates branch: 'stable/{stream}' disabled: false - functest-receivers: &functest-receivers - receivers: > - jalausuch@suse.com morgan.richomme@orange.com - cedric.ollivier@orange.com feng.xiaowei@zte.com.cn - juha.kosonen@nokia.com wangwulin@huawei.com storperf-receivers: &storperf-receivers receivers: > mark.beierl@emc.com @@ -44,6 +39,10 @@ project: 'releng-anteater' <<: *master <<: *other-receivers + - 'barometer': + project: 'barometer' + <<: *master + <<: *other-receivers - 'bottlenecks': project: 'bottlenecks' <<: *master @@ -56,10 +55,6 @@ project: 'dovetail' <<: *master <<: *other-receivers - - 'functest': - project: 'functest' - <<: *master - <<: *functest-receivers - 'nfvbench': project: 'nfvbench' <<: *master @@ -102,24 +97,19 @@ project: 'yardstick' <<: *master <<: *other-receivers - # projects with jobs for Danube - - 'qtip': - project: 'qtip' - <<: *euphrates - <<: *other-receivers - - 'yardstick': - project: 'yardstick' - <<: *euphrates - <<: *other-receivers # projects with jobs for euphrates - 'bottlenecks': project: 'bottlenecks' <<: *euphrates <<: *other-receivers - - 'functest': - project: 'functest' + - 'nfvbench': + project: 'nfvbench' + <<: *euphrates + <<: *other-receivers + - 'qtip': + project: 'qtip' <<: *euphrates - <<: *functest-receivers + <<: *other-receivers - 'storperf-master': project: 'storperf' dockerdir: 'docker/storperf-master' @@ -150,8 +140,8 @@ arch_tag: 'x86_64' <<: *euphrates <<: *storperf-receivers - - 'nfvbench': - project: 'nfvbench' + - 'yardstick': + project: 'yardstick' <<: *euphrates <<: *other-receivers diff --git a/jjb/releng/opnfv-docs.yml b/jjb/releng/opnfv-docs.yml deleted file mode 100644 index 740274518..000000000 --- a/jjb/releng/opnfv-docs.yml +++ /dev/null @@ -1,115 +0,0 @@ ---- -######################## -# Job configuration for opnfv-docs -######################## -- project: - - name: opnfv-docs - - project: opnfv-docs - - jobs: - - 'opnfv-docs-verify-{stream}' - - 'opnfv-docs-merge-{stream}' - - stream: - - master: - branch: '{stream}' - doc-version: '' - gs-pathname: '' - disabled: false - - euphrates: - branch: 'stable/{stream}' - doc-version: '5.0.0' - gs-pathname: '/{stream}/{doc-version}' - disabled: false - -######################## -# job templates -######################## - -- job-template: - name: 'opnfv-docs-verify-{stream}' - - disabled: '{obj:disabled}' - - parameters: - - project-parameter: - project: $GERRIT_PROJECT - branch: '{branch}' - - scm: - - git-scm-gerrit - - triggers: - - gerrit: - server-name: 'gerrit.opnfv.org' - trigger-on: - - patchset-created-event: - exclude-drafts: 'false' - exclude-trivial-rebase: 'false' - exclude-no-code-change: 'false' - - draft-published-event - - comment-added-contains-event: - comment-contains-value: 'recheck' - - comment-added-contains-event: - comment-contains-value: 'reverify' - projects: - - project-compare-type: 'ANT' - project-pattern: '*' - branches: - - branch-compare-type: 'ANT' - branch-pattern: '**/{branch}' - file-paths: - - compare-type: ANT - pattern: docs/** - - compare-type: ANT - pattern: yardstick/** - - builders: - - upload-review-docs - -- job-template: - name: 'opnfv-docs-merge-{stream}' - - disabled: '{obj:disabled}' - - parameters: - - project-parameter: - project: $GERRIT_PROJECT - branch: '{branch}' - - string: - name: GS_URL - default: '$GS_BASE{gs-pathname}' - description: "Directory where the build artifact will be located upon the completion of the build." - - string: - name: GERRIT_REFSPEC - default: 'refs/heads/{branch}' - description: "JJB configured GERRIT_REFSPEC parameter" - - scm: - - git-scm - - triggers: - - gerrit: - server-name: 'gerrit.opnfv.org' - trigger-on: - - change-merged-event - - comment-added-contains-event: - comment-contains-value: 'remerge' - - comment-added-contains-event: - comment-contains-value: 'rebuild docs' - projects: - - project-compare-type: 'ANT' - project-pattern: '*' - branches: - - branch-compare-type: 'ANT' - branch-pattern: '**/{branch}' - file-paths: - - compare-type: ANT - pattern: docs/** - - compare-type: ANT - pattern: yardstick/** - - builders: - - upload-merged-docs diff --git a/jjb/releng/opnfv-repo-archiver.sh b/jjb/releng/opnfv-repo-archiver.sh index c9fdba379..2408c2a83 100644 --- a/jjb/releng/opnfv-repo-archiver.sh +++ b/jjb/releng/opnfv-repo-archiver.sh @@ -35,7 +35,7 @@ for PROJECT in "${PROJECT_LIST[@]}"; do # Don't license scan kernel or qemu in kvmfornfv if [ "$PROJECT" == "kvmfornfv" ]; then - rm -rf "$CLONE_PATH/$PROJECT/{kernel,qemu}" + rm -rf "$CLONE_PATH/$PROJECT/"{kernel,qemu} fi done diff --git a/jjb/releng/releng-ci-jobs.yml b/jjb/releng/releng-ci-jobs.yml index d4f39708e..c4b7c8db3 100644 --- a/jjb/releng/releng-ci-jobs.yml +++ b/jjb/releng/releng-ci-jobs.yml @@ -5,7 +5,6 @@ - 'releng-verify-jjb' - 'releng-merge-jjb' - 'releng-comment-jjb' - - 'releng-generate-artifacts-api' project: 'releng' @@ -119,22 +118,3 @@ cd /opt/jenkins-ci/releng git pull jenkins-jobs update -r --delete-old jjb/ - -- job-template: - name: 'releng-generate-artifacts-api' - - # Generate and upload the JSON file to used for artifacts site - - parameters: - - project-parameter: - project: '{project}' - branch: 'master' - - scm: - - git-scm - - triggers: - - timed: '@hourly' - - builders: - - build-and-upload-artifacts-json-api diff --git a/jjb/releng/testapi-backup-mongodb.sh b/jjb/releng/testapi-backup-mongodb.sh deleted file mode 100644 index 795e479d9..000000000 --- a/jjb/releng/testapi-backup-mongodb.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -set -e - -# Run MongoDB backup -python $WORKSPACE/utils/test/testapi/update/templates/backup_mongodb.py -o $WORKSPACE/ - -# Compressing the dump -now=$(date +"%m_%d_%Y_%H_%M_%S") -echo $now - -file_name="testapi_mongodb_"$now".tar.gz" -echo $file_name - -tar cvfz "$file_name" test_results_collection* - -rm -rf test_results_collection* - -artifact_dir="testapibackup" -workspace="$WORKSPACE" - -set +e -/usr/local/bin/gsutil &>/dev/null -if [ $? != 0 ]; then - echo "Not possible to push results to artifact: gsutil not installed" - exit 1 -else - echo "Uploading mongodump to artifact $artifact_dir" - /usr/local/bin/gsutil cp -r "$workspace"/"$file_name" gs://artifacts.opnfv.org/"$artifact_dir"/ - echo "MongoDump can be found at http://artifacts.opnfv.org/$artifact_dir.html" -fi diff --git a/jjb/xci/bifrost-verify-jobs.yml b/jjb/xci/bifrost-verify-jobs.yml index f8d39b2fb..bbce9748a 100644 --- a/jjb/xci/bifrost-verify-jobs.yml +++ b/jjb/xci/bifrost-verify-jobs.yml @@ -70,16 +70,15 @@ - build-blocker: use-build-blocker: true blocking-jobs: + - 'xci-verify-{distro}-.*' - '.*-bifrost-verify.*-{type}' + block-level: 'NODE' parameters: - string: name: PROJECT_REPO default: 'https://git.openstack.org/openstack/bifrost' - - string: - name: CLONE_LOCATION - default: '$WORKSPACE/bifrost' - string: name: DISTRO default: '{distro}' diff --git a/jjb/xci/bifrost-verify.sh b/jjb/xci/bifrost-verify.sh index a86ba91c3..263f544ad 100755 --- a/jjb/xci/bifrost-verify.sh +++ b/jjb/xci/bifrost-verify.sh @@ -11,15 +11,13 @@ set -o errexit set -o nounset set -o pipefail -git clone https://git.openstack.org/openstack/bifrost $WORKSPACE/bifrost git clone https://gerrit.opnfv.org/gerrit/releng-xci $WORKSPACE/releng-xci -# checkout the patch -cd $CLONE_LOCATION +cd $WORKSPACE git fetch $PROJECT_REPO $GERRIT_REFSPEC && sudo git checkout FETCH_HEAD # combine opnfv and upstream scripts/playbooks -/bin/cp -rf $WORKSPACE/releng-xci/bifrost/* $WORKSPACE/bifrost/ +/bin/cp -rf $WORKSPACE/releng-xci/bifrost/* $WORKSPACE/ cd $WORKSPACE/releng-xci cat > bifrost_test.sh< "${dest_path}" - if [[ "${BUILD_TAG}" =~ "baremetal" ]]; then + if [[ ! "${BUILD_TAG}" =~ 'virtual' ]]; then ssh ${ssh_options} "${ssh_user}@${installer_ip}" \ "cat /etc/ssl/certs/os_cacert" > "${os_cacert}" fi diff --git a/utils/opnfv-artifacts.py b/utils/opnfv-artifacts.py deleted file mode 100644 index 2f2cc41ba..000000000 --- a/utils/opnfv-artifacts.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/usr/bin/python -# SPDX-license-identifier: Apache-2.0 -############################################################################## -# Copyright (c) 2016 The Linux Foundation and others -# -# 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. -############################################################################## - -""" -Generate JSON listing of OPNFV Artifacts - -This produces a slimmed down version of metadata provided by Google -Storage for each artifact. Also excludes a large number of uninteresting -files. -""" - -from apiclient import discovery -from apiclient.errors import HttpError - -import argparse -import json -import sys - -api = { - 'projects': {}, - 'docs': {}, - 'releases': {}, -} - -releases = [ - 'arno.2015.1.0', - 'arno.2015.2.0', - 'brahmaputra.1.0', -] - -# List of file extensions to filter out -ignore_extensions = [ - '.buildinfo', - '.woff', - '.ttf', - '.svg', - '.eot', - '.pickle', - '.doctree', - '.js', - '.png', - '.css', - '.gif', - '.jpeg', - '.jpg', - '.bmp', -] - - -parser = argparse.ArgumentParser( - description='OPNFV Artifacts JSON Generator') - -parser.add_argument( - '-k', - dest='key', - default='', - help='API Key for Google Cloud Storage') - -parser.add_argument( - '-p', - default=None, - dest='pretty', - action='store_const', - const=2, - help='pretty print the output') - -# Parse and assign arguments -args = parser.parse_args() -key = args.key -pretty_print = args.pretty - - -def output(item, indent=2): - print(json.dumps(item, sort_keys=True, indent=indent)) - - -def has_gerrit_review(dir_list): - """ - If a directory contains an integer, it is assumed to be a gerrit - review number - """ - for d in dir_list: - if d.isdigit(): - return int(d) - return False - - -def has_release(dir_list): - """ - Checks if any directory contains a release name - """ - for d in dir_list: - if d in releases: - return d - return False - - -def has_documentation(dir_list): - """ - Checks for a directory specifically named 'docs' - """ - for d in dir_list: - if d == 'docs': - return True - return False - - -# Rename this or modify how gerrit review are handled -def has_logs(gerrit_review): - """ - If a gerrit review exists, create a link to the review - """ - if gerrit_review: - return "https://gerrit.opnfv.org/gerrit/#/c/%s" % gerrit_review - return False - - -def has_ignorable_extension(filename): - for extension in ignore_extensions: - if filename.lower().endswith(extension): - return True - return False - - -def get_results(key): - """ - Pull down all metadata from artifacts.opnfv.org - and store it in projects as: - { 'PROJECT': [file ...], } - """ - storage = discovery.build('storage', 'v1', developerKey=key) - files = storage.objects().list(bucket='artifacts.opnfv.org', - fields='nextPageToken,' - 'items(' - 'name,' - 'mediaLink,' - 'updated,' - 'contentType,' - 'size' - ')') - while (files is not None): - sites = files.execute() - - for site in sites['items']: - # Filter out unneeded files (js, images, css, buildinfo, etc) - if has_ignorable_extension(site['name']): - continue - - # Split /foo/bar/ into ['foo', 'bar'] and remove any extra - # slashes (ex. /foo//bar/) - site_split = filter(None, site['name'].split('/')) - - # Don't do anything if we aren't given files multiple - # directories deep - if len(site_split) < 2: - continue - - project = site_split[0] - name = '/'.join(site_split[1:]) - proxy = "http://build.opnfv.org/artifacts.opnfv.org/%s" % site[ - 'name'] - if name.endswith('.html'): - href = "http://artifacts.opnfv.org/%s" % site['name'] - href_type = 'view' - else: - href = site['mediaLink'] - href_type = 'download' - - gerrit = has_gerrit_review(site_split) - logs = False # has_logs(gerrit) - # documentation = has_documentation(site_split) - release = has_release(site_split) - - category = 'project' - if gerrit: - category = 'gerrit' - elif release: - category = 'release' - elif logs: - category = 'logs' - - metadata = { - 'category': category, - 'gerritreview': gerrit, - 'release': release, - 'name': name, - 'size': site['size'], - 'time': site['updated'], - 'contentType': site['contentType'], - 'href': href, - 'href_type': href_type, - 'proxy_href': proxy, - } - - if project in releases: - if project not in api['releases']: - api['releases'][project] = [metadata] - else: - api['releases'][project].append(metadata) - else: - if project not in api['projects']: - api['projects'][project] = [metadata] - else: - api['projects'][project].append(metadata) - - files = storage.objects().list_next(files, sites) - - return api - - -# Fail if there is an invalid response from GCE -try: - js = get_results(key) -except HttpError as e: - print >> sys.stderr, e - exit(1) - -output(js, indent=pretty_print) diff --git a/utils/push-test-logs.sh b/utils/push-test-logs.sh index 518d20ae5..238c4c6ad 100644 --- a/utils/push-test-logs.sh +++ b/utils/push-test-logs.sh @@ -27,12 +27,12 @@ node_list=(\ 'ericsson-pod1' 'ericsson-pod2' \ 'ericsson-virtual1' 'ericsson-virtual2' 'ericsson-virtual3' \ 'ericsson-virtual4' 'ericsson-virtual5' 'ericsson-virtual12' \ -'arm-pod1' 'arm-pod5' \ +'arm-pod1' 'arm-pod5' 'arm-pod6' \ 'huawei-pod1' 'huawei-pod2' 'huawei-pod3' 'huawei-pod4' 'huawei-pod5' \ 'huawei-pod6' 'huawei-pod7' 'huawei-pod12' \ 'huawei-virtual1' 'huawei-virtual2' 'huawei-virtual3' 'huawei-virtual4' \ 'huawei-virtual5' 'huawei-virtual8' 'huawei-virtual9' \ -'zte-pod2' \ +'zte-pod2' 'zte-pod3' \ 'zte-virtual1') diff --git a/utils/test/dashboard/README.rst b/utils/test/dashboard/README.rst deleted file mode 100644 index e69de29bb..000000000 diff --git a/utils/test/dashboard/backup-db.sh b/utils/test/dashboard/backup-db.sh deleted file mode 100644 index 35c3fbe5a..000000000 --- a/utils/test/dashboard/backup-db.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -# SPDX-license-identifier: Apache-2.0 -############################################################################## -# Copyright (c) 2016 Orange and others. -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## -echo "Backup Test collection DB" -now=$(date +"%m_%d_%Y_%H_%M_%S") -echo $now -echo " ------------- " -TARGET_DIR=./$now -TEST_RESULT_DB_BACKUP="test_collection_db."$now".tar.gz" - -echo "Create Directory for backup" -mkdir -p $TARGET_DIR - -echo "Export results" -mongoexport --db test_results_collection -c results --out $TARGET_DIR/backup-results.json -echo "Export test cases" -mongoexport --db test_results_collection -c testcases --out $TARGET_DIR/backup-cases.json -echo "Export projects" -mongoexport --db test_results_collection -c projects --out $TARGET_DIR/backup-projects.json -echo "Export pods" -mongoexport --db test_results_collection -c pods --out $TARGET_DIR/backup-pod.json - -echo "Create tar.gz" -#tar -cvzf $TEST_RESULT_DB_BACKUP $TARGET_DIR - -echo "Delete temp directory" -#rm -Rf $TARGET_DIR diff --git a/utils/test/dashboard/dashboard/__init__.py b/utils/test/dashboard/dashboard/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/utils/test/dashboard/dashboard/common/__init__.py b/utils/test/dashboard/dashboard/common/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/utils/test/dashboard/dashboard/common/elastic_access.py b/utils/test/dashboard/dashboard/common/elastic_access.py deleted file mode 100644 index eb29ce879..000000000 --- a/utils/test/dashboard/dashboard/common/elastic_access.py +++ /dev/null @@ -1,51 +0,0 @@ -import json -import urlparse - -import urllib3 - -http = urllib3.PoolManager() - - -def _request(method, url, creds=None, body=None): - headers = urllib3.make_headers(basic_auth=creds) - return http.request(method, url, headers=headers, body=body) - - -def _post(url, creds=None, body=None): - return _request('POST', url, creds=creds, body=body) - - -def _get(url, creds=None, body=None): - return json.loads(_request('GET', url, creds=creds, body=body).data) - - -def delete_docs(url, creds=None, body=None): - return _request('DELETE', url, creds=creds, body=body) - - -def publish_docs(url, creds=None, body=None): - result = _post(url, creds=creds, body=(json.dumps(body))) - return result.status, result.data - - -def _get_docs_nr(url, creds=None, body=None): - res_data = _get('{}/_search?size=0'.format(url), creds=creds, body=body) - print(type(res_data), res_data) - return res_data['hits']['total'] - - -def get_docs(url, creds=None, body=None, field='_source'): - - docs_nr = _get_docs_nr(url, creds=creds, body=body) - res_data = _get('{}/_search?size={}'.format(url, docs_nr), - creds=creds, body=body) - - docs = [] - for hit in res_data['hits']['hits']: - docs.append(hit[field]) - return docs - - -def publish_kibana(url, creds, type, id, body): - url = urlparse.urljoin(url, '/.kibana/{}/{}'.format(type, id)) - publish_docs(url, creds, body) diff --git a/utils/test/dashboard/dashboard/common/logger_utils.py b/utils/test/dashboard/dashboard/common/logger_utils.py deleted file mode 100644 index 58e343d79..000000000 --- a/utils/test/dashboard/dashboard/common/logger_utils.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -# -# feng.xiaowei@zte.com.cn -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Logging levels: -# Level Numeric value -# CRITICAL 50 -# ERROR 40 -# WARNING 30 -# INFO 20 -# DEBUG 10 -# NOTSET 0 -# -# Usage: -# import functest_logger as fl -# logger = fl.Logger("script_name").getLogger() -# logger.info("message to be shown with - INFO - ") -# logger.debug("message to be shown with - DEBUG -") - -import logging -import os - - -class Logger(object): - file_path = '/var/log' - formatter = logging.Formatter('%(asctime)s - %(name)s - ' - '%(levelname)s - %(message)s') - - def __init__(self, logger_name): - - IF_DEBUG = os.getenv('IF_DEBUG') - - self.logger_name = logger_name - self.logger = logging.getLogger(logger_name) - self.logger.propagate = 0 - self.logger.setLevel(logging.DEBUG) - - ch = logging.StreamHandler() - ch.setFormatter(self.formatter) - if IF_DEBUG is not None and IF_DEBUG.lower() == "true": - ch.setLevel(logging.DEBUG) - else: - ch.setLevel(logging.INFO) - self.logger.addHandler(ch) - - hdlr = logging.FileHandler('%s/%s.log' % (self.file_path, logger_name)) - hdlr.setFormatter(self.formatter) - hdlr.setLevel(logging.DEBUG) - self.logger.addHandler(hdlr) - - @property - def get(self): - return self.logger - - -class DashboardLogger(Logger): - file_path = '/var/log/kibana_dashboard' - - def __init__(self, logger_name): - super(DashboardLogger, self).__init__(logger_name) diff --git a/utils/test/dashboard/dashboard/conf/__init__.py b/utils/test/dashboard/dashboard/conf/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/utils/test/dashboard/dashboard/conf/config.py b/utils/test/dashboard/dashboard/conf/config.py deleted file mode 100644 index 6114e90a9..000000000 --- a/utils/test/dashboard/dashboard/conf/config.py +++ /dev/null @@ -1,86 +0,0 @@ -#! /usr/bin/env python - -import urlparse -from ConfigParser import SafeConfigParser, NoOptionError - - -class ParseError(Exception): - """ - Custom exception class for config file - """ - - def __init__(self, message): - self.msg = message - - def __str__(self): - return 'error parsing config file : %s' % self.msg - - -class APIConfig: - """ - The purpose of this class is to load values correctly from the config file. - Each key is declared as an attribute in __init__() and linked in parse() - """ - - def __init__(self): - self._default_config_location = "/etc/dashboard/config.ini" - self.es_url = 'http://localhost:9200' - self.es_creds = None - self.kibana_url = None - self.js_path = None - self.index_url = None - - def _get_str_parameter(self, section, param): - try: - return self._parser.get(section, param) - except NoOptionError: - raise ParseError("[%s.%s] parameter not found" % (section, param)) - - def _get_int_parameter(self, section, param): - try: - return int(self._get_str_parameter(section, param)) - except ValueError: - raise ParseError("[%s.%s] not an int" % (section, param)) - - def _get_bool_parameter(self, section, param): - result = self._get_str_parameter(section, param) - if str(result).lower() == 'true': - return True - if str(result).lower() == 'false': - return False - - raise ParseError( - "[%s.%s : %s] not a boolean" % (section, param, result)) - - @staticmethod - def parse(config_location=None): - obj = APIConfig() - - if config_location is None: - config_location = obj._default_config_location - - obj._parser = SafeConfigParser() - obj._parser.read(config_location) - if not obj._parser: - raise ParseError("%s not found" % config_location) - - # Linking attributes to keys from file with their sections - obj.es_url = obj._get_str_parameter("elastic", "url") - obj.es_creds = obj._get_str_parameter("elastic", "creds") - obj.kibana_url = obj._get_str_parameter("kibana", "url") - obj.js_path = obj._get_str_parameter("kibana", "js_path") - index = obj._get_str_parameter("elastic", "index") - obj.index_url = urlparse.urljoin(obj.es_url, index) - - return obj - - def __str__(self): - return "elastic_url = %s \n" \ - "elastic_creds = %s \n" \ - "kibana_url = %s \n" \ - "index_url = %s \n" \ - "js_path = %s \n" % (self.es_url, - self.es_creds, - self.kibana_url, - self.index_url, - self.js_path) diff --git a/utils/test/dashboard/dashboard/conf/testcases.py b/utils/test/dashboard/dashboard/conf/testcases.py deleted file mode 100644 index 98ce20984..000000000 --- a/utils/test/dashboard/dashboard/conf/testcases.py +++ /dev/null @@ -1,24 +0,0 @@ -import yaml - - -with open('/etc/dashboard/testcases.yaml') as f: - testcases_yaml = yaml.safe_load(f) -f.close() - - -def compose_format(fmt): - return 'format_' + fmt.strip() - - -def get_format(project, case): - testcases = testcases_yaml.get(project) - if isinstance(testcases, list): - for case_dict in testcases: - if case_dict['name'] == case: - return compose_format(case_dict['format']) - return None - - -if __name__ == '__main__': - fmt = get_format('functest', 'vping_ssh') - print(fmt) diff --git a/utils/test/dashboard/dashboard/elastic2kibana/__init__.py b/utils/test/dashboard/dashboard/elastic2kibana/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/utils/test/dashboard/dashboard/elastic2kibana/dashboard_assembler.py b/utils/test/dashboard/dashboard/elastic2kibana/dashboard_assembler.py deleted file mode 100644 index 651168bbb..000000000 --- a/utils/test/dashboard/dashboard/elastic2kibana/dashboard_assembler.py +++ /dev/null @@ -1,59 +0,0 @@ -import json - -import utility -from dashboard.common import elastic_access - - -class DashboardAssembler(object): - def __init__(self, - project, - case, - family, - installer, - pod, - visualizations, - es_url, - es_creds): - super(DashboardAssembler, self).__init__() - self.project = project - self.case = case - self.test_family = family - self.installer = installer - self.pod = pod - self.visualizations = visualizations - self.es_url = es_url - self.es_creds = es_creds - self._assemble() - self._publish() - - def _assemble(self): - db = { - "query": { - "project_name": self.project, - "case_name": self.case, - "installer": self.installer, - "metric": self.visualizations[0].vis_state_title, - "pod": self.pod - }, - "test_family": self.test_family, - "ids": [visualization.id for visualization in self.visualizations] - } - template = utility.env.get_template('dashboard.json') - self.dashboard = json.loads(template.render(db=db)) - utility.dumps(self.dashboard, - ['description', - 'uiStateJSON', - 'panelsJSON', - 'optionsJSON']) - utility.dumps_2depth(self.dashboard, - 'kibanaSavedObjectMeta', - 'searchSourceJSON') - self.id = self.dashboard['title'].replace(' ', '-').replace('/', '-') - return self - - def _publish(self): - elastic_access.publish_kibana(self.es_url, - self.es_creds, - 'dashboard', - self.id, - self.dashboard) diff --git a/utils/test/dashboard/dashboard/elastic2kibana/main.py b/utils/test/dashboard/dashboard/elastic2kibana/main.py deleted file mode 100644 index 112d2226e..000000000 --- a/utils/test/dashboard/dashboard/elastic2kibana/main.py +++ /dev/null @@ -1,155 +0,0 @@ -#! /usr/bin/env python -import json - -import argparse - -from dashboard.common import elastic_access -from dashboard.common import logger_utils -from dashboard.conf import config -from dashboard.conf import testcases -from dashboard_assembler import DashboardAssembler -from visualization_assembler import VisualizationAssembler - -logger = logger_utils.DashboardLogger('elastic2kibana').get - -parser = argparse.ArgumentParser() -parser.add_argument("-c", "--config-file", - dest='config_file', - help="Config file location") - -args = parser.parse_args() -CONF = config.APIConfig().parse(args.config_file) - -_installers = {'fuel', 'apex', 'compass', 'joid'} - - -class KibanaConstructor(object): - def __init__(self): - super(KibanaConstructor, self).__init__() - self.js_dict = {} - - def construct(self): - for project, case_dicts in testcases.testcases_yaml.items(): - for case in case_dicts: - self._construct_by_case(project, case) - return self - - def _construct_by_case(self, project, case): - case_name = case.get('name') - vis_ps = case.get('visualizations') - family = case.get('test_family') - for vis_p in vis_ps: - self._construct_by_vis(project, case_name, family, vis_p) - - def _construct_by_vis(self, project, case, family, vis_p): - for installer in _installers: - pods_and_scenarios = self._get_pods_and_scenarios(project, - case, - installer) - for pod, scenarios in pods_and_scenarios.iteritems(): - visualizations = self._construct_visualizations(project, - case, - installer, - pod, - scenarios, - vis_p, - CONF.es_url, - CONF.es_creds) - dashboard = DashboardAssembler(project, - case, - family, - installer, - pod, - visualizations, - CONF.es_url, - CONF.es_creds) - self._set_js_dict(case, - pod, - installer, - family, - vis_p.get('name'), - dashboard.id) - - @staticmethod - def _construct_visualizations(project, - case, - installer, - pod, - scenarios, - vis_p, - es_url, - es_creds): - visualizations = [] - for scenario in scenarios: - visualizations.append(VisualizationAssembler(project, - case, - installer, - pod, - scenario, - vis_p, - es_url, - es_creds)) - return visualizations - - def _set_js_dict(self, case, pod, installer, family, metric, id): - test_label = '{} {}'.format(case, metric) - if family not in self.js_dict: - self.js_dict[family] = {} - - js_test_family = self.js_dict[family] - - if test_label not in js_test_family: - js_test_family[test_label] = {} - - js_test_label = js_test_family[test_label] - - if installer not in js_test_label: - js_test_label[installer] = {} - - js_installer = js_test_label[installer] - js_installer[pod] = CONF.kibana_url + '#/dashboard/' + id - - def config_js(self): - with open(CONF.js_path, 'w+') as conf_js_fdesc: - conf_js_fdesc.write('var kibana_dashboard_links = ') - conf_js_fdesc.write(str(self.js_dict).replace("u'", "'")) - - def _get_pods_and_scenarios(self, project, case, installer): - query = json.JSONEncoder().encode({ - "query": { - "bool": { - "must": [ - {"match_all": {}} - ], - "filter": [ - {"match": {"installer": installer}}, - {"match": {"project_name": project}}, - {"match": {"case_name": case}} - ] - } - } - }) - - elastic_data = elastic_access.get_docs(CONF.index_url, - CONF.es_creds, - query) - - pods_and_scenarios = {} - - for data in elastic_data: - pod = data['pod_name'] - if pod in pods_and_scenarios: - pods_and_scenarios[pod].add(data['scenario']) - else: - pods_and_scenarios[pod] = {data['scenario']} - - if 'all' in pods_and_scenarios: - pods_and_scenarios['all'].add(data['scenario']) - else: - pods_and_scenarios['all'] = {data['scenario']} - - return pods_and_scenarios - - -def main(): - KibanaConstructor().construct().config_js() diff --git a/utils/test/dashboard/dashboard/elastic2kibana/templates/dashboard.json b/utils/test/dashboard/dashboard/elastic2kibana/templates/dashboard.json deleted file mode 100644 index cc8099593..000000000 --- a/utils/test/dashboard/dashboard/elastic2kibana/templates/dashboard.json +++ /dev/null @@ -1,61 +0,0 @@ -{% set db = db|default({}) -%} - - -{% macro calc_col(index) -%} - {% if index is divisibleby 2 %} - 7 - {% else %} - 1 - {% endif %} -{%- endmacro %} - -{% macro calc_row(index) -%} -{% set num = (index - 1)//2 %} - {{1 + num * 3}} -{%- endmacro %} - -{ - "description": "Kibana dashboard for {{db.query}}", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": { - "filter": [ - { - "query": { - "query_string": { - "analyze_wildcard": true, - "query": "*" - } - } - } - ] - } - }, - "metadata": { - "label": "{{db.query.case_name}} {{db.query.metric}}", - "test_family": "{{db.test_family}}" - }, - "optionsJSON": { - "darkTheme": false - }, - "panelsJSON": [ - {% for id in db.ids %} - { - "col": {{calc_col(loop.index)}}, - "id": "{{id}}", - "panelIndex": {{loop.index}}, - "row": {{calc_row(loop.index)}}, - "size_x": 6, - "size_y": 3, - "type": "visualization" - } - {% if not loop.last %} - , - {% endif %} - {% endfor %} - ], - "scenario": 1, - "timeRestore": false, - "title": "{{db.query.project_name}} {{db.query.case_name}} {{db.query.installer}} {{db.query.metric}} {{db.query.pod}}", - "uiStateJSON": {} -} diff --git a/utils/test/dashboard/dashboard/elastic2kibana/templates/duration.json b/utils/test/dashboard/dashboard/elastic2kibana/templates/duration.json deleted file mode 100644 index f50a668db..000000000 --- a/utils/test/dashboard/dashboard/elastic2kibana/templates/duration.json +++ /dev/null @@ -1,45 +0,0 @@ -{% set aggs = aggs|default([]) -%} - -{ - "title": "duration", - "type": "line", - "listeners": {}, - "params": { - "addLegend": true, - "shareYAxis": true, - "addTooltip": true, - "smoothLines": false, - "scale": "linear", - "interpolate": "linear", - "times": [], - "addTimeMarker": false, - "defaultYExtents": false, - "setYExtents": false, - "yAxis": {}, - "mode": "stacked" - }, - "aggs": [ - {% for agg in aggs %} - { - "id": {{agg.id }}, - "type": "avg", - "schema": "metric", - "params": { - "field": "{{agg.field}}" - } - }, - {% endfor %} - { - "id": {{ aggs|length + 1 }}, - "type": "date_histogram", - "schema": "segment", - "params": { - "field": "start_date", - "interval": "auto", - "customInterval": "2h", - "min_doc_count": 1, - "extended_bounds": {} - } - } - ] -} diff --git a/utils/test/dashboard/dashboard/elastic2kibana/templates/qpi.json b/utils/test/dashboard/dashboard/elastic2kibana/templates/qpi.json deleted file mode 100644 index a46f315ef..000000000 --- a/utils/test/dashboard/dashboard/elastic2kibana/templates/qpi.json +++ /dev/null @@ -1,45 +0,0 @@ -{% set aggs = aggs|default([]) -%} - -{ - "title": "qpi", - "type": "line", - "listeners": {}, - "params": { - "addLegend": true, - "shareYAxis": true, - "addTooltip": true, - "smoothLines": false, - "scale": "linear", - "interpolate": "linear", - "times": [], - "addTimeMarker": false, - "defaultYExtents": false, - "setYExtents": false, - "yAxis": {}, - "mode": "stacked" - }, - "aggs": [ - {% for agg in aggs %} - { - "id": {{agg.id }}, - "type": "avg", - "schema": "metric", - "params": { - "field": "{{agg.field}}" - } - }, - {% endfor %} - { - "id": {{ aggs|length + 1 }}, - "type": "date_histogram", - "schema": "segment", - "params": { - "field": "start_date", - "interval": "auto", - "customInterval": "2h", - "min_doc_count": 1, - "extended_bounds": {} - } - } - ] -} diff --git a/utils/test/dashboard/dashboard/elastic2kibana/templates/success_percentage.json b/utils/test/dashboard/dashboard/elastic2kibana/templates/success_percentage.json deleted file mode 100644 index 993070844..000000000 --- a/utils/test/dashboard/dashboard/elastic2kibana/templates/success_percentage.json +++ /dev/null @@ -1,45 +0,0 @@ -{% set aggs = aggs|default([]) -%} - -{ - "title": "success_percentage", - "type": "line", - "listeners": {}, - "params": { - "addLegend": true, - "shareYAxis": true, - "addTooltip": true, - "smoothLines": false, - "scale": "linear", - "interpolate": "linear", - "times": [], - "addTimeMarker": false, - "defaultYExtents": false, - "setYExtents": false, - "yAxis": {}, - "mode": "stacked" - }, - "aggs": [ - {% for agg in aggs %} - { - "id": {{agg.id }}, - "type": "avg", - "schema": "metric", - "params": { - "field": "{{agg.field}}" - } - }, - {% endfor %} - { - "id": {{ aggs|length + 1 }}, - "type": "date_histogram", - "schema": "segment", - "params": { - "field": "start_date", - "interval": "auto", - "customInterval": "2h", - "min_doc_count": 1, - "extended_bounds": {} - } - } - ] -} diff --git a/utils/test/dashboard/dashboard/elastic2kibana/templates/tests_failures.json b/utils/test/dashboard/dashboard/elastic2kibana/templates/tests_failures.json deleted file mode 100644 index 01f9ba89e..000000000 --- a/utils/test/dashboard/dashboard/elastic2kibana/templates/tests_failures.json +++ /dev/null @@ -1,45 +0,0 @@ -{% set aggs = aggs|default([]) -%} - -{ - "title": "tests_failures", - "type": "histogram", - "listeners": {}, - "params": { - "addLegend": true, - "shareYAxis": true, - "addTooltip": true, - "smoothLines": false, - "scale": "linear", - "interpolate": "linear", - "times": [], - "addTimeMarker": false, - "defaultYExtents": false, - "setYExtents": false, - "yAxis": {}, - "mode": "grouped" - }, - "aggs": [ - {% for agg in aggs %} - { - "id": {{agg.id }}, - "type": "sum", - "schema": "metric", - "params": { - "field": "{{agg.field}}" - } - }, - {% endfor %} - { - "id": {{ aggs|length + 1 }}, - "type": "date_histogram", - "schema": "segment", - "params": { - "field": "start_date", - "interval": "auto", - "customInterval": "2h", - "min_doc_count": 1, - "extended_bounds": {} - } - } - ] -} diff --git a/utils/test/dashboard/dashboard/elastic2kibana/templates/visualization.json b/utils/test/dashboard/dashboard/elastic2kibana/templates/visualization.json deleted file mode 100644 index d51d4174e..000000000 --- a/utils/test/dashboard/dashboard/elastic2kibana/templates/visualization.json +++ /dev/null @@ -1,32 +0,0 @@ -{% set vis = vis|default({}) -%} - - -{ - "description": "Kibana visualization for {{ vis.filters }}", - "kibanaSavedObjectMeta": { - "searchSourceJSON": { - "filter": [ - {% for key, value in vis.filters.iteritems() if key != "metric" %} - {% if not (key == "pod_name" and value == "all") %} - { - "match": { - "{{ key }}": { - "query": "{{ value }}", - "type": "phrase" - } - } - } - {% if not loop.last %} - , - {% endif %} - {% endif %} - {% endfor %} - ] - } - }, - "scenario": 1, - "title": "{{vis.filters.project_name}} {{vis.filters.case_name}} {{vis.filters.installer}} {{vis.filters.metric}} {{vis.filters.pod_name}} {{vis.filters.scenario}}", - "uiStateJSON": {}, - "visState": {{ vis.visState }} -} - diff --git a/utils/test/dashboard/dashboard/elastic2kibana/utility.py b/utils/test/dashboard/dashboard/elastic2kibana/utility.py deleted file mode 100644 index 40d9202a6..000000000 --- a/utils/test/dashboard/dashboard/elastic2kibana/utility.py +++ /dev/null @@ -1,16 +0,0 @@ -import json - -from jinja2 import Environment, PackageLoader - -env = Environment(loader=PackageLoader('dashboard', - 'elastic2kibana/templates')) -env.filters['jsonify'] = json.dumps - - -def dumps(a_dict, items): - for key in items: - a_dict[key] = json.dumps(a_dict[key]) - - -def dumps_2depth(a_dict, key1, key2): - a_dict[key1][key2] = json.dumps(a_dict[key1][key2]) diff --git a/utils/test/dashboard/dashboard/elastic2kibana/visualization_assembler.py b/utils/test/dashboard/dashboard/elastic2kibana/visualization_assembler.py deleted file mode 100644 index d7e6e543a..000000000 --- a/utils/test/dashboard/dashboard/elastic2kibana/visualization_assembler.py +++ /dev/null @@ -1,84 +0,0 @@ -import json - -import utility -from dashboard.common import elastic_access - - -class VisStateBuilder(object): - def __init__(self, vis_p): - super(VisStateBuilder, self).__init__() - self.vis_p = vis_p - - def build(self): - name = self.vis_p.get('name') - fields = self.vis_p.get('fields') - - aggs = [] - index = 1 - for field in fields: - aggs.append({ - "id": index, - "field": field.get("field") - }) - index += 1 - - template = utility.env.get_template('{}.json'.format(name)) - vis = template.render(aggs=aggs) - return json.loads(vis) - - -class VisualizationAssembler(object): - def __init__(self, - project, - case, - installer, - pod, - scenario, - vis_p, - es_url, - es_creds): - super(VisualizationAssembler, self).__init__() - self.project = project - self.case = case - self.installer = installer - self.pod = pod - self.scenario = scenario - self.vis_p = vis_p - self.es_url = es_url - self.es_creds = es_creds - self._assemble() - self._publish() - - def _assemble(self): - visState = VisStateBuilder(self.vis_p).build() - self.vis_state_title = visState['title'] - - vis = { - "visState": json.dumps(visState), - "filters": { - "project_name": self.project, - "case_name": self.case, - "installer": self.installer, - "metric": self.vis_state_title, - "pod_name": self.pod, - "scenario": self.scenario - } - } - - template = utility.env.get_template('visualization.json') - - self.visualization = json.loads(template.render(vis=vis)) - utility.dumps(self.visualization, - ['visState', 'description', 'uiStateJSON']) - utility.dumps_2depth(self.visualization, - 'kibanaSavedObjectMeta', - 'searchSourceJSON') - title = self.visualization['title'] - self.id = title.replace(' ', '-').replace('/', '-') - - def _publish(self): - elastic_access.publish_kibana(self.es_url, - self.es_creds, - 'visualization', - self.id, - self.visualization) diff --git a/utils/test/dashboard/dashboard/functest/__init__.py b/utils/test/dashboard/dashboard/functest/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/utils/test/dashboard/dashboard/functest/format.py b/utils/test/dashboard/dashboard/functest/format.py deleted file mode 100644 index 75d361ff8..000000000 --- a/utils/test/dashboard/dashboard/functest/format.py +++ /dev/null @@ -1,192 +0,0 @@ -#! /usr/bin/env python - - -def _convert_value(value): - return value if value != '' else 0 - - -def _convert_duration(duration): - if ((isinstance(duration, str) or - isinstance(duration, unicode)) and ':' in duration): - hours, minutes, seconds = duration.split(":") - hours = _convert_value(hours) - minutes = _convert_value(minutes) - seconds = _convert_value(seconds) - int_duration = 3600 * int(hours) + 60 * int(minutes) + float(seconds) - else: - int_duration = duration - return int_duration - - -def format_normal(testcase): - """ - Look for these and leave any of those: - details.duration - details.tests - details.failures - - If none are present, then return False - """ - found = False - testcase_details = testcase['details'] - fields = ['duration', 'tests', 'failures'] - if isinstance(testcase_details, dict): - for key, value in testcase_details.items(): - if key in fields: - found = True - if key == 'duration': - testcase_details[key] = _convert_duration(value) - else: - del testcase_details[key] - - if 'tests' in testcase_details and 'failures' in testcase_details: - testcase_tests = float(testcase_details['tests']) - testcase_failures = float(testcase_details['failures']) - if testcase_tests != 0: - testcase_details['success_percentage'] = 100 * \ - (testcase_tests - testcase_failures) / testcase_tests - else: - testcase_details['success_percentage'] = 0 - - return found - - -def format_rally(testcase): - """ - Structure: - details.[{summary.duration}] - details.[{summary.nb success}] - details.[{summary.nb tests}] - - Find data for these fields - -> details.duration - -> details.tests - -> details.success_percentage - """ - details = testcase['details'] - summary = None - for item in details: - if 'summary' in item: - summary = item['summary'] - - if not summary: - return False - - testcase['details'] = { - 'duration': summary['duration'], - 'tests': summary['nb tests'], - 'success_percentage': summary['nb success'] - } - return True - - -def _get_statistics(orig_data, stat_fields, stat_values=None): - test_results = {} - for stat_data in orig_data: - for field in stat_fields: - stat_value = stat_data[field] - if stat_value in test_results: - test_results[stat_value] += 1 - else: - test_results[stat_value] = 1 - - if stat_values is not None: - for stat_value in stat_values: - if stat_value not in test_results: - test_results[stat_value] = 0 - - return test_results - - -def format_onos(testcase): - """ - Structure: - details.FUNCvirNet.duration - details.FUNCvirNet.status.[{Case result}] - details.FUNCvirNetL3.duration - details.FUNCvirNetL3.status.[{Case result}] - - Find data for these fields - -> details.FUNCvirNet.duration - -> details.FUNCvirNet.tests - -> details.FUNCvirNet.failures - -> details.FUNCvirNetL3.duration - -> details.FUNCvirNetL3.tests - -> details.FUNCvirNetL3.failures - """ - testcase_details = testcase['details'] - - if ('FUNCvirNet' not in testcase_details or - 'FUNCvirNetL3' not in testcase_details): - return False - - funcvirnet_details = testcase_details['FUNCvirNet']['status'] - funcvirnet_stats = _get_statistics( - funcvirnet_details, ('Case result',), ('PASS', 'FAIL')) - funcvirnet_passed = funcvirnet_stats['PASS'] - funcvirnet_failed = funcvirnet_stats['FAIL'] - funcvirnet_all = funcvirnet_passed + funcvirnet_failed - - funcvirnetl3_details = testcase_details['FUNCvirNetL3']['status'] - funcvirnetl3_stats = _get_statistics( - funcvirnetl3_details, ('Case result',), ('PASS', 'FAIL')) - funcvirnetl3_passed = funcvirnetl3_stats['PASS'] - funcvirnetl3_failed = funcvirnetl3_stats['FAIL'] - funcvirnetl3_all = funcvirnetl3_passed + funcvirnetl3_failed - - testcase_details['FUNCvirNet'] = { - 'duration': - _convert_duration(testcase_details['FUNCvirNet']['duration']), - 'tests': funcvirnet_all, - 'failures': funcvirnet_failed - } - testcase_details['FUNCvirNetL3'] = { - 'duration': - _convert_duration(testcase_details['FUNCvirNetL3']['duration']), - 'tests': funcvirnetl3_all, - 'failures': funcvirnetl3_failed - } - return True - - -def format_vims(testcase): - """ - Structure: - details.sig_test.result.[{result}] - details.sig_test.duration - details.vIMS.duration - details.orchestrator.duration - - Find data for these fields - -> details.sig_test.duration - -> details.sig_test.tests - -> details.sig_test.failures - -> details.sig_test.passed - -> details.sig_test.skipped - -> details.vIMS.duration - -> details.orchestrator.duration - """ - testcase_details = testcase['details'] - test_results = _get_statistics(testcase_details['sig_test']['result'], - ('result',), - ('Passed', 'Skipped', 'Failed')) - passed = test_results['Passed'] - skipped = test_results['Skipped'] - failures = test_results['Failed'] - all_tests = passed + skipped + failures - testcase['details'] = { - 'sig_test': { - 'duration': testcase_details['sig_test']['duration'], - 'tests': all_tests, - 'failures': failures, - 'passed': passed, - 'skipped': skipped - }, - 'vIMS': { - 'duration': testcase_details['vIMS']['duration'] - }, - 'orchestrator': { - 'duration': testcase_details['orchestrator']['duration'] - } - } - return True diff --git a/utils/test/dashboard/dashboard/functest/testcases.yaml b/utils/test/dashboard/dashboard/functest/testcases.yaml deleted file mode 100644 index 85cb8b292..000000000 --- a/utils/test/dashboard/dashboard/functest/testcases.yaml +++ /dev/null @@ -1,139 +0,0 @@ ---- -functest: - - - name: tempest_smoke_serial - format: normal - test_family: VIM - visualizations: - - - name: duration - fields: - - field: details.duration - - - name: tests_failures - fields: - - field: details.tests - - field: details.failures - - - name: success_percentage - fields: - - field: details.success_percentage - - - name: rally_sanity - test_family: VIM - format: rally - visualizations: - - - name: duration - fields: - - field: details.duration - - - name: tests_failures - fields: - - field: details.tests - - - name: success_percentage - fields: - - field: details.success_percentage - - - name: vping_ssh - format: normal - test_family: VIM - visualizations: - - - name: duration - fields: - - field: details.duration - - - name: vping_userdata - format: normal - test_family: VIM - visualizations: - - - name: duration - fields: - - field: details.duration - - - name: odl - test_family: Controller - format: odl - visualizations: - - - name: tests_failures - fields: - - field: details.tests - - field: details.failures - - - name: success_percentage - fields: - - field: details.success_percentage - - - name: onos - format: onos - test_family: Controller - visualizations: - - - name: duration - label: FUNCvirNet - fields: - - field: details.FUNCvirNet.duration - - - name: duration - label: FUNCvirNetL3 - fields: - - field: details.FUNCvirNetL3.duration - - - name: tests_failures - label: FUNCvirNet - fields: - - field: details.FUNCvirNet.tests - - field: details.FUNCvirNet.failures - - - name: tests_failures - label: FUNCvirNetL3 - fields: - - field: details.FUNCvirNetL3.tests - - field: details.FUNCvirNetL3.failures - - - name: vims - format: vims - test_family: Features - visualizations: - - - name: duration - fields: - - field: details.vIMS.duration - - field: details.orchestrator.duration - - field: details.sig_test.duration - - - name: tests_failures - fields: - - field: details.sig_test.tests - - field: details.sig_test.failures - - field: details.sig_test.passed - - field: details.sig_test.skipped -promise: - - - name: promise - format: normal - test_family: Features - visualizations: - - - name: duration - fields: - - field: details.duration - - - name: tests_failures - fields: - - field: details.tests - - field: details.failures -doctor: - - - name: doctor-notification - test_family: Features - format: normal - visualizations: - - - name: duration - fields: - - field: details.duration diff --git a/utils/test/dashboard/dashboard/mongo2elastic/__init__.py b/utils/test/dashboard/dashboard/mongo2elastic/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/utils/test/dashboard/dashboard/mongo2elastic/main.py b/utils/test/dashboard/dashboard/mongo2elastic/main.py deleted file mode 100644 index e33252df2..000000000 --- a/utils/test/dashboard/dashboard/mongo2elastic/main.py +++ /dev/null @@ -1,259 +0,0 @@ -#! /usr/bin/env python - -import datetime -import json -import os -import subprocess -import traceback -import uuid - -import argparse - -from dashboard.common import elastic_access -from dashboard.common import logger_utils -from dashboard.conf import testcases -from dashboard.conf.config import APIConfig -from dashboard.mongo2elastic import format - -logger = logger_utils.DashboardLogger('mongo2elastic').get - -parser = argparse.ArgumentParser() -parser.add_argument("-c", "--config-file", - dest='config_file', - help="Config file location") -parser.add_argument('-ld', '--latest-days', - default=0, - type=int, - metavar='N', - help='get entries old at most N days from mongodb and' - ' parse those that are not already in elasticsearch.' - ' If not present, will get everything from mongodb,' - ' which is the default') - -args = parser.parse_args() -CONF = APIConfig().parse(args.config_file) - - -tmp_docs_file = './mongo-{}.json'.format(uuid.uuid4()) - - -class DocumentVerification(object): - - def __init__(self, doc): - super(DocumentVerification, self).__init__() - self.doc = doc - self.doc_id = doc['_id'] if '_id' in doc else None - self.skip = False - - def mandatory_fields_exist(self): - mandatory_fields = ['installer', - 'pod_name', - 'version', - 'case_name', - 'project_name', - 'details', - 'start_date', - 'scenario'] - for key, value in self.doc.items(): - if key in mandatory_fields: - if value is None: - logger.info("Skip testcase '%s' because field " - "'%s' missing" % (self.doc_id, key)) - self.skip = True - else: - mandatory_fields.remove(key) - else: - del self.doc[key] - - if len(mandatory_fields) > 0: - logger.info("Skip testcase '%s' because field(s) '%s' missing" % - (self.doc_id, mandatory_fields)) - self.skip = True - - return self - - def modify_start_date(self): - field = 'start_date' - if field in self.doc: - self.doc[field] = self._fix_date(self.doc[field]) - - return self - - def modify_scenario(self): - scenario = 'scenario' - version = 'version' - - if (scenario not in self.doc) or \ - (scenario in self.doc and self.doc[scenario] is None): - self.doc[scenario] = self.doc[version] - - return self - - def is_skip(self): - return self.skip - - def _fix_date(self, date_string): - if date_string == 'None': - return None - if isinstance(date_string, dict): - return date_string['$date'] - if 'T' not in date_string: - date_string = date_string[:-3].replace(' ', 'T') - if not date_string.endswith('Z'): - date_string += 'Z' - - return date_string - - -class DocumentPublisher(object): - - def __init__(self, doc, fmt, exist_docs, creds, elastic_url): - self.doc = doc - self.fmt = fmt - self.creds = creds - self.exist_docs = exist_docs - self.elastic_url = elastic_url - self.is_formatted = True - - def format(self): - try: - if self._verify_document() and self.fmt: - self.is_formatted = vars(format)[self.fmt](self.doc) - else: - self.is_formatted = False - except Exception: - logger.error("Fail in format testcase[%s]\nerror message: %s" % - (self.doc, traceback.format_exc())) - self.is_formatted = False - finally: - return self - - def publish(self): - if self.is_formatted and self.doc not in self.exist_docs: - self._publish() - - def _publish(self): - status, data = elastic_access.publish_docs( - self.elastic_url, self.creds, self.doc) - if status > 300: - logger.error('Publish record[{}] failed, due to [{}]' - .format(self.doc, - json.loads(data)['error']['reason'])) - - def _fix_date(self, date_string): - if isinstance(date_string, dict): - return date_string['$date'] - else: - return date_string[:-3].replace(' ', 'T') + 'Z' - - def _verify_document(self): - return not (DocumentVerification(self.doc) - .modify_start_date() - .modify_scenario() - .mandatory_fields_exist() - .is_skip()) - - -class DocumentsPublisher(object): - - def __init__(self, project, case, fmt, days, elastic_url, creds): - self.project = project - self.case = case - self.fmt = fmt - self.days = days - self.elastic_url = elastic_url - self.creds = creds - self.existed_docs = [] - - def export(self): - if self.days > 0: - past_time = datetime.datetime.today( - ) - datetime.timedelta(days=self.days) - query = '''{{ - "project_name": "{}", - "case_name": "{}", - "start_date": {{"$gt" : "{}"}} - }}'''.format(self.project, self.case, past_time) - else: - query = '''{{ - "project_name": "{}", - "case_name": "{}" - }}'''.format(self.project, self.case) - cmd = ['mongoexport', - '--db', 'test_results_collection', - '--collection', 'results', - '--query', '{}'.format(query), - '--out', '{}'.format(tmp_docs_file)] - try: - subprocess.check_call(cmd) - return self - except Exception as err: - logger.error("export mongodb failed: %s" % err) - self._remove() - exit(-1) - - def get_exists(self): - if self.days == 0: - body = '''{{ - "query": {{ - "bool": {{ - "must": [ - {{ "match": {{ "project_name": "{}" }} }}, - {{ "match": {{ "case_name": "{}" }} }} - ] - }} - }} - }}'''.format(self.project, self.case) - elif self.days > 0: - body = '''{{ - "query": {{ - "bool": {{ - "must": [ - {{ "match": {{ "project_name": "{}" }} }}, - {{ "match": {{ "case_name": "{}" }} }} - ], - "filter": {{ - "range": {{ - "start_date": {{ "gte": "now-{}d" }} - }} - }} - }} - }} - }}'''.format(self.project, self.case, self.days) - else: - raise Exception('Update days must be non-negative') - self.existed_docs = elastic_access.get_docs( - self.elastic_url, self.creds, body) - return self - - def publish(self): - fdocs = None - try: - with open(tmp_docs_file) as fdocs: - for doc_line in fdocs: - DocumentPublisher(json.loads(doc_line), - self.fmt, - self.existed_docs, - self.creds, - self.elastic_url).format().publish() - finally: - if fdocs: - fdocs.close() - self._remove() - - def _remove(self): - if os.path.exists(tmp_docs_file): - os.remove(tmp_docs_file) - - -def main(): - for project, case_dicts in testcases.testcases_yaml.items(): - for case_dict in case_dicts: - case = case_dict.get('name') - fmt = testcases.compose_format(case_dict.get('format')) - DocumentsPublisher(project, - case, - fmt, - args.latest_days, - CONF.index_url, - CONF.es_creds).export().get_exists().publish() diff --git a/utils/test/dashboard/dashboard/qtip/__init__.py b/utils/test/dashboard/dashboard/qtip/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/utils/test/dashboard/dashboard/qtip/format.py b/utils/test/dashboard/dashboard/qtip/format.py deleted file mode 100644 index b78fa5b9b..000000000 --- a/utils/test/dashboard/dashboard/qtip/format.py +++ /dev/null @@ -1,19 +0,0 @@ -#! /usr/bin/env python - - -def format_qpi(testcase): - """ - Look for these and leave any of those: - details.index - - If none are present, then return False - """ - details = testcase['details'] - if 'index' not in details: - return False - - for key, value in details.items(): - if key != 'index': - del details[key] - - return True diff --git a/utils/test/dashboard/dashboard/qtip/testcases.yaml b/utils/test/dashboard/dashboard/qtip/testcases.yaml deleted file mode 100644 index dfa9cc2db..000000000 --- a/utils/test/dashboard/dashboard/qtip/testcases.yaml +++ /dev/null @@ -1,29 +0,0 @@ ---- -qtip: - - - name: compute_test_suite - format: qpi - test_family: compute - visualizations: - - - name: qpi - fields: - - field: details.index - - - name: network_test_suite - test_family: network - format: qpi - visualizations: - - - name: qpi - fields: - - field: details.index - - - name: storage_test_suite - format: qpi - test_family: storage - visualizations: - - - name: qpi - fields: - - field: details.index diff --git a/utils/test/dashboard/etc/config.ini b/utils/test/dashboard/etc/config.ini deleted file mode 100644 index 77adc1687..000000000 --- a/utils/test/dashboard/etc/config.ini +++ /dev/null @@ -1,10 +0,0 @@ -# to add a new parameter in the config file, -# the CONF object in config.ini must be updated -[elastic] -url = http://localhost:9200 -index = testapi/results -creds = - -[kibana] -url = http://10.63.243.17:5601/app/kibana -js_path = /usr/share/nginx/html/kibana_dashboards/conf.js diff --git a/utils/test/dashboard/install.sh b/utils/test/dashboard/install.sh deleted file mode 100755 index 9fd60d916..000000000 --- a/utils/test/dashboard/install.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -usage=" -Script to install dashboard automatically. -This script should be run under root. - -usage: - bash $(basename "$0") [-h|--help] [-t ] - -where: - -h|--help show this help text - -p|--project project dashboard - " - -# Parse parameters -while [[ $# > 0 ]] - do - key="$1" - case $key in - -h|--help) - echo "$usage" - exit 0 - shift - ;; - -p|--project) - PROJECT="$2" - shift - ;; - *) - echo "unknown option $1 $2" - exit 1 - ;; - esac - shift # past argument or value -done - -if [[ $(whoami) != "root" ]]; then - echo "Error: This script must be run as root!" - exit 1 -fi - -if [ -z ${PROJECT+x} ]; then - echo "project must be specified" - exit 1 -fi - -if [ $PROJECT != "functest" ] && [ $PROJECT != "qtip" ];then - echo "unsupported project $PROJECT" - exit 1 -fi - -cp -f dashboard/$PROJECT/format.py dashboard/mongo2elastic -cp -f dashboard/$PROJECT/testcases.yaml etc/ -python setup.py install diff --git a/utils/test/dashboard/kibana_cleanup.py b/utils/test/dashboard/kibana_cleanup.py deleted file mode 100644 index 7e3662c29..000000000 --- a/utils/test/dashboard/kibana_cleanup.py +++ /dev/null @@ -1,46 +0,0 @@ -#! /usr/bin/env python -import logging -import urlparse - -import argparse - -from dashboard.common import elastic_access - -logger = logging.getLogger('clear_kibana') -logger.setLevel(logging.DEBUG) -file_handler = logging.FileHandler('/var/log/{}.log'.format('clear_kibana')) -file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: ' - '%(message)s')) -logger.addHandler(file_handler) - - -def delete_all(url, es_creds): - ids = elastic_access.get_docs(url, es_creds, body=None, field='_id') - for id in ids: - del_url = '/'.join([url, id]) - elastic_access.delete_docs(del_url, es_creds) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser( - description=('Delete saved kibana searches, ' - 'visualizations and dashboards')) - parser.add_argument('-e', '--elasticsearch-url', - default='http://localhost:9200', - help=('the url of elasticsearch, ' - 'defaults to http://localhost:9200')) - - parser.add_argument('-u', '--elasticsearch-username', default=None, - help=('The username with password for elasticsearch ' - 'in format username:password')) - - args = parser.parse_args() - base_elastic_url = args.elasticsearch_url - es_creds = args.elasticsearch_username - - urls = (urlparse.urljoin(base_elastic_url, '/.kibana/visualization'), - urlparse.urljoin(base_elastic_url, '/.kibana/dashboard'), - urlparse.urljoin(base_elastic_url, '/.kibana/search')) - - for url in urls: - delete_all(url, es_creds) diff --git a/utils/test/dashboard/setup.cfg b/utils/test/dashboard/setup.cfg deleted file mode 100644 index 859dcc0fb..000000000 --- a/utils/test/dashboard/setup.cfg +++ /dev/null @@ -1,44 +0,0 @@ -[metadata] -name = dashboard -summary = Test Result Collector -description-file = - README.rst -author = SerenaFeng -author-email = feng.xiaowei@zte.com.cn -#home-page = http://www.opnfv.org/ -license = Apache-2.0 -classifier = - Environment :: opnfv - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - -[global] -setup-hooks = - pbr.hooks.setup_hook - -[files] -packages = - dashboard -package_data = - dashboard = - elastic2kibana/templates/*.* -data_files = - /etc/dashboard = - etc/config.ini - etc/testcases.yaml - -[entry_points] -console_scripts = - dashboard_mongo2elastic = dashboard.mongo2elastic.main:main - dashboard_elastic2kibana = dashboard.elastic2kibana.main:main - -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 - diff --git a/utils/test/dashboard/setup.py b/utils/test/dashboard/setup.py deleted file mode 100644 index 59637a509..000000000 --- a/utils/test/dashboard/setup.py +++ /dev/null @@ -1,8 +0,0 @@ -import setuptools - -__author__ = 'serena' - - -setuptools.setup( - setup_requires=['pbr>=1.8'], - pbr=True) diff --git a/utils/test/opts/one_click_deploy.py b/utils/test/opts/one_click_deploy.py deleted file mode 100644 index 074827021..000000000 --- a/utils/test/opts/one_click_deploy.py +++ /dev/null @@ -1,67 +0,0 @@ -import argparse -import os - -from jinja2 import Environment - -DOCKER_COMPOSE_FILE = './docker-compose.yml' -DOCKER_COMPOSE_TEMPLATE = """ -version: '2' -services: - mongo: - image: mongo:3.2.1 - container_name: opnfv-mongo - testapi: - image: opnfv/testapi:latest - container_name: opnfv-testapi - environment: - - mongodb_url=mongodb://mongo:27017/ - - base_url={{ vars.base_url }} - ports: - - "{{ vars.testapi_port }}:8000" - links: - - mongo - reporting: - image: opnfv/reporting:latest - container_name: opnfv-reporting - ports: - - "{{ vars.reporting_port }}:8000" -""" - - -def render_docker_compose(testapi_port, reporting_port, testapi_base_url): - vars = { - "testapi_port": testapi_port, - "reporting_port": reporting_port, - "base_url": testapi_base_url, - } - yml = Environment().from_string(DOCKER_COMPOSE_TEMPLATE).render(vars=vars) - with open(DOCKER_COMPOSE_FILE, 'w') as f: - f.write(yml) - f.close() - - -def main(args): - render_docker_compose(args.testapi_port, - args.reporting_port, - args.testapi_base_url) - os.system('docker-compose -f {} up -d'.format(DOCKER_COMPOSE_FILE)) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Backup MongoDBs') - parser.add_argument('-tp', '--testapi-port', - type=int, - required=False, - default=8082, - help='testapi exposed port') - parser.add_argument('-tl', '--testapi-base-url', - type=str, - required=True, - help='testapi exposed base-url') - parser.add_argument('-rp', '--reporting-port', - type=int, - required=False, - default=8084, - help='reporting exposed port') - - main(parser.parse_args()) diff --git a/utils/test/opts/watchdog.sh b/utils/test/opts/watchdog.sh deleted file mode 100644 index 51868d709..000000000 --- a/utils/test/opts/watchdog.sh +++ /dev/null @@ -1,162 +0,0 @@ -# * -# 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. * - -# This script checks if deployments are working or and then -# starts the specified containers in case one of the containers -# crash. The only solution is restarting docker as of now. - -#!/bin/bash - -## List of modules -modules=(testapi reporting) - -## Ports of the modules -declare -A ports=( ["testapi"]="8082" ["reporting"]="8084") - -## Urls to check if the modules are deployed or not ? -declare -A urls=( ["testapi"]="http://testresults.opnfv.org/test/" \ - ["reporting"]="http://testresults.opnfv.org/reporting/index.html") - -### Functions related to checking. - -function is_deploying() { - xml=$(curl -m10 "https://build.opnfv.org/ci/job/${1}-automate-docker-deploy-master/lastBuild/api/xml?depth=1") - building=$(grep -oPm1 "(?<=)[^<]+" <<< "$xml") - if [[ $building == "false" ]] - then - false - else - true - fi -} - -function get_docker_status() { - status=$(service docker status | sed -n 3p | cut -d ' ' -f5) - echo -e "Docker status: $status" - if [ $status = "active" ] - then - true - else - false - fi -} - -function check_connectivity() { - echo "Checking $1 connection : $2" - cmd=`curl --head -m10 --request GET ${2} | grep '200 OK' > /dev/null` - rc=$? - if [[ $rc == 0 ]]; then - true - else - false - fi -} - -function check_modules() { - echo -e "Checking modules" - failed_modules=() - for module in "${modules[@]}" - do - if ! check_connectivity $module "${urls[$module]}"; then - if ! is_deploying $module; then - echo -e "$module failed" - failed_modules+=($module) - fi - fi - done - if [ ! -z "$failed_modules" ]; then - echo -e "Failed Modules: $failed_modules" - false - else - echo -e "All modules working good" - exit 0 - fi -} - -### Functions related fixes. - -function restart_docker_fix() { - echo -e "Running restart_docker_fix" - service docker restart - start_containers_fix "${modules[@]}" -} - -function docker_proxy_fix() { - echo -e "Running docker_proxy_fix" - fix_modules=("${@}") - for module in "${fix_modules[@]}" - do - echo -e "Kill docker proxy and restart containers" - pid=$(netstat -nlp | grep :${ports[$module]} | awk '{print $7}' | cut -d'/' -f1) - echo $pid - if [ ! -z "$pid" ]; then - kill $pid - start_container_fix $module - fi - done -} - -function start_containers_fix() { - start_modules=("${@}") - for module in "${start_modules[@]}" - do - start_container_fix $module - done -} - -function start_container_fix() { - echo -e "Starting a container $module" - sudo docker restart $module - sleep 5 - if ! check_connectivity $module "${urls[$module]}"; then - echo -e "Starting an old container $module_old" - sudo docker restart $module"_old" - sleep 5 - fi -} - -### Main Flow - -echo -e -echo -e "WatchDog Started" -echo -e -echo -e `date "+%Y-%m-%d %H:%M:%S.%N"` -echo -e - -## If the problem is related to docker daemon - -if ! get_docker_status; then - restart_docker_fix - if ! check_modules; then - echo -e "Watchdog failed while restart_docker_fix" - fi - exit -fi - -## If the problem is related to docker proxy - -if ! check_modules; then - docker_proxy_fix "${failed_modules[@]}" -fi - -## If any other problem : restart docker - -if ! check_modules; then - restart_docker_fix -fi - -## If nothing works out - -if ! check_modules; then - echo -e "Watchdog failed" -fi - -sudo docker ps -sudo docker images \ No newline at end of file diff --git a/utils/test/reporting/3rd_party/css/font-awesome.min.css b/utils/test/reporting/3rd_party/css/font-awesome.min.css deleted file mode 100644 index 9b27f8ea8..000000000 --- a/utils/test/reporting/3rd_party/css/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.6.3 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.6.3');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.6.3') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.6.3') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.6.3') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.6.3') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.6.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/utils/test/reporting/3rd_party/css/ie8.css b/utils/test/reporting/3rd_party/css/ie8.css deleted file mode 100644 index 8110fe537..000000000 --- a/utils/test/reporting/3rd_party/css/ie8.css +++ /dev/null @@ -1,73 +0,0 @@ -/* - Phantom by HTML5 UP - html5up.net | @ajlkn - Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) -*/ - -/* Form */ - - form .field { - float: none !important; - width: 100% !important; - padding-left: 0 !important; - } - -/* Button */ - - input[type="submit"], - input[type="reset"], - input[type="button"], - button, - .button { - border: solid 2px #585858 !important; - } - - input[type="submit"]:hover, - input[type="reset"]:hover, - input[type="button"]:hover, - button:hover, - .button:hover { - border-color: #f2849e !important; - } - - input[type="submit"].special, - input[type="reset"].special, - input[type="button"].special, - button.special, - .button.special { - border: none !important; - } - -/* Tiles */ - - .tiles article > .image:before, .tiles article > .image:after { - display: none; - } - -/* Header */ - - #header .logo .symbol { - display: none; - } - - #header nav ul li a[href="#menu"] { - text-indent: 0; - width: auto; - font-size: 0.8em; - } - - #header nav ul li a[href="#menu"]:before, #header nav ul li a[href="#menu"]:after { - display: none; - } - -/* Footer */ - - #footer > .inner section { - width: 50%; - margin-left: 3em; - } - - #footer > .inner section:first-child { - margin-left: 0; - width: 40%; - } \ No newline at end of file diff --git a/utils/test/reporting/3rd_party/css/ie9.css b/utils/test/reporting/3rd_party/css/ie9.css deleted file mode 100644 index 2c1a43b88..000000000 --- a/utils/test/reporting/3rd_party/css/ie9.css +++ /dev/null @@ -1,40 +0,0 @@ -/* - Phantom by HTML5 UP - html5up.net | @ajlkn - Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) -*/ - -/* Tiles */ - - .tiles:after { - content: ''; - display: block; - clear: both; - } - - .tiles article { - float: left; - } - - .tiles article > a { - padding-top: 50%; - margin-top: -1.75em; - } - - body:not(.is-touch) .tiles article:hover > .image { - -moz-transform: none; - -webkit-transform: none; - -ms-transform: none; - transform: none; - } - -/* Footer */ - - #footer > .inner section { - float: left; - } - - #footer > .inner .copyright { - clear: both; - padding-top: 4em; - } \ No newline at end of file diff --git a/utils/test/reporting/3rd_party/css/main.css b/utils/test/reporting/3rd_party/css/main.css deleted file mode 100644 index b74d484cb..000000000 --- a/utils/test/reporting/3rd_party/css/main.css +++ /dev/null @@ -1,3356 +0,0 @@ -@import url(font-awesome.min.css); -@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,700,900"); - -/* - Phantom by HTML5 UP - html5up.net | @ajlkn - Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) -*/ - -/* Reset */ - - html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; - } - - article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { - display: block; - } - - body { - line-height: 1; - } - - ol, ul { - list-style: none; - } - - blockquote, q { - quotes: none; - } - - blockquote:before, blockquote:after, q:before, q:after { - content: ''; - content: none; - } - - table { - border-collapse: collapse; - border-spacing: 0; - } - - body { - -webkit-text-size-adjust: none; - } - -/* Box Model */ - - *, *:before, *:after { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - } - -/* Grid */ - - .row { - border-bottom: solid 1px transparent; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - } - - .row > * { - float: left; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - } - - .row:after, .row:before { - content: ''; - display: block; - clear: both; - height: 0; - } - - .row.uniform > * > :first-child { - margin-top: 0; - } - - .row.uniform > * > :last-child { - margin-bottom: 0; - } - - .row.\30 \25 > * { - padding: 0 0 0 0em; - } - - .row.\30 \25 { - margin: 0 0 -1px 0em; - } - - .row.uniform.\30 \25 > * { - padding: 0em 0 0 0em; - } - - .row.uniform.\30 \25 { - margin: 0em 0 -1px 0em; - } - - .row > * { - padding: 0 0 0 2em; - } - - .row { - margin: 0 0 -1px -2em; - } - - .row.uniform > * { - padding: 2em 0 0 2em; - } - - .row.uniform { - margin: -2em 0 -1px -2em; - } - - .row.\32 00\25 > * { - padding: 0 0 0 4em; - } - - .row.\32 00\25 { - margin: 0 0 -1px -4em; - } - - .row.uniform.\32 00\25 > * { - padding: 4em 0 0 4em; - } - - .row.uniform.\32 00\25 { - margin: -4em 0 -1px -4em; - } - - .row.\31 50\25 > * { - padding: 0 0 0 3em; - } - - .row.\31 50\25 { - margin: 0 0 -1px -3em; - } - - .row.uniform.\31 50\25 > * { - padding: 3em 0 0 3em; - } - - .row.uniform.\31 50\25 { - margin: -3em 0 -1px -3em; - } - - .row.\35 0\25 > * { - padding: 0 0 0 1em; - } - - .row.\35 0\25 { - margin: 0 0 -1px -1em; - } - - .row.uniform.\35 0\25 > * { - padding: 1em 0 0 1em; - } - - .row.uniform.\35 0\25 { - margin: -1em 0 -1px -1em; - } - - .row.\32 5\25 > * { - padding: 0 0 0 0.5em; - } - - .row.\32 5\25 { - margin: 0 0 -1px -0.5em; - } - - .row.uniform.\32 5\25 > * { - padding: 0.5em 0 0 0.5em; - } - - .row.uniform.\32 5\25 { - margin: -0.5em 0 -1px -0.5em; - } - - .\31 2u, .\31 2u\24 { - width: 100%; - clear: none; - margin-left: 0; - } - - .\31 1u, .\31 1u\24 { - width: 91.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 0u, .\31 0u\24 { - width: 83.3333333333%; - clear: none; - margin-left: 0; - } - - .\39 u, .\39 u\24 { - width: 75%; - clear: none; - margin-left: 0; - } - - .\38 u, .\38 u\24 { - width: 66.6666666667%; - clear: none; - margin-left: 0; - } - - .\37 u, .\37 u\24 { - width: 58.3333333333%; - clear: none; - margin-left: 0; - } - - .\36 u, .\36 u\24 { - width: 50%; - clear: none; - margin-left: 0; - } - - .\35 u, .\35 u\24 { - width: 41.6666666667%; - clear: none; - margin-left: 0; - } - - .\34 u, .\34 u\24 { - width: 33.3333333333%; - clear: none; - margin-left: 0; - } - - .\33 u, .\33 u\24 { - width: 25%; - clear: none; - margin-left: 0; - } - - .\32 u, .\32 u\24 { - width: 16.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 u, .\31 u\24 { - width: 8.3333333333%; - clear: none; - margin-left: 0; - } - - .\31 2u\24 + *, - .\31 1u\24 + *, - .\31 0u\24 + *, - .\39 u\24 + *, - .\38 u\24 + *, - .\37 u\24 + *, - .\36 u\24 + *, - .\35 u\24 + *, - .\34 u\24 + *, - .\33 u\24 + *, - .\32 u\24 + *, - .\31 u\24 + * { - clear: left; - } - - .\-11u { - margin-left: 91.66667%; - } - - .\-10u { - margin-left: 83.33333%; - } - - .\-9u { - margin-left: 75%; - } - - .\-8u { - margin-left: 66.66667%; - } - - .\-7u { - margin-left: 58.33333%; - } - - .\-6u { - margin-left: 50%; - } - - .\-5u { - margin-left: 41.66667%; - } - - .\-4u { - margin-left: 33.33333%; - } - - .\-3u { - margin-left: 25%; - } - - .\-2u { - margin-left: 16.66667%; - } - - .\-1u { - margin-left: 8.33333%; - } - - @media screen and (max-width: 1680px) { - - .row > * { - padding: 0 0 0 2em; - } - - .row { - margin: 0 0 -1px -2em; - } - - .row.uniform > * { - padding: 2em 0 0 2em; - } - - .row.uniform { - margin: -2em 0 -1px -2em; - } - - .row.\32 00\25 > * { - padding: 0 0 0 4em; - } - - .row.\32 00\25 { - margin: 0 0 -1px -4em; - } - - .row.uniform.\32 00\25 > * { - padding: 4em 0 0 4em; - } - - .row.uniform.\32 00\25 { - margin: -4em 0 -1px -4em; - } - - .row.\31 50\25 > * { - padding: 0 0 0 3em; - } - - .row.\31 50\25 { - margin: 0 0 -1px -3em; - } - - .row.uniform.\31 50\25 > * { - padding: 3em 0 0 3em; - } - - .row.uniform.\31 50\25 { - margin: -3em 0 -1px -3em; - } - - .row.\35 0\25 > * { - padding: 0 0 0 1em; - } - - .row.\35 0\25 { - margin: 0 0 -1px -1em; - } - - .row.uniform.\35 0\25 > * { - padding: 1em 0 0 1em; - } - - .row.uniform.\35 0\25 { - margin: -1em 0 -1px -1em; - } - - .row.\32 5\25 > * { - padding: 0 0 0 0.5em; - } - - .row.\32 5\25 { - margin: 0 0 -1px -0.5em; - } - - .row.uniform.\32 5\25 > * { - padding: 0.5em 0 0 0.5em; - } - - .row.uniform.\32 5\25 { - margin: -0.5em 0 -1px -0.5em; - } - - .\31 2u\28xlarge\29, .\31 2u\24\28xlarge\29 { - width: 100%; - clear: none; - margin-left: 0; - } - - .\31 1u\28xlarge\29, .\31 1u\24\28xlarge\29 { - width: 91.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 0u\28xlarge\29, .\31 0u\24\28xlarge\29 { - width: 83.3333333333%; - clear: none; - margin-left: 0; - } - - .\39 u\28xlarge\29, .\39 u\24\28xlarge\29 { - width: 75%; - clear: none; - margin-left: 0; - } - - .\38 u\28xlarge\29, .\38 u\24\28xlarge\29 { - width: 66.6666666667%; - clear: none; - margin-left: 0; - } - - .\37 u\28xlarge\29, .\37 u\24\28xlarge\29 { - width: 58.3333333333%; - clear: none; - margin-left: 0; - } - - .\36 u\28xlarge\29, .\36 u\24\28xlarge\29 { - width: 50%; - clear: none; - margin-left: 0; - } - - .\35 u\28xlarge\29, .\35 u\24\28xlarge\29 { - width: 41.6666666667%; - clear: none; - margin-left: 0; - } - - .\34 u\28xlarge\29, .\34 u\24\28xlarge\29 { - width: 33.3333333333%; - clear: none; - margin-left: 0; - } - - .\33 u\28xlarge\29, .\33 u\24\28xlarge\29 { - width: 25%; - clear: none; - margin-left: 0; - } - - .\32 u\28xlarge\29, .\32 u\24\28xlarge\29 { - width: 16.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 u\28xlarge\29, .\31 u\24\28xlarge\29 { - width: 8.3333333333%; - clear: none; - margin-left: 0; - } - - .\31 2u\24\28xlarge\29 + *, - .\31 1u\24\28xlarge\29 + *, - .\31 0u\24\28xlarge\29 + *, - .\39 u\24\28xlarge\29 + *, - .\38 u\24\28xlarge\29 + *, - .\37 u\24\28xlarge\29 + *, - .\36 u\24\28xlarge\29 + *, - .\35 u\24\28xlarge\29 + *, - .\34 u\24\28xlarge\29 + *, - .\33 u\24\28xlarge\29 + *, - .\32 u\24\28xlarge\29 + *, - .\31 u\24\28xlarge\29 + * { - clear: left; - } - - .\-11u\28xlarge\29 { - margin-left: 91.66667%; - } - - .\-10u\28xlarge\29 { - margin-left: 83.33333%; - } - - .\-9u\28xlarge\29 { - margin-left: 75%; - } - - .\-8u\28xlarge\29 { - margin-left: 66.66667%; - } - - .\-7u\28xlarge\29 { - margin-left: 58.33333%; - } - - .\-6u\28xlarge\29 { - margin-left: 50%; - } - - .\-5u\28xlarge\29 { - margin-left: 41.66667%; - } - - .\-4u\28xlarge\29 { - margin-left: 33.33333%; - } - - .\-3u\28xlarge\29 { - margin-left: 25%; - } - - .\-2u\28xlarge\29 { - margin-left: 16.66667%; - } - - .\-1u\28xlarge\29 { - margin-left: 8.33333%; - } - - } - - @media screen and (max-width: 1280px) { - - .row > * { - padding: 0 0 0 2em; - } - - .row { - margin: 0 0 -1px -2em; - } - - .row.uniform > * { - padding: 2em 0 0 2em; - } - - .row.uniform { - margin: -2em 0 -1px -2em; - } - - .row.\32 00\25 > * { - padding: 0 0 0 4em; - } - - .row.\32 00\25 { - margin: 0 0 -1px -4em; - } - - .row.uniform.\32 00\25 > * { - padding: 4em 0 0 4em; - } - - .row.uniform.\32 00\25 { - margin: -4em 0 -1px -4em; - } - - .row.\31 50\25 > * { - padding: 0 0 0 3em; - } - - .row.\31 50\25 { - margin: 0 0 -1px -3em; - } - - .row.uniform.\31 50\25 > * { - padding: 3em 0 0 3em; - } - - .row.uniform.\31 50\25 { - margin: -3em 0 -1px -3em; - } - - .row.\35 0\25 > * { - padding: 0 0 0 1em; - } - - .row.\35 0\25 { - margin: 0 0 -1px -1em; - } - - .row.uniform.\35 0\25 > * { - padding: 1em 0 0 1em; - } - - .row.uniform.\35 0\25 { - margin: -1em 0 -1px -1em; - } - - .row.\32 5\25 > * { - padding: 0 0 0 0.5em; - } - - .row.\32 5\25 { - margin: 0 0 -1px -0.5em; - } - - .row.uniform.\32 5\25 > * { - padding: 0.5em 0 0 0.5em; - } - - .row.uniform.\32 5\25 { - margin: -0.5em 0 -1px -0.5em; - } - - .\31 2u\28large\29, .\31 2u\24\28large\29 { - width: 100%; - clear: none; - margin-left: 0; - } - - .\31 1u\28large\29, .\31 1u\24\28large\29 { - width: 91.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 0u\28large\29, .\31 0u\24\28large\29 { - width: 83.3333333333%; - clear: none; - margin-left: 0; - } - - .\39 u\28large\29, .\39 u\24\28large\29 { - width: 75%; - clear: none; - margin-left: 0; - } - - .\38 u\28large\29, .\38 u\24\28large\29 { - width: 66.6666666667%; - clear: none; - margin-left: 0; - } - - .\37 u\28large\29, .\37 u\24\28large\29 { - width: 58.3333333333%; - clear: none; - margin-left: 0; - } - - .\36 u\28large\29, .\36 u\24\28large\29 { - width: 50%; - clear: none; - margin-left: 0; - } - - .\35 u\28large\29, .\35 u\24\28large\29 { - width: 41.6666666667%; - clear: none; - margin-left: 0; - } - - .\34 u\28large\29, .\34 u\24\28large\29 { - width: 33.3333333333%; - clear: none; - margin-left: 0; - } - - .\33 u\28large\29, .\33 u\24\28large\29 { - width: 25%; - clear: none; - margin-left: 0; - } - - .\32 u\28large\29, .\32 u\24\28large\29 { - width: 16.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 u\28large\29, .\31 u\24\28large\29 { - width: 8.3333333333%; - clear: none; - margin-left: 0; - } - - .\31 2u\24\28large\29 + *, - .\31 1u\24\28large\29 + *, - .\31 0u\24\28large\29 + *, - .\39 u\24\28large\29 + *, - .\38 u\24\28large\29 + *, - .\37 u\24\28large\29 + *, - .\36 u\24\28large\29 + *, - .\35 u\24\28large\29 + *, - .\34 u\24\28large\29 + *, - .\33 u\24\28large\29 + *, - .\32 u\24\28large\29 + *, - .\31 u\24\28large\29 + * { - clear: left; - } - - .\-11u\28large\29 { - margin-left: 91.66667%; - } - - .\-10u\28large\29 { - margin-left: 83.33333%; - } - - .\-9u\28large\29 { - margin-left: 75%; - } - - .\-8u\28large\29 { - margin-left: 66.66667%; - } - - .\-7u\28large\29 { - margin-left: 58.33333%; - } - - .\-6u\28large\29 { - margin-left: 50%; - } - - .\-5u\28large\29 { - margin-left: 41.66667%; - } - - .\-4u\28large\29 { - margin-left: 33.33333%; - } - - .\-3u\28large\29 { - margin-left: 25%; - } - - .\-2u\28large\29 { - margin-left: 16.66667%; - } - - .\-1u\28large\29 { - margin-left: 8.33333%; - } - - } - - @media screen and (max-width: 980px) { - - .row > * { - padding: 0 0 0 1.5em; - } - - .row { - margin: 0 0 -1px -1.5em; - } - - .row.uniform > * { - padding: 1.5em 0 0 1.5em; - } - - .row.uniform { - margin: -1.5em 0 -1px -1.5em; - } - - .row.\32 00\25 > * { - padding: 0 0 0 3em; - } - - .row.\32 00\25 { - margin: 0 0 -1px -3em; - } - - .row.uniform.\32 00\25 > * { - padding: 3em 0 0 3em; - } - - .row.uniform.\32 00\25 { - margin: -3em 0 -1px -3em; - } - - .row.\31 50\25 > * { - padding: 0 0 0 2.25em; - } - - .row.\31 50\25 { - margin: 0 0 -1px -2.25em; - } - - .row.uniform.\31 50\25 > * { - padding: 2.25em 0 0 2.25em; - } - - .row.uniform.\31 50\25 { - margin: -2.25em 0 -1px -2.25em; - } - - .row.\35 0\25 > * { - padding: 0 0 0 0.75em; - } - - .row.\35 0\25 { - margin: 0 0 -1px -0.75em; - } - - .row.uniform.\35 0\25 > * { - padding: 0.75em 0 0 0.75em; - } - - .row.uniform.\35 0\25 { - margin: -0.75em 0 -1px -0.75em; - } - - .row.\32 5\25 > * { - padding: 0 0 0 0.375em; - } - - .row.\32 5\25 { - margin: 0 0 -1px -0.375em; - } - - .row.uniform.\32 5\25 > * { - padding: 0.375em 0 0 0.375em; - } - - .row.uniform.\32 5\25 { - margin: -0.375em 0 -1px -0.375em; - } - - .\31 2u\28medium\29, .\31 2u\24\28medium\29 { - width: 100%; - clear: none; - margin-left: 0; - } - - .\31 1u\28medium\29, .\31 1u\24\28medium\29 { - width: 91.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 0u\28medium\29, .\31 0u\24\28medium\29 { - width: 83.3333333333%; - clear: none; - margin-left: 0; - } - - .\39 u\28medium\29, .\39 u\24\28medium\29 { - width: 75%; - clear: none; - margin-left: 0; - } - - .\38 u\28medium\29, .\38 u\24\28medium\29 { - width: 66.6666666667%; - clear: none; - margin-left: 0; - } - - .\37 u\28medium\29, .\37 u\24\28medium\29 { - width: 58.3333333333%; - clear: none; - margin-left: 0; - } - - .\36 u\28medium\29, .\36 u\24\28medium\29 { - width: 50%; - clear: none; - margin-left: 0; - } - - .\35 u\28medium\29, .\35 u\24\28medium\29 { - width: 41.6666666667%; - clear: none; - margin-left: 0; - } - - .\34 u\28medium\29, .\34 u\24\28medium\29 { - width: 33.3333333333%; - clear: none; - margin-left: 0; - } - - .\33 u\28medium\29, .\33 u\24\28medium\29 { - width: 25%; - clear: none; - margin-left: 0; - } - - .\32 u\28medium\29, .\32 u\24\28medium\29 { - width: 16.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 u\28medium\29, .\31 u\24\28medium\29 { - width: 8.3333333333%; - clear: none; - margin-left: 0; - } - - .\31 2u\24\28medium\29 + *, - .\31 1u\24\28medium\29 + *, - .\31 0u\24\28medium\29 + *, - .\39 u\24\28medium\29 + *, - .\38 u\24\28medium\29 + *, - .\37 u\24\28medium\29 + *, - .\36 u\24\28medium\29 + *, - .\35 u\24\28medium\29 + *, - .\34 u\24\28medium\29 + *, - .\33 u\24\28medium\29 + *, - .\32 u\24\28medium\29 + *, - .\31 u\24\28medium\29 + * { - clear: left; - } - - .\-11u\28medium\29 { - margin-left: 91.66667%; - } - - .\-10u\28medium\29 { - margin-left: 83.33333%; - } - - .\-9u\28medium\29 { - margin-left: 75%; - } - - .\-8u\28medium\29 { - margin-left: 66.66667%; - } - - .\-7u\28medium\29 { - margin-left: 58.33333%; - } - - .\-6u\28medium\29 { - margin-left: 50%; - } - - .\-5u\28medium\29 { - margin-left: 41.66667%; - } - - .\-4u\28medium\29 { - margin-left: 33.33333%; - } - - .\-3u\28medium\29 { - margin-left: 25%; - } - - .\-2u\28medium\29 { - margin-left: 16.66667%; - } - - .\-1u\28medium\29 { - margin-left: 8.33333%; - } - - } - - @media screen and (max-width: 736px) { - - .row > * { - padding: 0 0 0 1em; - } - - .row { - margin: 0 0 -1px -1em; - } - - .row.uniform > * { - padding: 1em 0 0 1em; - } - - .row.uniform { - margin: -1em 0 -1px -1em; - } - - .row.\32 00\25 > * { - padding: 0 0 0 2em; - } - - .row.\32 00\25 { - margin: 0 0 -1px -2em; - } - - .row.uniform.\32 00\25 > * { - padding: 2em 0 0 2em; - } - - .row.uniform.\32 00\25 { - margin: -2em 0 -1px -2em; - } - - .row.\31 50\25 > * { - padding: 0 0 0 1.5em; - } - - .row.\31 50\25 { - margin: 0 0 -1px -1.5em; - } - - .row.uniform.\31 50\25 > * { - padding: 1.5em 0 0 1.5em; - } - - .row.uniform.\31 50\25 { - margin: -1.5em 0 -1px -1.5em; - } - - .row.\35 0\25 > * { - padding: 0 0 0 0.5em; - } - - .row.\35 0\25 { - margin: 0 0 -1px -0.5em; - } - - .row.uniform.\35 0\25 > * { - padding: 0.5em 0 0 0.5em; - } - - .row.uniform.\35 0\25 { - margin: -0.5em 0 -1px -0.5em; - } - - .row.\32 5\25 > * { - padding: 0 0 0 0.25em; - } - - .row.\32 5\25 { - margin: 0 0 -1px -0.25em; - } - - .row.uniform.\32 5\25 > * { - padding: 0.25em 0 0 0.25em; - } - - .row.uniform.\32 5\25 { - margin: -0.25em 0 -1px -0.25em; - } - - .\31 2u\28small\29, .\31 2u\24\28small\29 { - width: 100%; - clear: none; - margin-left: 0; - } - - .\31 1u\28small\29, .\31 1u\24\28small\29 { - width: 91.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 0u\28small\29, .\31 0u\24\28small\29 { - width: 83.3333333333%; - clear: none; - margin-left: 0; - } - - .\39 u\28small\29, .\39 u\24\28small\29 { - width: 75%; - clear: none; - margin-left: 0; - } - - .\38 u\28small\29, .\38 u\24\28small\29 { - width: 66.6666666667%; - clear: none; - margin-left: 0; - } - - .\37 u\28small\29, .\37 u\24\28small\29 { - width: 58.3333333333%; - clear: none; - margin-left: 0; - } - - .\36 u\28small\29, .\36 u\24\28small\29 { - width: 50%; - clear: none; - margin-left: 0; - } - - .\35 u\28small\29, .\35 u\24\28small\29 { - width: 41.6666666667%; - clear: none; - margin-left: 0; - } - - .\34 u\28small\29, .\34 u\24\28small\29 { - width: 33.3333333333%; - clear: none; - margin-left: 0; - } - - .\33 u\28small\29, .\33 u\24\28small\29 { - width: 25%; - clear: none; - margin-left: 0; - } - - .\32 u\28small\29, .\32 u\24\28small\29 { - width: 16.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 u\28small\29, .\31 u\24\28small\29 { - width: 8.3333333333%; - clear: none; - margin-left: 0; - } - - .\31 2u\24\28small\29 + *, - .\31 1u\24\28small\29 + *, - .\31 0u\24\28small\29 + *, - .\39 u\24\28small\29 + *, - .\38 u\24\28small\29 + *, - .\37 u\24\28small\29 + *, - .\36 u\24\28small\29 + *, - .\35 u\24\28small\29 + *, - .\34 u\24\28small\29 + *, - .\33 u\24\28small\29 + *, - .\32 u\24\28small\29 + *, - .\31 u\24\28small\29 + * { - clear: left; - } - - .\-11u\28small\29 { - margin-left: 91.66667%; - } - - .\-10u\28small\29 { - margin-left: 83.33333%; - } - - .\-9u\28small\29 { - margin-left: 75%; - } - - .\-8u\28small\29 { - margin-left: 66.66667%; - } - - .\-7u\28small\29 { - margin-left: 58.33333%; - } - - .\-6u\28small\29 { - margin-left: 50%; - } - - .\-5u\28small\29 { - margin-left: 41.66667%; - } - - .\-4u\28small\29 { - margin-left: 33.33333%; - } - - .\-3u\28small\29 { - margin-left: 25%; - } - - .\-2u\28small\29 { - margin-left: 16.66667%; - } - - .\-1u\28small\29 { - margin-left: 8.33333%; - } - - } - - @media screen and (max-width: 480px) { - - .row > * { - padding: 0 0 0 1em; - } - - .row { - margin: 0 0 -1px -1em; - } - - .row.uniform > * { - padding: 1em 0 0 1em; - } - - .row.uniform { - margin: -1em 0 -1px -1em; - } - - .row.\32 00\25 > * { - padding: 0 0 0 2em; - } - - .row.\32 00\25 { - margin: 0 0 -1px -2em; - } - - .row.uniform.\32 00\25 > * { - padding: 2em 0 0 2em; - } - - .row.uniform.\32 00\25 { - margin: -2em 0 -1px -2em; - } - - .row.\31 50\25 > * { - padding: 0 0 0 1.5em; - } - - .row.\31 50\25 { - margin: 0 0 -1px -1.5em; - } - - .row.uniform.\31 50\25 > * { - padding: 1.5em 0 0 1.5em; - } - - .row.uniform.\31 50\25 { - margin: -1.5em 0 -1px -1.5em; - } - - .row.\35 0\25 > * { - padding: 0 0 0 0.5em; - } - - .row.\35 0\25 { - margin: 0 0 -1px -0.5em; - } - - .row.uniform.\35 0\25 > * { - padding: 0.5em 0 0 0.5em; - } - - .row.uniform.\35 0\25 { - margin: -0.5em 0 -1px -0.5em; - } - - .row.\32 5\25 > * { - padding: 0 0 0 0.25em; - } - - .row.\32 5\25 { - margin: 0 0 -1px -0.25em; - } - - .row.uniform.\32 5\25 > * { - padding: 0.25em 0 0 0.25em; - } - - .row.uniform.\32 5\25 { - margin: -0.25em 0 -1px -0.25em; - } - - .\31 2u\28xsmall\29, .\31 2u\24\28xsmall\29 { - width: 100%; - clear: none; - margin-left: 0; - } - - .\31 1u\28xsmall\29, .\31 1u\24\28xsmall\29 { - width: 91.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 0u\28xsmall\29, .\31 0u\24\28xsmall\29 { - width: 83.3333333333%; - clear: none; - margin-left: 0; - } - - .\39 u\28xsmall\29, .\39 u\24\28xsmall\29 { - width: 75%; - clear: none; - margin-left: 0; - } - - .\38 u\28xsmall\29, .\38 u\24\28xsmall\29 { - width: 66.6666666667%; - clear: none; - margin-left: 0; - } - - .\37 u\28xsmall\29, .\37 u\24\28xsmall\29 { - width: 58.3333333333%; - clear: none; - margin-left: 0; - } - - .\36 u\28xsmall\29, .\36 u\24\28xsmall\29 { - width: 50%; - clear: none; - margin-left: 0; - } - - .\35 u\28xsmall\29, .\35 u\24\28xsmall\29 { - width: 41.6666666667%; - clear: none; - margin-left: 0; - } - - .\34 u\28xsmall\29, .\34 u\24\28xsmall\29 { - width: 33.3333333333%; - clear: none; - margin-left: 0; - } - - .\33 u\28xsmall\29, .\33 u\24\28xsmall\29 { - width: 25%; - clear: none; - margin-left: 0; - } - - .\32 u\28xsmall\29, .\32 u\24\28xsmall\29 { - width: 16.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 u\28xsmall\29, .\31 u\24\28xsmall\29 { - width: 8.3333333333%; - clear: none; - margin-left: 0; - } - - .\31 2u\24\28xsmall\29 + *, - .\31 1u\24\28xsmall\29 + *, - .\31 0u\24\28xsmall\29 + *, - .\39 u\24\28xsmall\29 + *, - .\38 u\24\28xsmall\29 + *, - .\37 u\24\28xsmall\29 + *, - .\36 u\24\28xsmall\29 + *, - .\35 u\24\28xsmall\29 + *, - .\34 u\24\28xsmall\29 + *, - .\33 u\24\28xsmall\29 + *, - .\32 u\24\28xsmall\29 + *, - .\31 u\24\28xsmall\29 + * { - clear: left; - } - - .\-11u\28xsmall\29 { - margin-left: 91.66667%; - } - - .\-10u\28xsmall\29 { - margin-left: 83.33333%; - } - - .\-9u\28xsmall\29 { - margin-left: 75%; - } - - .\-8u\28xsmall\29 { - margin-left: 66.66667%; - } - - .\-7u\28xsmall\29 { - margin-left: 58.33333%; - } - - .\-6u\28xsmall\29 { - margin-left: 50%; - } - - .\-5u\28xsmall\29 { - margin-left: 41.66667%; - } - - .\-4u\28xsmall\29 { - margin-left: 33.33333%; - } - - .\-3u\28xsmall\29 { - margin-left: 25%; - } - - .\-2u\28xsmall\29 { - margin-left: 16.66667%; - } - - .\-1u\28xsmall\29 { - margin-left: 8.33333%; - } - - } - - @media screen and (max-width: 360px) { - - .row > * { - padding: 0 0 0 1em; - } - - .row { - margin: 0 0 -1px -1em; - } - - .row.uniform > * { - padding: 1em 0 0 1em; - } - - .row.uniform { - margin: -1em 0 -1px -1em; - } - - .row.\32 00\25 > * { - padding: 0 0 0 2em; - } - - .row.\32 00\25 { - margin: 0 0 -1px -2em; - } - - .row.uniform.\32 00\25 > * { - padding: 2em 0 0 2em; - } - - .row.uniform.\32 00\25 { - margin: -2em 0 -1px -2em; - } - - .row.\31 50\25 > * { - padding: 0 0 0 1.5em; - } - - .row.\31 50\25 { - margin: 0 0 -1px -1.5em; - } - - .row.uniform.\31 50\25 > * { - padding: 1.5em 0 0 1.5em; - } - - .row.uniform.\31 50\25 { - margin: -1.5em 0 -1px -1.5em; - } - - .row.\35 0\25 > * { - padding: 0 0 0 0.5em; - } - - .row.\35 0\25 { - margin: 0 0 -1px -0.5em; - } - - .row.uniform.\35 0\25 > * { - padding: 0.5em 0 0 0.5em; - } - - .row.uniform.\35 0\25 { - margin: -0.5em 0 -1px -0.5em; - } - - .row.\32 5\25 > * { - padding: 0 0 0 0.25em; - } - - .row.\32 5\25 { - margin: 0 0 -1px -0.25em; - } - - .row.uniform.\32 5\25 > * { - padding: 0.25em 0 0 0.25em; - } - - .row.uniform.\32 5\25 { - margin: -0.25em 0 -1px -0.25em; - } - - .\31 2u\28xxsmall\29, .\31 2u\24\28xxsmall\29 { - width: 100%; - clear: none; - margin-left: 0; - } - - .\31 1u\28xxsmall\29, .\31 1u\24\28xxsmall\29 { - width: 91.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 0u\28xxsmall\29, .\31 0u\24\28xxsmall\29 { - width: 83.3333333333%; - clear: none; - margin-left: 0; - } - - .\39 u\28xxsmall\29, .\39 u\24\28xxsmall\29 { - width: 75%; - clear: none; - margin-left: 0; - } - - .\38 u\28xxsmall\29, .\38 u\24\28xxsmall\29 { - width: 66.6666666667%; - clear: none; - margin-left: 0; - } - - .\37 u\28xxsmall\29, .\37 u\24\28xxsmall\29 { - width: 58.3333333333%; - clear: none; - margin-left: 0; - } - - .\36 u\28xxsmall\29, .\36 u\24\28xxsmall\29 { - width: 50%; - clear: none; - margin-left: 0; - } - - .\35 u\28xxsmall\29, .\35 u\24\28xxsmall\29 { - width: 41.6666666667%; - clear: none; - margin-left: 0; - } - - .\34 u\28xxsmall\29, .\34 u\24\28xxsmall\29 { - width: 33.3333333333%; - clear: none; - margin-left: 0; - } - - .\33 u\28xxsmall\29, .\33 u\24\28xxsmall\29 { - width: 25%; - clear: none; - margin-left: 0; - } - - .\32 u\28xxsmall\29, .\32 u\24\28xxsmall\29 { - width: 16.6666666667%; - clear: none; - margin-left: 0; - } - - .\31 u\28xxsmall\29, .\31 u\24\28xxsmall\29 { - width: 8.3333333333%; - clear: none; - margin-left: 0; - } - - .\31 2u\24\28xxsmall\29 + *, - .\31 1u\24\28xxsmall\29 + *, - .\31 0u\24\28xxsmall\29 + *, - .\39 u\24\28xxsmall\29 + *, - .\38 u\24\28xxsmall\29 + *, - .\37 u\24\28xxsmall\29 + *, - .\36 u\24\28xxsmall\29 + *, - .\35 u\24\28xxsmall\29 + *, - .\34 u\24\28xxsmall\29 + *, - .\33 u\24\28xxsmall\29 + *, - .\32 u\24\28xxsmall\29 + *, - .\31 u\24\28xxsmall\29 + * { - clear: left; - } - - .\-11u\28xxsmall\29 { - margin-left: 91.66667%; - } - - .\-10u\28xxsmall\29 { - margin-left: 83.33333%; - } - - .\-9u\28xxsmall\29 { - margin-left: 75%; - } - - .\-8u\28xxsmall\29 { - margin-left: 66.66667%; - } - - .\-7u\28xxsmall\29 { - margin-left: 58.33333%; - } - - .\-6u\28xxsmall\29 { - margin-left: 50%; - } - - .\-5u\28xxsmall\29 { - margin-left: 41.66667%; - } - - .\-4u\28xxsmall\29 { - margin-left: 33.33333%; - } - - .\-3u\28xxsmall\29 { - margin-left: 25%; - } - - .\-2u\28xxsmall\29 { - margin-left: 16.66667%; - } - - .\-1u\28xxsmall\29 { - margin-left: 8.33333%; - } - - } - -/* Basic */ - - @-ms-viewport { - width: device-width; - } - - body { - -ms-overflow-style: scrollbar; - } - - @media screen and (max-width: 480px) { - - html, body { - min-width: 320px; - } - - } - - body { - background: #ffffff; - } - - body.is-loading *, body.is-loading *:before, body.is-loading *:after { - -moz-animation: none !important; - -webkit-animation: none !important; - -ms-animation: none !important; - animation: none !important; - -moz-transition: none !important; - -webkit-transition: none !important; - -ms-transition: none !important; - transition: none !important; - } - -/* Type */ - - body, input, select, textarea { - color: #585858; - font-family: "Source Sans Pro", Helvetica, sans-serif; - font-size: 16pt; - font-weight: 300; - line-height: 1.75; - } - - @media screen and (max-width: 1680px) { - - body, input, select, textarea { - font-size: 14pt; - } - - } - - @media screen and (max-width: 1280px) { - - body, input, select, textarea { - font-size: 12pt; - } - - } - - a { - -moz-transition: border-bottom-color 0.2s ease, color 0.2s ease; - -webkit-transition: border-bottom-color 0.2s ease, color 0.2s ease; - -ms-transition: border-bottom-color 0.2s ease, color 0.2s ease; - transition: border-bottom-color 0.2s ease, color 0.2s ease; - text-decoration: none; - color: #585858; - border-bottom: dotted 1px rgba(88, 88, 88, 0.5); - } - - a:hover { - border-bottom-color: transparent; - color: #f2849e !important; - } - - strong, b { - font-weight: 900; - } - - em, i { - font-style: italic; - } - - p { - margin: 0 0 2em 0; - } - - h1 { - font-size: 2.75em; - font-weight: 700; - line-height: 1.3; - margin: 0 0 1em 0; - letter-spacing: -0.035em; - } - - h1 a { - color: inherit; - } - - @media screen and (max-width: 736px) { - - h1 { - font-size: 2em; - margin: 0 0 1em 0; - } - - } - - @media screen and (max-width: 360px) { - - h1 { - font-size: 1.75em; - } - - } - - h2, h3, h4, h5, h6 { - font-weight: 900; - line-height: 1.5; - margin: 0 0 2em 0; - text-transform: uppercase; - letter-spacing: 0.35em; - } - - h2 a, h3 a, h4 a, h5 a, h6 a { - color: inherit; - } - - h2 { - font-size: 1.1em; - } - - h3 { - font-size: 1em; - } - - h4 { - font-size: 0.8em; - } - - h5 { - font-size: 0.8em; - } - - h6 { - font-size: 0.8em; - } - - @media screen and (max-width: 980px) { - - h1 br, h2 br, h3 br, h4 br, h5 br, h6 br { - display: none; - } - - } - - @media screen and (max-width: 736px) { - - h2 { - font-size: 1em; - } - - h3 { - font-size: 0.8em; - } - - } - - sub { - font-size: 0.8em; - position: relative; - top: 0.5em; - } - - sup { - font-size: 0.8em; - position: relative; - top: -0.5em; - } - - blockquote { - border-left: solid 4px #c9c9c9; - font-style: italic; - margin: 0 0 2em 0; - padding: 0.5em 0 0.5em 2em; - } - - code { - background: rgba(144, 144, 144, 0.075); - border-radius: 4px; - border: solid 1px #c9c9c9; - font-family: "Courier New", monospace; - font-size: 0.9em; - margin: 0 0.25em; - padding: 0.25em 0.65em; - } - - pre { - -webkit-overflow-scrolling: touch; - font-family: "Courier New", monospace; - font-size: 0.9em; - margin: 0 0 2em 0; - } - - pre code { - display: block; - line-height: 1.75; - padding: 1em 1.5em; - overflow-x: auto; - } - - hr { - border: 0; - border-bottom: solid 1px #c9c9c9; - margin: 2em 0; - } - - hr.major { - margin: 3em 0; - } - - .align-left { - text-align: left; - } - - .align-center { - text-align: center; - } - - .align-right { - text-align: right; - } - -/* Section/Article */ - - section.special, article.special { - text-align: center; - } - - header p { - margin-top: -1em; - } - - @media screen and (max-width: 736px) { - - header p { - margin-top: 0; - } - - } - -/* Icon */ - - .icon { - text-decoration: none; - border-bottom: none; - position: relative; - } - - .icon:before { - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - font-family: FontAwesome; - font-style: normal; - font-weight: normal; - text-transform: none !important; - } - - .icon > .label { - display: none; - } - - .icon.style2 { - -moz-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, border-color 0.2s ease-in-out; - -webkit-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, border-color 0.2s ease-in-out; - -ms-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, border-color 0.2s ease-in-out; - transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, border-color 0.2s ease-in-out; - background-color: transparent; - border: solid 1px #c9c9c9; - border-radius: 4px; - width: 2.65em; - height: 2.65em; - display: inline-block; - text-align: center; - line-height: 2.65em; - color: inherit; - } - - .icon.style2:before { - font-size: 1.1em; - } - - .icon.style2:hover { - color: #f2849e; - border-color: #f2849e; - } - - .icon.style2:active { - background-color: rgba(242, 132, 158, 0.1); - } - -/* List */ - - ol { - list-style: decimal; - margin: 0 0 2em 0; - padding-left: 1.25em; - } - - ol li { - padding-left: 0.25em; - } - - ul { - list-style: disc; - margin: 0 0 2em 0; - padding-left: 1em; - } - - ul li { - padding-left: 0.5em; - } - - ul.alt { - list-style: none; - padding-left: 0; - } - - ul.alt li { - border-top: solid 1px #c9c9c9; - padding: 0.5em 0; - } - - ul.alt li:first-child { - border-top: 0; - padding-top: 0; - } - - ul.icons { - cursor: default; - list-style: none; - padding-left: 0; - margin: -1em 0 2em -1em; - } - - ul.icons li { - display: inline-block; - padding: 1em 0 0 1em; - } - - ul.actions { - cursor: default; - list-style: none; - padding-left: 0; - } - - ul.actions li { - display: inline-block; - padding: 0 1em 0 0; - vertical-align: middle; - } - - ul.actions li:last-child { - padding-right: 0; - } - - ul.actions.small li { - padding: 0 0.5em 0 0; - } - - ul.actions.vertical li { - display: block; - padding: 1em 0 0 0; - } - - ul.actions.vertical li:first-child { - padding-top: 0; - } - - ul.actions.vertical li > * { - margin-bottom: 0; - } - - ul.actions.vertical.small li { - padding: 0.5em 0 0 0; - } - - ul.actions.vertical.small li:first-child { - padding-top: 0; - } - - ul.actions.fit { - display: table; - margin-left: -1em; - padding: 0; - table-layout: fixed; - width: calc(100% + 1em); - } - - ul.actions.fit li { - display: table-cell; - padding: 0 0 0 1em; - } - - ul.actions.fit li > * { - margin-bottom: 0; - } - - ul.actions.fit.small { - margin-left: -0.5em; - width: calc(100% + 0.5em); - } - - ul.actions.fit.small li { - padding: 0 0 0 0.5em; - } - - @media screen and (max-width: 480px) { - - ul.actions { - margin: 0 0 2em 0; - } - - ul.actions li { - padding: 1em 0 0 0; - display: block; - text-align: center; - width: 100%; - } - - ul.actions li:first-child { - padding-top: 0; - } - - ul.actions li > * { - width: 100%; - margin: 0 !important; - } - - ul.actions li > *.icon:before { - margin-left: -2em; - } - - ul.actions.small li { - padding: 0.5em 0 0 0; - } - - ul.actions.small li:first-child { - padding-top: 0; - } - - } - - dl { - margin: 0 0 2em 0; - } - - dl dt { - display: block; - font-weight: 900; - margin: 0 0 1em 0; - } - - dl dd { - margin-left: 2em; - } - -/* Form */ - - form { - margin: -1em 0 2em 0; - } - - form:after { - content: ''; - display: block; - clear: both; - height: 1px; - } - - form .field { - position: relative; - float: left; - margin: 0 0 1.3em 0; - vertical-align: top; - width: 100%; - } - - form .half { - width: calc(50% + 1em) !important; - padding-left: 2em; - } - - form .half.first { - width: calc(50% - 1em) !important; - padding-left: 0; - } - - form :last-child { - margin-bottom: 0; - } - - form .half:nth-last-child(2) { - margin-bottom: 0; - } - - form .actions { - position: relative; - clear: both; - padding-top: 1em; - } - - @media screen and (max-width: 480px) { - - form .half { - width: 100% !important; - padding-left: 0; - } - - form .half.first { - width: 100% !important; - padding-left: 0; - } - - form .half:nth-last-child(2) { - margin: 0 0 1.3em 0; - } - - } - - label { - display: block; - font-size: 0.9em; - font-weight: 900; - margin: 0 0 1em 0; - } - - input[type="text"], - input[type="password"], - input[type="email"], - input[type="tel"], - select, - textarea { - -moz-appearance: none; - -webkit-appearance: none; - -ms-appearance: none; - appearance: none; - background-color: transparent; - border: none; - border-radius: 0; - border-bottom: solid 1px #c9c9c9; - color: inherit; - display: block; - outline: 0; - padding: 0; - text-decoration: none; - width: 100%; - } - - input[type="text"]:invalid, - input[type="password"]:invalid, - input[type="email"]:invalid, - input[type="tel"]:invalid, - select:invalid, - textarea:invalid { - box-shadow: none; - } - - input[type="text"]:focus, - input[type="password"]:focus, - input[type="email"]:focus, - input[type="tel"]:focus, - select:focus, - textarea:focus { - border-bottom-color: #f2849e; - box-shadow: inset 0 -1px 0 0 #f2849e; - } - - .select-wrapper { - text-decoration: none; - display: block; - position: relative; - } - - .select-wrapper:before { - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - font-family: FontAwesome; - font-style: normal; - font-weight: normal; - text-transform: none !important; - } - - .select-wrapper:before { - color: #c9c9c9; - content: '\f078'; - display: block; - height: 3em; - line-height: 3em; - pointer-events: none; - position: absolute; - right: 0; - text-align: center; - top: 0; - width: 3em; - } - - .select-wrapper select::-ms-expand { - display: none; - } - - input[type="text"], - input[type="password"], - input[type="email"], - select { - height: 3em; - } - - textarea { - padding: 0; - min-height: 3.75em; - } - - input[type="checkbox"], - input[type="radio"] { - -moz-appearance: none; - -webkit-appearance: none; - -ms-appearance: none; - appearance: none; - display: block; - float: left; - margin-right: -2em; - opacity: 0; - width: 1em; - z-index: -1; - } - - input[type="checkbox"] + label, - input[type="radio"] + label { - text-decoration: none; - color: #585858; - cursor: pointer; - display: inline-block; - font-size: 1em; - font-weight: 300; - padding-left: 2.55em; - padding-right: 0.75em; - position: relative; - } - - input[type="checkbox"] + label:before, - input[type="radio"] + label:before { - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - font-family: FontAwesome; - font-style: normal; - font-weight: normal; - text-transform: none !important; - } - - input[type="checkbox"] + label:before, - input[type="radio"] + label:before { - border-radius: 4px; - border: solid 1px #c9c9c9; - content: ''; - display: inline-block; - height: 1.8em; - left: 0; - line-height: 1.725em; - position: absolute; - text-align: center; - top: 0; - width: 1.8em; - } - - input[type="checkbox"]:checked + label:before, - input[type="radio"]:checked + label:before { - background: #585858; - border-color: #585858; - color: #ffffff; - content: '\f00c'; - } - - input[type="checkbox"]:focus + label:before, - input[type="radio"]:focus + label:before { - border-color: #f2849e; - box-shadow: 0 0 0 1px #f2849e; - } - - input[type="checkbox"] + label:before { - border-radius: 4px; - } - - input[type="radio"] + label:before { - border-radius: 100%; - } - -/* Box */ - - .box { - border-radius: 4px; - border: solid 1px #c9c9c9; - margin-bottom: 2em; - padding: 1.5em; - } - - .box > :last-child, - .box > :last-child > :last-child, - .box > :last-child > :last-child > :last-child { - margin-bottom: 0; - } - - .box.alt { - border: 0; - border-radius: 0; - padding: 0; - } - -/* Image */ - - .image { - border-radius: 4px; - border: 0; - display: inline-block; - position: relative; - } - - .image img { - border-radius: 4px; - display: block; - } - - .image.left, .image.right { - max-width: 40%; - } - - .image.left img, .image.right img { - width: 100%; - } - - .image.left { - float: left; - padding: 0 1.5em 1em 0; - top: 0.25em; - } - - .image.right { - float: right; - padding: 0 0 1em 1.5em; - top: 0.25em; - } - - .image.fit { - display: block; - margin: 0 0 2em 0; - width: 100%; - } - - .image.fit img { - width: 100%; - } - - .image.main { - display: block; - margin: 0 0 3em 0; - width: 100%; - } - - .image.main img { - width: 100%; - } - - @media screen and (max-width: 736px) { - - .image.main { - margin: 0 0 2em 0; - } - - } - -/* Table */ - - .table-wrapper { - -webkit-overflow-scrolling: touch; - overflow-x: auto; - } - - table { - margin: 0 0 2em 0; - width: 100%; - } - - table tbody tr { - border: solid 1px #c9c9c9; - border-left: 0; - border-right: 0; - } - - table tbody tr:nth-child(2n + 1) { - background-color: rgba(144, 144, 144, 0.075); - } - - table td { - padding: 0.75em 0.75em; - } - - table th { - font-size: 0.9em; - font-weight: 900; - padding: 0 0.75em 0.75em 0.75em; - text-align: left; - } - - table thead { - border-bottom: solid 2px #c9c9c9; - } - - table tfoot { - border-top: solid 2px #c9c9c9; - } - - table.alt { - border-collapse: separate; - } - - table.alt tbody tr td { - border: solid 1px #c9c9c9; - border-left-width: 0; - border-top-width: 0; - } - - table.alt tbody tr td:first-child { - border-left-width: 1px; - } - - table.alt tbody tr:first-child td { - border-top-width: 1px; - } - - table.alt thead { - border-bottom: 0; - } - - table.alt tfoot { - border-top: 0; - } - -/* Button */ - - input[type="submit"], - input[type="reset"], - input[type="button"], - button, - .button { - -moz-appearance: none; - -webkit-appearance: none; - -ms-appearance: none; - appearance: none; - -moz-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, box-shadow 0.2s ease-in-out; - -webkit-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, box-shadow 0.2s ease-in-out; - -ms-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, box-shadow 0.2s ease-in-out; - transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, box-shadow 0.2s ease-in-out; - background-color: transparent; - border-radius: 4px; - border: 0; - box-shadow: inset 0 0 0 2px #585858; - color: #585858 !important; - cursor: pointer; - display: inline-block; - font-size: 0.8em; - font-weight: 900; - height: 3.5em; - letter-spacing: 0.35em; - line-height: 3.45em; - overflow: hidden; - padding: 0 1.25em 0 1.6em; - text-align: center; - text-decoration: none; - text-overflow: ellipsis; - text-transform: uppercase; - white-space: nowrap; - } - - input[type="submit"].icon:before, - input[type="reset"].icon:before, - input[type="button"].icon:before, - button.icon:before, - .button.icon:before { - margin-right: 0.5em; - } - - input[type="submit"].fit, - input[type="reset"].fit, - input[type="button"].fit, - button.fit, - .button.fit { - display: block; - margin: 0 0 1em 0; - width: 100%; - } - - input[type="submit"]:hover, - input[type="reset"]:hover, - input[type="button"]:hover, - button:hover, - .button:hover { - color: #f2849e !important; - box-shadow: inset 0 0 0 2px #f2849e; - } - - input[type="submit"]:active, - input[type="reset"]:active, - input[type="button"]:active, - button:active, - .button:active { - background-color: rgba(242, 132, 158, 0.1); - } - - input[type="submit"].small, - input[type="reset"].small, - input[type="button"].small, - button.small, - .button.small { - font-size: 0.6em; - } - - input[type="submit"].big, - input[type="reset"].big, - input[type="button"].big, - button.big, - .button.big { - font-size: 1em; - } - - input[type="submit"].special, - input[type="reset"].special, - input[type="button"].special, - button.special, - .button.special { - box-shadow: none; - background-color: #585858; - color: #ffffff !important; - } - - input[type="submit"].special:hover, - input[type="reset"].special:hover, - input[type="button"].special:hover, - button.special:hover, - .button.special:hover { - background-color: #f2849e; - } - - input[type="submit"].special:active, - input[type="reset"].special:active, - input[type="button"].special:active, - button.special:active, - .button.special:active { - background-color: #ee5f81; - } - - input[type="submit"].disabled, input[type="submit"]:disabled, - input[type="reset"].disabled, - input[type="reset"]:disabled, - input[type="button"].disabled, - input[type="button"]:disabled, - button.disabled, - button:disabled, - .button.disabled, - .button:disabled { - -moz-pointer-events: none; - -webkit-pointer-events: none; - -ms-pointer-events: none; - pointer-events: none; - opacity: 0.25; - } - -/* Tiles */ - - .tiles { - display: -moz-flex; - display: -webkit-flex; - display: -ms-flex; - display: flex; - -moz-flex-wrap: wrap; - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - postiion: relative; - margin: -2.5em 0 0 -2.5em; - } - - .tiles article { - -moz-transition: -moz-transform 0.5s ease, opacity 0.5s ease; - -webkit-transition: -webkit-transform 0.5s ease, opacity 0.5s ease; - -ms-transition: -ms-transform 0.5s ease, opacity 0.5s ease; - transition: transform 0.5s ease, opacity 0.5s ease; - position: relative; - width: calc(33.33333% - 2.5em); - margin: 2.5em 0 0 2.5em; - } - - .tiles article > .image { - -moz-transition: -moz-transform 0.5s ease; - -webkit-transition: -webkit-transform 0.5s ease; - -ms-transition: -ms-transform 0.5s ease; - transition: transform 0.5s ease; - position: relative; - display: block; - width: 100%; - border-radius: 4px; - overflow: hidden; - } - - .tiles article > .image img { - display: block; - width: 100%; - } - - .tiles article > .image:before { - -moz-pointer-events: none; - -webkit-pointer-events: none; - -ms-pointer-events: none; - pointer-events: none; - -moz-transition: background-color 0.5s ease, opacity 0.5s ease; - -webkit-transition: background-color 0.5s ease, opacity 0.5s ease; - -ms-transition: background-color 0.5s ease, opacity 0.5s ease; - transition: background-color 0.5s ease, opacity 0.5s ease; - content: ''; - display: block; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - opacity: 1.0; - z-index: 1; - opacity: 0.8; - } - - .tiles article > .image:after { - -moz-pointer-events: none; - -webkit-pointer-events: none; - -ms-pointer-events: none; - pointer-events: none; - -moz-transition: opacity 0.5s ease; - -webkit-transition: opacity 0.5s ease; - -ms-transition: opacity 0.5s ease; - transition: opacity 0.5s ease; - content: ''; - display: block; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cstyle%3Eline %7B stroke-width: 0.25px%3B stroke: %23ffffff%3B %7D%3C/style%3E%3Cline x1='0' y1='0' x2='100' y2='100' /%3E%3Cline x1='100' y1='0' x2='0' y2='100' /%3E%3C/svg%3E"); - background-position: center; - background-repeat: no-repeat; - background-size: 100% 100%; - opacity: 0.25; - z-index: 2; - } - - .tiles article > a { - display: -moz-flex; - display: -webkit-flex; - display: -ms-flex; - display: flex; - -moz-flex-direction: column; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -moz-align-items: center; - -webkit-align-items: center; - -ms-align-items: center; - align-items: center; - -moz-justify-content: center; - -webkit-justify-content: center; - -ms-justify-content: center; - justify-content: center; - -moz-transition: background-color 0.5s ease, -moz-transform 0.5s ease; - -webkit-transition: background-color 0.5s ease, -webkit-transform 0.5s ease; - -ms-transition: background-color 0.5s ease, -ms-transform 0.5s ease; - transition: background-color 0.5s ease, transform 0.5s ease; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - padding: 1em; - border-radius: 4px; - border-bottom: 0; - color: #ffffff; - text-align: center; - text-decoration: none; - z-index: 3; - } - - .tiles article > a > :last-child { - margin: 0; - } - - .tiles article > a:hover { - color: #ffffff !important; - } - - .tiles article > a h2 { - margin: 0; - } - - .tiles article > a .content { - -moz-transition: max-height 0.5s ease, opacity 0.5s ease; - -webkit-transition: max-height 0.5s ease, opacity 0.5s ease; - -ms-transition: max-height 0.5s ease, opacity 0.5s ease; - transition: max-height 0.5s ease, opacity 0.5s ease; - width: 100%; - max-height: 0; - line-height: 1.5; - margin-top: 0.35em; - opacity: 0; - } - - .tiles article > a .content > :last-child { - margin-bottom: 0; - } - - .tiles article.style1 > .image:before { - background-color: #f2849e; - } - - .tiles article.style2 > .image:before { - background-color: #7ecaf6; - } - - .tiles article.style3 > .image:before { - background-color: #7bd0c1; - } - - .tiles article.style4 > .image:before { - background-color: #c75b9b; - } - - .tiles article.style5 > .image:before { - background-color: #ae85ca; - } - - .tiles article.style6 > .image:before { - background-color: #8499e7; - } - - body:not(.is-touch) .tiles article:hover > .image { - -moz-transform: scale(1.1); - -webkit-transform: scale(1.1); - -ms-transform: scale(1.1); - transform: scale(1.1); - } - - body:not(.is-touch) .tiles article:hover > .image:before { - background-color: #333333; - opacity: 0.35; - } - - body:not(.is-touch) .tiles article:hover > .image:after { - opacity: 0; - } - - body:not(.is-touch) .tiles article:hover .content { - max-height: 15em; - opacity: 1; - } - - * + .tiles { - margin-top: 2em; - } - - body.is-loading .tiles article { - -moz-transform: scale(0.9); - -webkit-transform: scale(0.9); - -ms-transform: scale(0.9); - transform: scale(0.9); - opacity: 0; - } - - body.is-touch .tiles article .content { - max-height: 15em; - opacity: 1; - } - - @media screen and (max-width: 1280px) { - - .tiles { - margin: -1.25em 0 0 -1.25em; - } - - .tiles article { - width: calc(33.33333% - 1.25em); - margin: 1.25em 0 0 1.25em; - } - - } - - @media screen and (max-width: 980px) { - - .tiles { - margin: -2.5em 0 0 -2.5em; - } - - .tiles article { - width: calc(50% - 2.5em); - margin: 2.5em 0 0 2.5em; - } - - } - - @media screen and (max-width: 736px) { - - .tiles { - margin: -1.25em 0 0 -1.25em; - } - - .tiles article { - width: calc(50% - 1.25em); - margin: 1.25em 0 0 1.25em; - } - - .tiles article:hover > .image { - -moz-transform: scale(1.0); - -webkit-transform: scale(1.0); - -ms-transform: scale(1.0); - transform: scale(1.0); - } - - } - - @media screen and (max-width: 480px) { - - .tiles { - margin: 0; - } - - .tiles article { - width: 100%; - margin: 1.25em 0 0 0; - } - - } - -/* Header */ - - #header { - padding: 3em 0 0.1em 0 ; - } - - #header .logo { - display: block; - border-bottom: 0; - color: inherit; - font-weight: 900; - letter-spacing: 0.35em; - margin: 0 0 2.5em 0; - text-decoration: none; - text-transform: uppercase; - display: inline-block; - } - - #header .logo > * { - display: inline-block; - vertical-align: middle; - } - - #header .logo .symbol { - margin-right: 0.65em; - } - - #header .logo .symbol img { - display: block; - width: 2em; - height: 2em; - } - - #header nav { - position: fixed; - right: 2em; - top: 2em; - z-index: 10000; - } - - #header nav ul { - display: -moz-flex; - display: -webkit-flex; - display: -ms-flex; - display: flex; - -moz-align-items: center; - -webkit-align-items: center; - -ms-align-items: center; - align-items: center; - list-style: none; - margin: 0; - padding: 0; - } - - #header nav ul li { - display: block; - padding: 0; - } - - #header nav ul li a { - display: block; - position: relative; - height: 3em; - line-height: 3em; - padding: 0 1.5em; - background-color: rgba(255, 255, 255, 0.5); - border-radius: 4px; - border: 0; - font-size: 0.8em; - font-weight: 900; - letter-spacing: 0.35em; - text-transform: uppercase; - } - - #header nav ul li a[href="#menu"] { - -webkit-tap-highlight-color: transparent; - width: 4em; - text-indent: 4em; - font-size: 1em; - overflow: hidden; - padding: 0; - white-space: nowrap; - } - - #header nav ul li a[href="#menu"]:before, #header nav ul li a[href="#menu"]:after { - -moz-transition: opacity 0.2s ease; - -webkit-transition: opacity 0.2s ease; - -ms-transition: opacity 0.2s ease; - transition: opacity 0.2s ease; - content: ''; - display: block; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-position: center; - background-repeat: no-repeat; - background-size: 2em 2em; - } - - #header nav ul li a[href="#menu"]:before { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cstyle%3Eline %7B stroke-width: 8px%3B stroke: %23f2849e%3B %7D%3C/style%3E%3Cline x1='0' y1='25' x2='100' y2='25' /%3E%3Cline x1='0' y1='50' x2='100' y2='50' /%3E%3Cline x1='0' y1='75' x2='100' y2='75' /%3E%3C/svg%3E"); - opacity: 0; - } - - #header nav ul li a[href="#menu"]:after { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cstyle%3Eline %7B stroke-width: 8px%3B stroke: %23585858%3B %7D%3C/style%3E%3Cline x1='0' y1='25' x2='100' y2='25' /%3E%3Cline x1='0' y1='50' x2='100' y2='50' /%3E%3Cline x1='0' y1='75' x2='100' y2='75' /%3E%3C/svg%3E"); - opacity: 1; - } - - #header nav ul li a[href="#menu"]:hover:before { - opacity: 1; - } - - #header nav ul li a[href="#menu"]:hover:after { - opacity: 0; - } - - @media screen and (max-width: 736px) { - - #header { - padding: 4em 0 0.1em 0 ; - } - - #header nav { - right: 0.5em; - top: 0.5em; - } - - #header nav ul li a[href="#menu"]:before, #header nav ul li a[href="#menu"]:after { - background-size: 1.5em 1.5em; - } - - } - -/* Menu */ - - #wrapper { - -moz-transition: opacity 0.45s ease; - -webkit-transition: opacity 0.45s ease; - -ms-transition: opacity 0.45s ease; - transition: opacity 0.45s ease; - opacity: 1; - } - - #menu { - -moz-transform: translateX(22em); - -webkit-transform: translateX(22em); - -ms-transform: translateX(22em); - transform: translateX(22em); - -moz-transition: -moz-transform 0.45s ease, visibility 0.45s; - -webkit-transition: -webkit-transform 0.45s ease, visibility 0.45s; - -ms-transition: -ms-transform 0.45s ease, visibility 0.45s; - transition: transform 0.45s ease, visibility 0.45s; - position: fixed; - top: 0; - right: 0; - width: 22em; - max-width: 80%; - height: 100%; - -webkit-overflow-scrolling: touch; - background: #585858; - color: #ffffff; - cursor: default; - visibility: hidden; - z-index: 10002; - } - - #menu > .inner { - -moz-transition: opacity 0.45s ease; - -webkit-transition: opacity 0.45s ease; - -ms-transition: opacity 0.45s ease; - transition: opacity 0.45s ease; - -webkit-overflow-scrolling: touch; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - padding: 2.75em; - opacity: 0; - overflow-y: auto; - } - - #menu > .inner > ul { - list-style: none; - margin: 0 0 1em 0; - padding: 0; - } - - #menu > .inner > ul > li { - padding: 0; - border-top: solid 1px rgba(255, 255, 255, 0.15); - } - - #menu > .inner > ul > li a { - display: block; - padding: 1em 0; - line-height: 1.5; - border: 0; - color: inherit; - } - - #menu > .inner > ul > li:first-child { - border-top: 0; - margin-top: -1em; - } - - #menu > .close { - -moz-transition: opacity 0.45s ease, -moz-transform 0.45s ease; - -webkit-transition: opacity 0.45s ease, -webkit-transform 0.45s ease; - -ms-transition: opacity 0.45s ease, -ms-transform 0.45s ease; - transition: opacity 0.45s ease, transform 0.45s ease; - -moz-transform: scale(0.25) rotate(180deg); - -webkit-transform: scale(0.25) rotate(180deg); - -ms-transform: scale(0.25) rotate(180deg); - transform: scale(0.25) rotate(180deg); - -webkit-tap-highlight-color: transparent; - display: block; - position: absolute; - top: 2em; - left: -6em; - width: 6em; - text-indent: 6em; - height: 3em; - border: 0; - font-size: 1em; - opacity: 0; - overflow: hidden; - padding: 0; - white-space: nowrap; - } - - #menu > .close:before, #menu > .close:after { - -moz-transition: opacity 0.2s ease; - -webkit-transition: opacity 0.2s ease; - -ms-transition: opacity 0.2s ease; - transition: opacity 0.2s ease; - content: ''; - display: block; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-position: center; - background-repeat: no-repeat; - background-size: 2em 2em; - } - - #menu > .close:before { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cstyle%3Eline %7B stroke-width: 8px%3B stroke: %23f2849e%3B %7D%3C/style%3E%3Cline x1='15' y1='15' x2='85' y2='85' /%3E%3Cline x1='85' y1='15' x2='15' y2='85' /%3E%3C/svg%3E"); - opacity: 0; - } - - #menu > .close:after { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cstyle%3Eline %7B stroke-width: 8px%3B stroke: %23585858%3B %7D%3C/style%3E%3Cline x1='15' y1='15' x2='85' y2='85' /%3E%3Cline x1='85' y1='15' x2='15' y2='85' /%3E%3C/svg%3E"); - opacity: 1; - } - - #menu > .close:hover:before { - opacity: 1; - } - - #menu > .close:hover:after { - opacity: 0; - } - - @media screen and (max-width: 736px) { - - #menu { - -moz-transform: translateX(16.5em); - -webkit-transform: translateX(16.5em); - -ms-transform: translateX(16.5em); - transform: translateX(16.5em); - width: 16.5em; - } - - #menu > .inner { - padding: 2.75em 1.5em; - } - - #menu > .close { - top: 0.5em; - left: -4.25em; - width: 4.25em; - text-indent: 4.25em; - } - - #menu > .close:before, #menu > .close:after { - background-size: 1.5em 1.5em; - } - - } - - body.is-menu-visible #wrapper { - -moz-pointer-events: none; - -webkit-pointer-events: none; - -ms-pointer-events: none; - pointer-events: none; - cursor: default; - opacity: 0.25; - } - - body.is-menu-visible #menu { - -moz-transform: translateX(0); - -webkit-transform: translateX(0); - -ms-transform: translateX(0); - transform: translateX(0); - visibility: visible; - } - - body.is-menu-visible #menu > * { - opacity: 1; - } - - body.is-menu-visible #menu .close { - -moz-transform: scale(1.0) rotate(0deg); - -webkit-transform: scale(1.0) rotate(0deg); - -ms-transform: scale(1.0) rotate(0deg); - transform: scale(1.0) rotate(0deg); - opacity: 1; - } - -/* Main */ - - #main { - padding: 0em 0 6em 0 ; - } - - @media screen and (max-width: 736px) { - - #main { - padding: 0em 0 4em 0 ; - } - - } - -/* Footer */ - - #footer { - padding: 5em 0 6em 0 ; - background-color: #f6f6f6; - } - - #footer > .inner { - display: -moz-flex; - display: -webkit-flex; - display: -ms-flex; - display: flex; - -moz-flex-wrap: wrap; - -webkit-flex-wrap: wrap; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -moz-flex-direction: row; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - } - - #footer > .inner > * > :last-child { - margin-bottom: 0; - } - - #footer > .inner section:nth-child(1) { - width: calc(66% - 2.5em); - margin-right: 2.5em; - } - - #footer > .inner section:nth-child(2) { - width: calc(33% - 2.5em); - margin-left: 2.5em; - } - - #footer > .inner .copyright { - width: 100%; - padding: 0; - margin-top: 5em; - list-style: none; - font-size: 0.8em; - color: rgba(88, 88, 88, 0.5); - } - - #footer > .inner .copyright a { - color: inherit; - } - - #footer > .inner .copyright li { - display: inline-block; - border-left: solid 1px rgba(88, 88, 88, 0.15); - line-height: 1; - padding: 0 0 0 1em; - margin: 0 0 0 1em; - } - - #footer > .inner .copyright li:first-child { - border-left: 0; - padding-left: 0; - margin-left: 0; - } - - @media screen and (max-width: 1280px) { - - #footer { - padding: 5em 0 3em 0 ; - } - - #footer > .inner section:nth-child(1) { - width: calc(66% - 1.25em); - margin-right: 1.25em; - } - - #footer > .inner section:nth-child(2) { - width: calc(33% - 1.25em); - margin-left: 1.25em; - } - - } - - @media screen and (max-width: 980px) { - - #footer > .inner section:nth-child(1) { - width: 66%; - margin-right: 0; - } - - #footer > .inner section:nth-child(2) { - width: calc(33% - 2.5em); - margin-left: 2.5em; - } - - } - - @media screen and (max-width: 736px) { - - #footer { - padding: 3em 0 1em 0 ; - } - - #footer > .inner { - -moz-flex-direction: column; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - } - - #footer > .inner section:nth-child(1) { - width: 100%; - margin-right: 0; - margin: 3em 0 0 0; - } - - #footer > .inner section:nth-child(2) { - -moz-order: -1; - -webkit-order: -1; - -ms-order: -1; - order: -1; - width: 100%; - margin-left: 0; - } - - #footer > .inner .copyright { - margin-top: 3em; - } - - } - - @media screen and (max-width: 480px) { - - #footer > .inner .copyright { - margin-top: 3em; - } - - #footer > .inner .copyright li { - border-left: 0; - padding-left: 0; - margin: 0.75em 0 0 0; - display: block; - line-height: inherit; - } - - #footer > .inner .copyright li:first-child { - margin-top: 0; - } - - } - -/* Wrapper */ - - #wrapper > * > .inner { - width: 100%; - max-width: 68em; - margin: 0 auto; - padding: 0 2.5em; - } - - @media screen and (max-width: 736px) { - - #wrapper > * > .inner { - padding: 0 1.25em; - } - - } diff --git a/utils/test/reporting/3rd_party/fonts/FontAwesome.otf b/utils/test/reporting/3rd_party/fonts/FontAwesome.otf deleted file mode 100644 index d4de13e83..000000000 Binary files a/utils/test/reporting/3rd_party/fonts/FontAwesome.otf and /dev/null differ diff --git a/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.eot b/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.eot deleted file mode 100644 index c7b00d2ba..000000000 Binary files a/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.svg b/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.svg deleted file mode 100644 index 8b66187fe..000000000 --- a/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,685 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.ttf b/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.ttf deleted file mode 100644 index f221e50a2..000000000 Binary files a/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.woff b/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.woff deleted file mode 100644 index 6e7483cf6..000000000 Binary files a/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.woff2 b/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.woff2 deleted file mode 100644 index 7eb74fd12..000000000 Binary files a/utils/test/reporting/3rd_party/fonts/fontawesome-webfont.woff2 and /dev/null differ diff --git a/utils/test/reporting/3rd_party/js/ie/html5shiv.js b/utils/test/reporting/3rd_party/js/ie/html5shiv.js deleted file mode 100644 index dcf351c86..000000000 --- a/utils/test/reporting/3rd_party/js/ie/html5shiv.js +++ /dev/null @@ -1,8 +0,0 @@ -/* - HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed -*/ -(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); -a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; -c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| -"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video",version:"3.6.2",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); -for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d #mq-test-1 { width: 42px; }',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){v(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))},g=function(a){return a.replace(c.regex.minmaxwh,"").match(c.regex.other)};if(c.ajax=f,c.queue=d,c.unsupportedmq=g,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,comments:/\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,maxw:/\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,minmaxwh:/\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,other:/\([^\)]*\)/g},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var h,i,j,k=a.document,l=k.documentElement,m=[],n=[],o=[],p={},q=30,r=k.getElementsByTagName("head")[0]||l,s=k.getElementsByTagName("base")[0],t=r.getElementsByTagName("link"),u=function(){var a,b=k.createElement("div"),c=k.body,d=l.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=k.createElement("body"),c.style.background="none"),l.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&l.insertBefore(c,l.firstChild),a=b.offsetWidth,f?l.removeChild(c):c.removeChild(b),l.style.fontSize=d,e&&(c.style.fontSize=e),a=j=parseFloat(a)},v=function(b){var c="clientWidth",d=l[c],e="CSS1Compat"===k.compatMode&&d||k.body[c]||d,f={},g=t[t.length-1],p=(new Date).getTime();if(b&&h&&q>p-h)return a.clearTimeout(i),i=a.setTimeout(v,q),void 0;h=p;for(var s in m)if(m.hasOwnProperty(s)){var w=m[s],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?j||u():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?j||u():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(n[w.rules]))}for(var C in o)o.hasOwnProperty(C)&&o[C]&&o[C].parentNode===r&&r.removeChild(o[C]);o.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=k.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,r.insertBefore(E,g.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(k.createTextNode(F)),o.push(E)}},w=function(a,b,d){var e=a.replace(c.regex.comments,"").replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var h=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},i=!f&&d;b.length&&(b+="/"),i&&(f=1);for(var j=0;f>j;j++){var k,l,o,p;i?(k=d,n.push(h(a))):(k=e[j].match(c.regex.findStyles)&&RegExp.$1,n.push(RegExp.$2&&h(RegExp.$2))),o=k.split(","),p=o.length;for(var q=0;p>q;q++)l=o[q],g(l)||m.push({media:l.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:n.length-1,hasquery:l.indexOf("(")>-1,minw:l.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:l.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}v()},x=function(){if(d.length){var b=d.shift();f(b.href,function(c){w(c,b.href,b.media),p[b.href]=!0,a.setTimeout(function(){x()},0)})}},y=function(){for(var b=0;ba?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; - -return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/\s*$/g,ra={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("