diff options
72 files changed, 2304 insertions, 1206 deletions
diff --git a/docs/jenkins-job-builder/opnfv-jjb-usage.rst b/docs/jenkins-job-builder/opnfv-jjb-usage.rst index fc968f841..52dbdebe5 100644 --- a/docs/jenkins-job-builder/opnfv-jjb-usage.rst +++ b/docs/jenkins-job-builder/opnfv-jjb-usage.rst @@ -70,6 +70,7 @@ reviewed and submitted. * jose.lausuch@ericsson.com * koffirodrigue@gmail.com * r-mibu@cq.jp.nec.com +* tbramwell@linuxfoundation.org Or Add the group releng-contributors @@ -81,4 +82,4 @@ in `releng-jobs.yaml`_. .. _releng-jobs.yaml: https://gerrit.opnfv.org/gerrit/gitweb?p=releng.git;a=blob;f=jjb/releng-jobs.yaml; .. _skip vote: - https://wiki.jenkins-ci.org/display/JENKINS/Gerrit+Trigger#GerritTrigger-SkipVote
\ No newline at end of file + https://wiki.jenkins-ci.org/display/JENKINS/Gerrit+Trigger#GerritTrigger-SkipVote diff --git a/jjb/apex/apex-deploy.sh b/jjb/apex/apex-deploy.sh index d39217a8d..c91e3ee82 100755 --- a/jjb/apex/apex-deploy.sh +++ b/jjb/apex/apex-deploy.sh @@ -3,7 +3,7 @@ set -o errexit set -o nounset set -o pipefail -APEX_PKGS="common undercloud onos" +APEX_PKGS="common undercloud" # removed onos for danube IPV6_FLAG=False # log info to console diff --git a/jjb/apex/apex-upload-artifact.sh b/jjb/apex/apex-upload-artifact.sh index 15aa67a6b..c2de7d70d 100755 --- a/jjb/apex/apex-upload-artifact.sh +++ b/jjb/apex/apex-upload-artifact.sh @@ -51,13 +51,13 @@ echo "ISO Upload Complete!" RPM_INSTALL_PATH=$BUILD_DIRECTORY/noarch RPM_LIST=$RPM_INSTALL_PATH/$(basename $OPNFV_RPM_URL) VERSION_EXTENSION=$(echo $(basename $OPNFV_RPM_URL) | sed 's/opnfv-apex-//') -for pkg in common undercloud onos; do +for pkg in common undercloud; do # removed onos for danube RPM_LIST+=" ${RPM_INSTALL_PATH}/opnfv-apex-${pkg}-${VERSION_EXTENSION}" done SRPM_INSTALL_PATH=$BUILD_DIRECTORY SRPM_LIST=$SRPM_INSTALL_PATH/$(basename $OPNFV_SRPM_URL) VERSION_EXTENSION=$(echo $(basename $OPNFV_SRPM_URL) | sed 's/opnfv-apex-//') -for pkg in common undercloud onos; do +for pkg in common undercloud; do # removed onos for danube SRPM_LIST+=" ${SRPM_INSTALL_PATH}/opnfv-apex-${pkg}-${VERSION_EXTENSION}" done } diff --git a/jjb/apex/apex.yml b/jjb/apex/apex.yml index 126651e6c..ac1ef499b 100644 --- a/jjb/apex/apex.yml +++ b/jjb/apex/apex.yml @@ -599,6 +599,23 @@ build-step-failure-threshold: 'never' failure-threshold: 'never' unstable-threshold: 'FAILURE' + # 1.dovetail only master by now, not sync with A/B/C branches + # 2.here the stream means the SUT stream, dovetail stream is defined in its own job + # 3.only debug testsuite here(includes basic testcase, + # i.e. one tempest smoke ipv6, two vping from functest) + # 4.not used for release criteria or compliance, + # only to debug the dovetail tool bugs with apex + - trigger-builds: + - project: 'dovetail-apex-{slave}-debug-{stream}' + current-parameters: false + predefined-parameters: + DEPLOY_SCENARIO=os-nosdn-nofeature-ha + block: true + same-node: true + block-thresholds: + build-step-failure-threshold: 'never' + failure-threshold: 'never' + unstable-threshold: 'FAILURE' - trigger-builds: - project: 'apex-deploy-baremetal-os-odl_l3-nofeature-ha-{stream}' predefined-parameters: | diff --git a/jjb/compass4nfv/compass-ci-jobs.yml b/jjb/compass4nfv/compass-ci-jobs.yml index 7258e89f4..5ccd4b56f 100644 --- a/jjb/compass4nfv/compass-ci-jobs.yml +++ b/jjb/compass4nfv/compass-ci-jobs.yml @@ -71,6 +71,10 @@ - 'os-nosdn-kvm-ha': disabled: false auto-trigger-name: 'compass-{scenario}-{pod}-{stream}-trigger' + - 'os-nosdn-openo-ha': + disabled: false + auto-trigger-name: 'compass-{scenario}-{pod}-{stream}-trigger' + jobs: - 'compass-{scenario}-{pod}-daily-{stream}' @@ -247,6 +251,10 @@ triggers: - timed: '0 19 * * *' - trigger: + name: 'compass-os-nosdn-openo-ha-baremetal-centos-master-trigger' + triggers: + - timed: '' +- trigger: name: 'compass-os-odl_l2-nofeature-ha-baremetal-centos-master-trigger' triggers: - timed: '0 23 * * *' @@ -280,6 +288,10 @@ triggers: - timed: '0 2 * * *' - trigger: + name: 'compass-os-nosdn-openo-ha-baremetal-master-trigger' + triggers: + - timed: '0 3 * * *' +- trigger: name: 'compass-os-odl_l2-nofeature-ha-baremetal-master-trigger' triggers: - timed: '0 22 * * *' @@ -313,6 +325,10 @@ triggers: - timed: '' - trigger: + name: 'compass-os-nosdn-openo-ha-baremetal-danube-trigger' + triggers: + - timed: '' +- trigger: name: 'compass-os-odl_l2-nofeature-ha-baremetal-danube-trigger' triggers: - timed: '' @@ -346,6 +362,10 @@ triggers: - timed: '0 21 * * *' - trigger: + name: 'compass-os-nosdn-openo-ha-virtual-master-trigger' + triggers: + - timed: '0 22 * * *' +- trigger: name: 'compass-os-odl_l2-nofeature-ha-virtual-master-trigger' triggers: - timed: '0 20 * * *' @@ -379,6 +399,10 @@ triggers: - timed: '0 21 * * *' - trigger: + name: 'compass-os-nosdn-openo-ha-virtual-danube-trigger' + triggers: + - timed: '0 22 * * *' +- trigger: name: 'compass-os-odl_l2-nofeature-ha-virtual-danube-trigger' triggers: - timed: '0 20 * * *' diff --git a/jjb/compass4nfv/compass-deploy.sh b/jjb/compass4nfv/compass-deploy.sh index 6696e4b3d..534e17e62 100644 --- a/jjb/compass4nfv/compass-deploy.sh +++ b/jjb/compass4nfv/compass-deploy.sh @@ -34,6 +34,8 @@ if [[ "${DEPLOY_SCENARIO}" =~ "-ocl" ]]; then export NETWORK_CONF_FILE=network_ocl.yml elif [[ "${DEPLOY_SCENARIO}" =~ "-onos" ]]; then export NETWORK_CONF_FILE=network_onos.yml +elif [[ "${DEPLOY_SCENARIO}" =~ "-openo" ]]; then + export NETWORK_CONF_FILE=network_openo.yml else export NETWORK_CONF_FILE=network.yml fi diff --git a/jjb/compass4nfv/compass-verify-jobs.yml b/jjb/compass4nfv/compass-verify-jobs.yml index d58138088..039b30a69 100644 --- a/jjb/compass4nfv/compass-verify-jobs.yml +++ b/jjb/compass4nfv/compass-verify-jobs.yml @@ -125,6 +125,11 @@ node-parameters: true kill-phase-on: FAILURE abort-all-job: true + - name: 'opnfv-yamllint-verify-{stream}' + current-parameters: true + node-parameters: true + kill-phase-on: FAILURE + abort-all-job: true - multijob: name: deploy-virtual condition: SUCCESSFUL diff --git a/jjb/daisy4nfv/daisy4nfv-download-artifact.sh b/jjb/daisy4nfv/daisy4nfv-download-artifact.sh index b9af2e8ad..1cc0443ad 100755 --- a/jjb/daisy4nfv/daisy4nfv-download-artifact.sh +++ b/jjb/daisy4nfv/daisy4nfv-download-artifact.sh @@ -36,6 +36,25 @@ echo "Using $OPNFV_ARTIFACT for deployment" [[ "$NODE_NAME" =~ (zte) ]] && OPNFV_ARTIFACT_URL=${GS_BASE_PROXY%%/*}/$OPNFV_ARTIFACT_URL +if [[ ! "$JOB_NAME" =~ (verify|merge) ]]; then + # check if we already have the image to avoid redownload + BINSTORE="/bin_mount/opnfv_ci/${BRANCH##*/}" + if [[ -f "$BINSTORE/$OPNFV_ARTIFACT" && ! -z $OPNFV_ARTIFACT_SHA512SUM ]]; then + echo "BIN exists locally. Starting to check the sha512sum." + if [[ $OPNFV_ARTIFACT_SHA512SUM = $(sha512sum -b $BINSTORE/$OPNFV_ARTIFACT | cut -d' ' -f1) ]]; then + echo "Sha512sum is verified. Skipping the download and using the file from BIN store." + ln -s $BINSTORE/$OPNFV_ARTIFACT $WORKSPACE/opnfv.bin + echo "--------------------------------------------------------" + echo + ls -al $WORKSPACE/opnfv.bin + echo + echo "--------------------------------------------------------" + echo "Done!" + exit 0 + fi + fi +fi + # log info to console echo "Downloading the $INSTALLER_TYPE artifact using URL http://$OPNFV_ARTIFACT_URL" echo "This could take some time..." diff --git a/jjb/doctor/doctor.yml b/jjb/doctor/doctor.yml index 28888d673..c677ef96e 100644 --- a/jjb/doctor/doctor.yml +++ b/jjb/doctor/doctor.yml @@ -145,11 +145,16 @@ builders: - 'clean-workspace-log' + - shell: | + # NOTE: Create symbolic link, so that we can archive file outside + # of $WORKSPACE . + # NOTE: We are printing all logs under 'tests/' during test run, + # so this symbolic link should not be in 'tests/'. Otherwise, + # we'll have the same log twice in jenkins console log. + ln -sfn $HOME/opnfv/functest/results/{stream} functest_results - 'functest-suite-builder' - shell: | functest_log="$HOME/opnfv/functest/results/{stream}/{project}.log" - to_be_archived="$WORKSPACE/tests/functest-{project}.log" - cp $functest_log $to_be_archived # NOTE: checking the test result, as the previous job could return # 0 regardless the result of doctor test scenario. grep -e ' OK$' $functest_log || exit 1 @@ -157,6 +162,8 @@ publishers: - archive: artifacts: 'tests/*.log' + - archive: + artifacts: 'functest_results/{project}.log' ##################################### diff --git a/jjb/dovetail/dovetail-ci-jobs.yml b/jjb/dovetail/dovetail-ci-jobs.yml index 22bc28109..0bd32a4ab 100644 --- a/jjb/dovetail/dovetail-ci-jobs.yml +++ b/jjb/dovetail/dovetail-ci-jobs.yml @@ -81,27 +81,23 @@ SUT: compass auto-trigger-name: 'daily-trigger-disabled' <<: *danube -#apex CI PODs - - apex-verify-master: +#-------------------------------- +# Installers not using labels +# CI PODs +# This section should only contain the installers +# that have not been switched using labels for slaves +#-------------------------------- +#apex PODs + - lf-pod1: slave-label: '{pod}' SUT: apex auto-trigger-name: 'daily-trigger-disabled' <<: *master - - apex-daily-master: + - lf-pod1: slave-label: '{pod}' SUT: apex auto-trigger-name: 'daily-trigger-disabled' - <<: *master -# - apex-verify-colorado: -# slave-label: '{pod}' -# SUT: apex -# auto-trigger-name: 'daily-trigger-disabled' -# <<: *danube -# - apex-daily-colorado: -# slave-label: '{pod}' -# SUT: apex -# auto-trigger-name: 'daily-trigger-disabled' -# <<: *danube + <<: *danube #armband CI PODs - armband-baremetal: slave-label: armband-baremetal diff --git a/jjb/fuel/fuel-basic-exp.sh b/jjb/fuel/fuel-basic-exp.sh deleted file mode 100755 index a70a0c765..000000000 --- a/jjb/fuel/fuel-basic-exp.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -set -o nounset - -echo "-----------------------------------------------------------------------" -echo $GERRIT_CHANGE_COMMIT_MESSAGE -echo "-----------------------------------------------------------------------" - -# proposal for specifying the scenario name in commit message -# currently only 1 scenario name is supported but depending on -# the need, it can be expanded, supporting multiple scenarios -# using comma separated list or something -SCENARIO_NAME_PATTERN="(?<=@scenario:).*?(?=@)" -SCENARIO_NAME=(echo $GERRIT_CHANGE_COMMIT_MESSAGE | grep -oP "$SCENARIO_NAME_PATTERN") -if [[ $? -ne 0 ]]; then - echo "The patch verification will be done only with build!" -else - echo "Will run full verification; build, deploy, and smoke test using scenario $SCENARIO_NAME" -fi diff --git a/jjb/fuel/fuel-build-exp.sh b/jjb/fuel/fuel-build-exp.sh deleted file mode 100755 index f7f613dc0..000000000 --- a/jjb/fuel/fuel-build-exp.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -if [[ "$JOB_NAME" =~ (verify|merge|daily|weekly) ]]; then - JOB_TYPE=${BASH_REMATCH[0]} -else - echo "Unable to determine job type!" - exit 1 -fi - -echo "Not activated!" diff --git a/jjb/fuel/fuel-daily-jobs.yml b/jjb/fuel/fuel-daily-jobs.yml index 237855236..19336d8ac 100644 --- a/jjb/fuel/fuel-daily-jobs.yml +++ b/jjb/fuel/fuel-daily-jobs.yml @@ -134,6 +134,7 @@ use-build-blocker: true blocking-jobs: - 'fuel-os-.*?-{pod}-daily-.*' + - 'fuel-os-.*?-{pod}-weekly-.*' block-level: 'NODE' wrappers: @@ -158,7 +159,7 @@ builders: - description-setter: - description: "POD: $NODE_NAME" + description: "Built on $NODE_NAME" - trigger-builds: - project: 'fuel-deploy-{pod}-daily-{stream}' current-parameters: false @@ -212,6 +213,8 @@ blocking-jobs: - 'fuel-deploy-{pod}-daily-.*' - 'fuel-deploy-generic-daily-.*' + - 'fuel-deploy-{pod}-weekly-.*' + - 'fuel-deploy-generic-weekly-.*' block-level: 'NODE' parameters: @@ -240,7 +243,7 @@ builders: - description-setter: - description: "POD: $NODE_NAME" + description: "Built on $NODE_NAME" - shell: !include-raw-escape: ./fuel-download-artifact.sh - shell: diff --git a/jjb/fuel/fuel-deploy-exp.sh b/jjb/fuel/fuel-deploy-exp.sh deleted file mode 100755 index f7f613dc0..000000000 --- a/jjb/fuel/fuel-deploy-exp.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -if [[ "$JOB_NAME" =~ (verify|merge|daily|weekly) ]]; then - JOB_TYPE=${BASH_REMATCH[0]} -else - echo "Unable to determine job type!" - exit 1 -fi - -echo "Not activated!" diff --git a/jjb/fuel/fuel-deploy.sh b/jjb/fuel/fuel-deploy.sh index 4efccd611..f5bbd1818 100755 --- a/jjb/fuel/fuel-deploy.sh +++ b/jjb/fuel/fuel-deploy.sh @@ -95,7 +95,7 @@ echo "Deployment is done!" # upload logs for baremetal deployments # work with virtual deployments is still going on so we skip that for the timebeing -if [[ "$JOB_NAME" =~ "baremetal-daily" ]]; then +if [[ "$JOB_NAME" =~ (baremetal-daily|baremetal-weekly) ]]; then echo "Uploading deployment logs" gsutil cp $WORKSPACE/$FUEL_LOG_FILENAME gs://$GS_URL/logs/$FUEL_LOG_FILENAME > /dev/null 2>&1 echo "Logs are available as http://$GS_URL/logs/$FUEL_LOG_FILENAME" diff --git a/jjb/fuel/fuel-smoke-test-exp.sh b/jjb/fuel/fuel-smoke-test-exp.sh deleted file mode 100755 index f7f613dc0..000000000 --- a/jjb/fuel/fuel-smoke-test-exp.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -if [[ "$JOB_NAME" =~ (verify|merge|daily|weekly) ]]; then - JOB_TYPE=${BASH_REMATCH[0]} -else - echo "Unable to determine job type!" - exit 1 -fi - -echo "Not activated!" diff --git a/jjb/fuel/fuel-verify-jobs-experimental.yml b/jjb/fuel/fuel-verify-jobs-experimental.yml deleted file mode 100644 index ae6458021..000000000 --- a/jjb/fuel/fuel-verify-jobs-experimental.yml +++ /dev/null @@ -1,255 +0,0 @@ -- project: - # TODO: rename the project name - # TODO: get rid of appended -exp from the remainder of the file - name: 'fuel-verify-jobs-experimental' - - project: 'fuel' - - installer: 'fuel' -#------------------------------------ -# branch definitions -#------------------------------------ - # TODO: enable master once things settle - stream-exp: - - experimental: - branch: 'stable/{stream-exp}' - gs-pathname: '/{stream-exp}' - disabled: false -#------------------------------------ -# patch verification phases -#------------------------------------ - phase: - - 'basic': - # this phase does basic commit message check, unit test and so on - slave-label: 'opnfv-build' - - 'build': - # this phase builds artifacts if valid for given installer - slave-label: 'opnfv-build-ubuntu' - - 'deploy-virtual': - # this phase does virtual deployment using the artifacts produced in previous phase - slave-label: 'fuel-virtual' - - 'smoke-test': - # this phase runs functest smoke test - slave-label: 'fuel-virtual' -#------------------------------------ -# jobs -#------------------------------------ - jobs: - - 'fuel-verify-{stream-exp}' - - 'fuel-verify-{phase}-{stream-exp}' -#------------------------------------ -# job templates -#------------------------------------ -- job-template: - name: 'fuel-verify-{stream-exp}' - - project-type: multijob - - disabled: '{obj:disabled}' - - # TODO: this is valid for experimental only - # enable concurrency for master once things settle - concurrent: false - - properties: - - logrotate-default - - throttle: - enabled: true - max-total: 4 - option: 'project' - - scm: - - git-scm-gerrit - - wrappers: - - ssh-agent-wrapper - - timeout: - timeout: 360 - fail: true - - 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: '{project}' - branches: - - branch-compare-type: 'ANT' - branch-pattern: '**/{branch}' - file-paths: - - compare-type: ANT - pattern: 'ci/**' - - compare-type: ANT - pattern: 'build/**' - - compare-type: ANT - pattern: 'deploy/**' - forbidden-file-paths: - - compare-type: ANT - pattern: 'docs/**' - readable-message: true - - parameters: - - project-parameter: - project: '{project}' - branch: '{branch}' - - 'opnfv-build-defaults' - - 'fuel-verify-defaults-exp': - gs-pathname: '{gs-pathname}' - - builders: - - description-setter: - description: "Built on $NODE_NAME" - - multijob: - name: basic - condition: SUCCESSFUL - projects: - - name: 'fuel-verify-basic-{stream-exp}' - current-parameters: false - predefined-parameters: | - BRANCH=$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 - - multijob: - name: build - condition: SUCCESSFUL - projects: - - name: 'fuel-verify-build-{stream-exp}' - current-parameters: false - predefined-parameters: | - BRANCH=$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 - - multijob: - name: deploy-virtual - condition: SUCCESSFUL - projects: - - name: 'fuel-verify-deploy-virtual-{stream-exp}' - current-parameters: false - predefined-parameters: | - BRANCH=$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 - - multijob: - name: smoke-test - condition: SUCCESSFUL - projects: - - name: 'fuel-verify-smoke-test-{stream-exp}' - current-parameters: false - predefined-parameters: | - BRANCH=$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 - -- job-template: - name: 'fuel-verify-{phase}-{stream-exp}' - - disabled: '{obj:disabled}' - - concurrent: true - - properties: - - logrotate-default - - throttle: - enabled: true - max-total: 6 - option: 'project' - - build-blocker: - use-build-blocker: true - blocking-jobs: - - 'fuel-verify-deploy-.*' - - 'fuel-verify-test-.*' - block-level: 'NODE' - - scm: - - git-scm-gerrit - - wrappers: - - ssh-agent-wrapper - - timeout: - timeout: 360 - fail: true - parameters: - - project-parameter: - project: '{project}' - branch: '{branch}' - - '{slave-label}-defaults' - - '{installer}-defaults' - - 'fuel-verify-defaults-exp': - gs-pathname: '{gs-pathname}' - - builders: - - description-setter: - description: "Built on $NODE_NAME" - - '{project}-verify-{phase}-macro-exp' -#------------------------------------ -# builder macros -#------------------------------------ -- builder: - name: 'fuel-verify-basic-macro-exp' - builders: - - shell: - !include-raw: ./fuel-basic-exp.sh - -- builder: - name: 'fuel-verify-build-macro-exp' - builders: - - shell: - !include-raw: ./fuel-build-exp.sh - - shell: - !include-raw: ./fuel-workspace-cleanup.sh - -- builder: - name: 'fuel-verify-deploy-virtual-macro-exp' - builders: - - shell: - !include-raw: ./fuel-deploy-exp.sh - -- builder: - name: 'fuel-verify-smoke-test-macro-exp' - builders: - - shell: - !include-raw: ./fuel-smoke-test-exp.sh -#------------------------------------ -# parameter macros -#------------------------------------ -- parameter: - name: 'fuel-verify-defaults-exp' - parameters: - - string: - name: BUILD_DIRECTORY - default: $WORKSPACE/build_output - description: "Directory where the build artifact will be located upon the completion of the build." - - string: - name: CACHE_DIRECTORY - default: $HOME/opnfv/cache/$INSTALLER_TYPE - description: "Directory where the cache to be used during the build is located." - - string: - name: GS_URL - default: artifacts.opnfv.org/$PROJECT{gs-pathname} - description: "URL to Google Storage." diff --git a/jjb/fuel/fuel-weekly-jobs.yml b/jjb/fuel/fuel-weekly-jobs.yml new file mode 100644 index 000000000..06d813458 --- /dev/null +++ b/jjb/fuel/fuel-weekly-jobs.yml @@ -0,0 +1,210 @@ +# jenkins job templates for Fuel +- project: + + name: fuel-weekly + + project: fuel + + installer: fuel + +#-------------------------------- +# BRANCH ANCHORS +#-------------------------------- + master: &master + stream: master + branch: '{stream}' + disabled: false + gs-pathname: '' + danube: &danube + stream: danube + branch: 'stable/{stream}' + disabled: true + gs-pathname: '/{stream}' +#-------------------------------- +# POD, INSTALLER, AND BRANCH MAPPING +#-------------------------------- +# CI PODs +#-------------------------------- + pod: + - baremetal: + slave-label: fuel-baremetal + <<: *master + - virtual: + slave-label: fuel-virtual + <<: *master + - baremetal: + slave-label: fuel-baremetal + <<: *danube + - virtual: + slave-label: fuel-virtual + <<: *danube +#-------------------------------- +# scenarios +#-------------------------------- + scenario: + # HA scenarios + - 'os-nosdn-nofeature-ha': + auto-trigger-name: 'weekly-trigger-disabled' + + jobs: + - 'fuel-{scenario}-{pod}-weekly-{stream}' + - 'fuel-deploy-{pod}-weekly-{stream}' + +######################## +# job templates +######################## +- job-template: + name: 'fuel-{scenario}-{pod}-weekly-{stream}' + + disabled: '{obj:disabled}' + + concurrent: false + + properties: + - logrotate-default + - throttle: + enabled: true + max-total: 4 + max-per-node: 1 + option: 'project' + - build-blocker: + use-build-blocker: true + blocking-jobs: + - 'fuel-os-.*?-{pod}-daily-.*' + - 'fuel-os-.*?-{pod}-weekly-.*' + block-level: 'NODE' + + wrappers: + - build-name: + name: '$BUILD_NUMBER - Scenario: $DEPLOY_SCENARIO' + + triggers: + - '{auto-trigger-name}' + + parameters: + - project-parameter: + project: '{project}' + branch: '{branch}' + - '{installer}-defaults' + - '{slave-label}-defaults': + installer: '{installer}' + - string: + name: DEPLOY_SCENARIO + default: '{scenario}' + - fuel-weekly-parameter: + gs-pathname: '{gs-pathname}' + + builders: + - description-setter: + description: "Built on $NODE_NAME" + - trigger-builds: + - project: 'fuel-deploy-{pod}-weekly-{stream}' + current-parameters: false + predefined-parameters: + DEPLOY_SCENARIO={scenario} + same-node: true + block: true + - trigger-builds: + - project: 'functest-fuel-{pod}-weekly-{stream}' + current-parameters: false + predefined-parameters: + DEPLOY_SCENARIO={scenario} + same-node: true + block: true + block-thresholds: + build-step-failure-threshold: 'never' + failure-threshold: 'never' + unstable-threshold: 'FAILURE' + + publishers: + - email: + recipients: peter.barabas@ericsson.com fzhadaev@mirantis.com + +- job-template: + name: 'fuel-deploy-{pod}-weekly-{stream}' + + disabled: '{obj:disabled}' + + concurrent: true + + properties: + - logrotate-default + - throttle: + enabled: true + max-total: 4 + max-per-node: 1 + option: 'project' + - build-blocker: + use-build-blocker: true + blocking-jobs: + - 'fuel-deploy-{pod}-daily-.*' + - 'fuel-deploy-generic-daily-.*' + - 'fuel-deploy-{pod}-weekly-.*' + - 'fuel-deploy-generic-weekly-.*' + block-level: 'NODE' + + parameters: + - project-parameter: + project: '{project}' + branch: '{branch}' + - '{installer}-defaults' + - '{slave-label}-defaults': + installer: '{installer}' + - string: + name: DEPLOY_SCENARIO + default: 'os-odl_l2-nofeature-ha' + - fuel-weekly-parameter: + gs-pathname: '{gs-pathname}' + - string: + name: DEPLOY_TIMEOUT + default: '150' + description: 'Deployment timeout in minutes' + + scm: + - git-scm + + wrappers: + - build-name: + name: '$BUILD_NUMBER - Scenario: $DEPLOY_SCENARIO' + + builders: + - description-setter: + description: "Built on $NODE_NAME" + - shell: + !include-raw-escape: ./fuel-download-artifact.sh + - shell: + !include-raw-escape: ./fuel-deploy.sh + + publishers: + - email: + recipients: peter.barabas@ericsson.com fzhadaev@mirantis.com + +######################## +# parameter macros +######################## +- parameter: + name: fuel-weekly-parameter + parameters: + - string: + name: BUILD_DIRECTORY + default: $WORKSPACE/build_output + description: "Directory where the build artifact will be located upon the completion of the build." + - string: + name: CACHE_DIRECTORY + default: $HOME/opnfv/cache/$INSTALLER_TYPE + description: "Directory where the cache to be used during the build is located." + - string: + name: GS_URL + default: artifacts.opnfv.org/$PROJECT{gs-pathname} + description: "URL to Google Storage." +######################## +# trigger macros +######################## +#----------------------------------------------- +# Triggers for job running on fuel-baremetal against master branch +#----------------------------------------------- +# HA Scenarios +- trigger: + name: 'fuel-os-nosdn-nofeature-ha-baremetal-weekly-master-trigger' + triggers: + - timed: '' diff --git a/jjb/functest/functest-ci-jobs.yml b/jjb/functest/functest-daily-jobs.yml index 9bf6a1a6e..5984b3674 100644 --- a/jjb/functest/functest-ci-jobs.yml +++ b/jjb/functest/functest-daily-jobs.yml @@ -2,9 +2,9 @@ # job configuration for functest ################################### - project: - name: functest + name: functest-daily - project: '{name}' + project: functest #-------------------------------- # BRANCH ANCHORS @@ -114,11 +114,11 @@ installer: fuel <<: *danube # daisy CI PODs - - daisy-baremetal: + - baremetal: slave-label: daisy-baremetal installer: daisy <<: *master - - daisy-virtual: + - virtual: slave-label: daisy-virtual installer: daisy <<: *master @@ -198,8 +198,6 @@ job-timeout: 60 - 'daily': job-timeout: 180 - - 'weekly': - job-timeout: 400 jobs: - 'functest-{installer}-{pod}-{testsuite}-{stream}' @@ -252,7 +250,7 @@ builders: - description-setter: - description: "POD: $NODE_NAME" + description: "Built on $NODE_NAME" - 'functest-{testsuite}-builder' ######################## @@ -266,13 +264,6 @@ default: 'daily' description: "Daily suite name to run" - parameter: - name: functest-weekly-parameter - parameters: - - string: - name: FUNCTEST_SUITE_NAME - default: 'weekly' - description: "Weekly suite name to run" -- parameter: name: functest-suite-parameter parameters: - choice: @@ -343,15 +334,6 @@ - 'functest-exit' - builder: - name: functest-weekly-builder - builders: - - 'functest-cleanup' - - 'set-functest-env' - - 'functest-weekly' - - 'functest-store-results' - - 'functest-exit' - -- builder: name: functest-suite-builder builders: - 'functest-cleanup' @@ -364,11 +346,6 @@ - shell: !include-raw: ./functest-loop.sh -- builder: - name: functest-weekly - builders: - - shell: - !include-raw: ./functest-loop.sh - builder: name: functest-suite diff --git a/jjb/functest/functest-weekly-jobs.yml b/jjb/functest/functest-weekly-jobs.yml new file mode 100644 index 000000000..f44f7b8aa --- /dev/null +++ b/jjb/functest/functest-weekly-jobs.yml @@ -0,0 +1,124 @@ +################################### +# job configuration for functest +################################### +- project: + name: functest-weekly + + project: functest + +#-------------------------------- +# BRANCH ANCHORS +#-------------------------------- + master: &master + stream: master + branch: '{stream}' + gs-pathname: '' + docker-tag: 'latest' + disabled: false + danube: &danube + stream: danube + branch: 'stable/{stream}' + gs-pathname: '/{stream}' + docker-tag: 'stable' + disabled: true +#-------------------------------- +# POD, INSTALLER, AND BRANCH MAPPING +#-------------------------------- +# Installers using labels +# CI PODs +# This section should only contain the installers +# that have been switched using labels for slaves +#-------------------------------- + pod: +# fuel CI PODs + - baremetal: + slave-label: fuel-baremetal + installer: fuel + <<: *master + - virtual: + slave-label: fuel-virtual + installer: fuel + <<: *master + - baremetal: + slave-label: fuel-baremetal + installer: fuel + <<: *danube + - virtual: + slave-label: fuel-virtual + installer: fuel + <<: *danube +#-------------------------------- + jobs: + - 'functest-{installer}-{pod}-weekly-{stream}' + +################################ +# job template +################################ +- job-template: + name: 'functest-{installer}-{pod}-weekly-{stream}' + + disabled: '{obj:disabled}' + + concurrent: true + + properties: + - logrotate-default + - throttle: + enabled: true + max-per-node: 1 + option: 'project' + + wrappers: + - build-name: + name: '$BUILD_NUMBER Suite: $FUNCTEST_SUITE_NAME Scenario: $DEPLOY_SCENARIO' + - timeout: + timeout: '400' + abort: true + + parameters: + - project-parameter: + project: '{project}' + branch: '{branch}' + - '{installer}-defaults' + - '{slave-label}-defaults' + - string: + name: FUNCTEST_SUITE_NAME + default: 'weekly' + description: "Weekly suite name to run" + - 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' + description: 'Remove downloaded docker images (opnfv/functest*:*)' + - functest-parameter: + gs-pathname: '{gs-pathname}' + + scm: + - git-scm + + builders: + - description-setter: + description: "Built on $NODE_NAME" + - 'functest-weekly-builder' +######################## +# builder macros +######################## +- builder: + name: functest-weekly-builder + builders: + - shell: + !include-raw: ./functest-cleanup.sh + - shell: + !include-raw: ./set-functest-env.sh + - shell: + !include-raw: ./functest-loop.sh + - shell: + !include-raw: ../../utils/push-test-logs.sh + - shell: + !include-raw: ./functest-exit.sh diff --git a/jjb/global/releng-macros.yml b/jjb/global/releng-macros.yml index 34f53fb5f..63613f88d 100644 --- a/jjb/global/releng-macros.yml +++ b/jjb/global/releng-macros.yml @@ -111,10 +111,10 @@ - compare-type: 'ANT' pattern: '{files}' skip-vote: - successful: true - failed: true - unstable: true - notbuilt: true + successful: false + failed: false + unstable: false + notbuilt: false - trigger: name: gerrit-trigger-change-merged @@ -131,6 +131,9 @@ branches: - branch-compare-type: 'ANT' branch-pattern: '**/{branch}' + file-paths: + - compare-type: 'ANT' + pattern: '{files}' - trigger: name: 'experimental' diff --git a/jjb/infra/bifrost-cleanup-job.yml b/jjb/infra/bifrost-cleanup-job.yml index 0ee906f73..f1b38ca4b 100644 --- a/jjb/infra/bifrost-cleanup-job.yml +++ b/jjb/infra/bifrost-cleanup-job.yml @@ -133,6 +133,4 @@ file-paths: - compare-type: ANT pattern: 'prototypes/bifrost/**' - - compare-type: ANT - pattern: 'jjb/infra/**' readable-message: true diff --git a/jjb/multisite/fuel-deploy-for-multisite.sh b/jjb/multisite/fuel-deploy-for-multisite.sh index d8b40517c..06617610c 100755 --- a/jjb/multisite/fuel-deploy-for-multisite.sh +++ b/jjb/multisite/fuel-deploy-for-multisite.sh @@ -27,6 +27,9 @@ if [[ -z "FUEL_PROPERTIES_FILE" ]]; then echo "Unable to extract the url to Fuel ISO properties from ${FUEL_DEPLOY_URL}" exit 1 fi + +# use known/working version of fuel +FUEL_PROPERTIES_FILE="opnfv-2017-03-06_16-00-15.properties" curl -L -s -o $WORKSPACE/latest.properties http://artifacts.opnfv.org/fuel/$FUEL_PROPERTIES_FILE # source the file so we get OPNFV vars diff --git a/jjb/opera/opera-daily-jobs.yml b/jjb/opera/opera-daily-jobs.yml index d49caf1a6..5d2cc03f3 100644 --- a/jjb/opera/opera-daily-jobs.yml +++ b/jjb/opera/opera-daily-jobs.yml @@ -83,7 +83,7 @@ - name: 'compass-deploy-virtual-daily-{stream}' current-parameters: false predefined-parameters: | - DEPLOY_SCENARIO=os-nosdn-openo-noha + DEPLOY_SCENARIO=os-nosdn-openo-ha COMPASS_OS_VERSION=xenial node-parameters: true kill-phase-on: FAILURE diff --git a/jjb/opnfvdocs/docs-rtd.yaml b/jjb/opnfvdocs/docs-rtd.yaml index 2d5ec4fa4..c78e7f0f6 100644 --- a/jjb/opnfvdocs/docs-rtd.yaml +++ b/jjb/opnfvdocs/docs-rtd.yaml @@ -33,7 +33,10 @@ - git-scm triggers: - - gerrit-trigger-change-merged + - gerrit-trigger-change-merged: + project: '**' + branch: '{branch}' + files: 'docs/**/*.*' builders: - shell: !include-raw: docs-post-rtd.sh diff --git a/jjb/opnfvdocs/opnfvdocs.yml b/jjb/opnfvdocs/opnfvdocs.yml index 12950338d..661f060ee 100644 --- a/jjb/opnfvdocs/opnfvdocs.yml +++ b/jjb/opnfvdocs/opnfvdocs.yml @@ -62,6 +62,11 @@ branches: - branch-compare-type: 'ANT' branch-pattern: '**/{branch}' + skip-vote: + successful: true + failed: true + unstable: true + notbuilt: true builders: - check-bash-syntax diff --git a/jjb/parser/parser.yml b/jjb/parser/parser.yml index 69fcefc20..7f3d6cebe 100644 --- a/jjb/parser/parser.yml +++ b/jjb/parser/parser.yml @@ -55,7 +55,11 @@ branch-pattern: '**/{branch}' forbidden-file-paths: - compare-type: ANT - pattern: 'docs/**|.gitignore' + pattern: 'docs/**' + - compare-type: ANT + pattern: 'governance/**' + - compare-type: ANT + pattern: '*.txt|.gitignore|.gitreview|INFO|LICENSE' builders: - shell: | diff --git a/jjb/qtip/qtip-validate-jobs.yml b/jjb/qtip/qtip-validate-jobs.yml index 98f7ab90a..10ee72a8b 100644 --- a/jjb/qtip/qtip-validate-jobs.yml +++ b/jjb/qtip/qtip-validate-jobs.yml @@ -139,3 +139,4 @@ - gerrit-trigger-change-merged: project: '{project}' branch: '{branch}' + files: '**' diff --git a/jjb/releng/opnfv-lint.yml b/jjb/releng/opnfv-lint.yml index 37cdef28f..166aea8f9 100644 --- a/jjb/releng/opnfv-lint.yml +++ b/jjb/releng/opnfv-lint.yml @@ -102,7 +102,7 @@ comment-contains-value: 'reverify' projects: - project-compare-type: 'REG_EXP' - project-pattern: 'compass4nfv' + project-pattern: '' branches: - branch-compare-type: 'ANT' branch-pattern: '**/{branch}' diff --git a/jjb/snaps/snaps.yml b/jjb/snaps/snaps.yml new file mode 100644 index 000000000..32680f54e --- /dev/null +++ b/jjb/snaps/snaps.yml @@ -0,0 +1,62 @@ +################################################### +# All the jobs except verify have been removed! +# They will only be enabled on request by projects! +################################################### +- project: + name: snaps + + project: '{name}' + + jobs: + - 'snaps-verify-{stream}' + + stream: + - master: + branch: '{stream}' + gs-pathname: '' + disabled: false + - danube: + branch: 'stable/{stream}' + gs-pathname: '/{stream}' + disabled: true + +- job-template: + name: 'snaps-verify-{stream}' + + disabled: '{obj:disabled}' + + parameters: + - project-parameter: + project: '{project}' + branch: '{branch}' + - 'opnfv-build-ubuntu-defaults' + + 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: '{project}' + branches: + - branch-compare-type: 'ANT' + branch-pattern: '**/{branch}' + forbidden-file-paths: + - compare-type: ANT + pattern: 'docs/**|.gitignore' + + builders: + - shell: | + echo "Nothing to verify!" diff --git a/modules/opnfv/deployment/fuel/adapter.py b/modules/opnfv/deployment/fuel/adapter.py index a71d6cbf9..a217767ba 100644 --- a/modules/opnfv/deployment/fuel/adapter.py +++ b/modules/opnfv/deployment/fuel/adapter.py @@ -176,7 +176,7 @@ class FuelAdapter(manager.DeploymentHandler): return version def get_sdn_version(self): - cmd = "apt-cache show opendaylight|grep Version" + cmd = "apt-cache policy opendaylight|grep Installed" version = None for node in self.nodes: if manager.Role.ODL in node.roles and node.is_active(): diff --git a/prototypes/openstack-ansible/README.md b/prototypes/openstack-ansible/README.md new file mode 100644 index 000000000..34c1d0d03 --- /dev/null +++ b/prototypes/openstack-ansible/README.md @@ -0,0 +1,48 @@ +=============================== +How to deploy OpenStack-Ansible +=============================== +The script and playbooks defined on this repo will deploy an OpenStack +cloud based on OpenStack-Ansible. +It needs to be combined with Bifrost. You need use Bifrost to provide six VMs. +To learn about how to use Bifrost, you can read the document on +[/opt/releng/prototypes/bifrost/README.md]. + +Minimal requirements: +1. You will need to have a least 150G free space for the partition on where + "/var/lib/libvirt/images/" lives. +2. each vm needs to have at least 8 vCPU, 12 GB RAM, 60 GB HDD. + +After provisioning the six VMs please follow that steps: + +1.Run the script to deploy OpenStack + cd /opt/releng/prototypes/openstack-ansible/scripts/ + sudo ./osa_deploy.sh +It will take a lot of time. When the deploy is successful, you will see the +message "OpenStack deployed successfully". + +2.To verify the OpenStack operation + 2.1 ssh into the controller:: + ssh 192.168.122.3 + 2.2 Enter into the lxc container:: + lxcname=$(lxc-ls | grep utility) + lxc-attach -n $lxcname + 2.3 Verify the OpenStack API:: + source /root/openrc + openstack user list + +This will show the following output:: ++----------------------------------+--------------------+ +| ID | Name | ++----------------------------------+--------------------+ +| 056f8fe41336435991fd80872731cada | aodh | +| 308f6436e68f40b49d3b8e7ce5c5be1e | glance | +| 351b71b43a66412d83f9b3cd75485875 | nova | +| 511129e053394aea825cce13b9f28504 | ceilometer | +| 5596f71319d44c8991fdc65f3927b62e | gnocchi | +| 586f49e3398a4c47a2f6fe50135d4941 | stack_domain_admin | +| 601b329e6b1d427f9a1e05ed28753497 | heat | +| 67fe383b94964a4781345fbcc30ae434 | cinder | +| 729bb08351264d729506dad84ed3ccf0 | admin | +| 9f2beb2b270940048fe6844f0b16281e | neutron | +| fa68f86dd1de4ddbbb7415b4d9a54121 | keystone | ++----------------------------------+--------------------+ diff --git a/prototypes/openstack-ansible/file/cinder.yml b/prototypes/openstack-ansible/file/cinder.yml new file mode 100644 index 000000000..e40b39256 --- /dev/null +++ b/prototypes/openstack-ansible/file/cinder.yml @@ -0,0 +1,13 @@ +--- +# This file contains an example to show how to set +# the cinder-volume service to run in a container. +# +# Important note: +# When using LVM or any iSCSI-based cinder backends, such as NetApp with +# iSCSI protocol, the cinder-volume service *must* run on metal. +# Reference: https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/1226855 + +container_skel: + cinder_volumes_container: + properties: + is_metal: false diff --git a/prototypes/openstack-ansible/file/exports b/prototypes/openstack-ansible/file/exports new file mode 100644 index 000000000..315f79d2f --- /dev/null +++ b/prototypes/openstack-ansible/file/exports @@ -0,0 +1,12 @@ +# /etc/exports: the access control list for filesystems which may be exported +# to NFS clients. See exports(5). +# +# Example for NFSv2 and NFSv3: +# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check) +# +# Example for NFSv4: +# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check) +# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check) +# +/images *(rw,sync,no_subtree_check,no_root_squash) + diff --git a/prototypes/openstack-ansible/file/modules b/prototypes/openstack-ansible/file/modules new file mode 100644 index 000000000..60a517f18 --- /dev/null +++ b/prototypes/openstack-ansible/file/modules @@ -0,0 +1,8 @@ +# /etc/modules: kernel modules to load at boot time. +# +# This file contains the names of kernel modules that should be loaded +# at boot time, one per line. Lines beginning with "#" are ignored. +# Parameters can be specified after the module name. + +bonding +8021q diff --git a/prototypes/openstack-ansible/file/openstack_user_config.yml b/prototypes/openstack-ansible/file/openstack_user_config.yml new file mode 100644 index 000000000..2811e62ce --- /dev/null +++ b/prototypes/openstack-ansible/file/openstack_user_config.yml @@ -0,0 +1,278 @@ +--- +cidr_networks: + container: 172.29.236.0/22 + tunnel: 172.29.240.0/22 + storage: 172.29.244.0/22 + +used_ips: + - "172.29.236.1,172.29.236.50" + - "172.29.240.1,172.29.240.50" + - "172.29.244.1,172.29.244.50" + - "172.29.248.1,172.29.248.50" + +global_overrides: + internal_lb_vip_address: 172.29.236.222 + external_lb_vip_address: 192.168.122.220 + tunnel_bridge: "br-vxlan" + management_bridge: "br-mgmt" + provider_networks: + - network: + container_bridge: "br-mgmt" + container_type: "veth" + container_interface: "eth1" + ip_from_q: "container" + type: "raw" + group_binds: + - all_containers + - hosts + is_container_address: true + is_ssh_address: true + - network: + container_bridge: "br-vxlan" + container_type: "veth" + container_interface: "eth10" + ip_from_q: "tunnel" + type: "vxlan" + range: "1:1000" + net_name: "vxlan" + group_binds: + - neutron_linuxbridge_agent + - network: + container_bridge: "br-vlan" + container_type: "veth" + container_interface: "eth12" + host_bind_override: "eth12" + type: "flat" + net_name: "flat" + group_binds: + - neutron_linuxbridge_agent + - network: + container_bridge: "br-vlan" + container_type: "veth" + container_interface: "eth11" + type: "vlan" + range: "1:1" + net_name: "vlan" + group_binds: + - neutron_linuxbridge_agent + - network: + container_bridge: "br-storage" + container_type: "veth" + container_interface: "eth2" + ip_from_q: "storage" + type: "raw" + group_binds: + - glance_api + - cinder_api + - cinder_volume + - nova_compute + +### +### Infrastructure +### + +# galera, memcache, rabbitmq, utility +shared-infra_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# repository (apt cache, python packages, etc) +repo-infra_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# load balancer +# Ideally the load balancer should not use the Infrastructure hosts. +# Dedicated hardware is best for improved performance and security. +haproxy_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# rsyslog server +#log_hosts: + # log1: + # ip: 172.29.236.14 + +### +### OpenStack +### + +# keystone +identity_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# cinder api services +storage-infra_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# glance +# The settings here are repeated for each infra host. +# They could instead be applied as global settings in +# user_variables, but are left here to illustrate that +# each container could have different storage targets. +image_hosts: + controller00: + ip: 172.29.236.11 + container_vars: + limit_container_types: glance + glance_nfs_client: + - server: "172.29.244.15" + remote_path: "/images" + local_path: "/var/lib/glance/images" + type: "nfs" + options: "_netdev,auto" + controller01: + ip: 172.29.236.12 + container_vars: + limit_container_types: glance + glance_nfs_client: + - server: "172.29.244.15" + remote_path: "/images" + local_path: "/var/lib/glance/images" + type: "nfs" + options: "_netdev,auto" + controller02: + ip: 172.29.236.13 + container_vars: + limit_container_types: glance + glance_nfs_client: + - server: "172.29.244.15" + remote_path: "/images" + local_path: "/var/lib/glance/images" + type: "nfs" + options: "_netdev,auto" + +# nova api, conductor, etc services +compute-infra_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# heat +orchestration_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# horizon +dashboard_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# neutron server, agents (L3, etc) +network_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# ceilometer (telemetry API) +metering-infra_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# aodh (telemetry alarm service) +metering-alarm_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# gnocchi (telemetry metrics storage) +metrics_hosts: + controller00: + ip: 172.29.236.11 + controller01: + ip: 172.29.236.12 + controller02: + ip: 172.29.236.13 + +# nova hypervisors +compute_hosts: + compute00: + ip: 172.29.236.14 + compute01: + ip: 172.29.236.15 + +# ceilometer compute agent (telemetry) +metering-compute_hosts: + compute00: + ip: 172.29.236.14 + compute01: + ip: 172.29.236.15 +# cinder volume hosts (NFS-backed) +# The settings here are repeated for each infra host. +# They could instead be applied as global settings in +# user_variables, but are left here to illustrate that +# each container could have different storage targets. +storage_hosts: + controller00: + ip: 172.29.236.11 + container_vars: + cinder_backends: + limit_container_types: cinder_volume + lvm: + volume_group: cinder-volumes + volume_driver: cinder.volume.drivers.lvm.LVMVolumeDriver + volume_backend_name: LVM_iSCSI + iscsi_ip_address: "172.29.244.11" + controller01: + ip: 172.29.236.12 + container_vars: + cinder_backends: + limit_container_types: cinder_volume + lvm: + volume_group: cinder-volumes + volume_driver: cinder.volume.drivers.lvm.LVMVolumeDriver + volume_backend_name: LVM_iSCSI + iscsi_ip_address: "172.29.244.12" + controller02: + ip: 172.29.236.13 + container_vars: + cinder_backends: + limit_container_types: cinder_volume + lvm: + volume_group: cinder-volumes + volume_driver: cinder.volume.drivers.lvm.LVMVolumeDriver + volume_backend_name: LVM_iSCSI + iscsi_ip_address: "172.29.244.13" diff --git a/prototypes/openstack-ansible/file/user_variables.yml b/prototypes/openstack-ansible/file/user_variables.yml new file mode 100644 index 000000000..3e14bc57e --- /dev/null +++ b/prototypes/openstack-ansible/file/user_variables.yml @@ -0,0 +1,27 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +### +### This file contains commonly used overrides for convenience. Please inspect +### the defaults for each role to find additional override options. +### + +## Debug and Verbose options. +debug: false + +haproxy_keepalived_external_vip_cidr: "192.168.122.220/32" +haproxy_keepalived_internal_vip_cidr: "172.29.236.222/32" +haproxy_keepalived_external_interface: br-vlan +haproxy_keepalived_internal_interface: br-mgmt diff --git a/prototypes/openstack-ansible/playbooks/inventory b/prototypes/openstack-ansible/playbooks/inventory new file mode 100644 index 000000000..f53da5305 --- /dev/null +++ b/prototypes/openstack-ansible/playbooks/inventory @@ -0,0 +1,11 @@ +[jumphost] +jumphost ansible_ssh_host=192.168.122.2 + +[controller] +controller00 ansible_ssh_host=192.168.122.3 +controller01 ansible_ssh_host=192.168.122.4 +controller02 ansible_ssh_host=192.168.122.5 + +[compute] +compute00 ansible_ssh_host=192.168.122.6 +compute01 ansible_ssh_host=192.168.122.7 diff --git a/prototypes/openstack-ansible/playbooks/jumphost_configuration.yml b/prototypes/openstack-ansible/playbooks/jumphost_configuration.yml new file mode 100644 index 000000000..c51d83073 --- /dev/null +++ b/prototypes/openstack-ansible/playbooks/jumphost_configuration.yml @@ -0,0 +1,53 @@ +--- +- hosts: jumphost + remote_user: root + vars_files: + - ../var/ubuntu.yml + tasks: + - name: generate SSH keys + shell: ssh-keygen -b 2048 -t rsa -f /root/.ssh/id_rsa -q -N "" + args: + creates: /root/.ssh/id_rsa + - name: fetch public key + fetch: src="/root/.ssh/id_rsa.pub" dest="/" + - name: remove the directory + shell: "rm -rf {{OSA_PATH}} {{OSA_ETC_PATH}}" + - name: git openstack ansible + shell: "git clone {{OSA_URL}} {{OSA_PATH}} -b {{OSA_BRANCH}}" + - name: copy /opt/openstack-ansible/etc/openstack_deploy to /etc/openstack_deploy + shell: "/bin/cp -rf {{OSA_PATH}}/etc/openstack_deploy {{OSA_ETC_PATH}}" + - name: bootstrap + command: "/bin/bash ./scripts/bootstrap-ansible.sh" + args: + chdir: "{{OSA_PATH}}" + - name: generate password token + command: "python pw-token-gen.py --file /etc/openstack_deploy/user_secrets.yml" + args: + chdir: /opt/openstack-ansible/scripts/ + - name: copy openstack_user_config.yml to /etc/openstack_deploy + copy: + src: ../file/openstack_user_config.yml + dest: "{{OSA_ETC_PATH}}/openstack_user_config.yml" + - name: copy cinder.yml to /etc/openstack_deploy/env.d + copy: + src: ../file/cinder.yml + dest: "{{OSA_ETC_PATH}}/env.d/cinder.yml" + - name: copy user_variables.yml to /etc/openstack_deploy/ + copy: + src: ../file/user_variables.yml + dest: "{{OSA_ETC_PATH}}/user_variables.yml" + - name: configure network + template: + src: ../template/bifrost/controller.interface.j2 + dest: /etc/network/interfaces + notify: + - restart network service + handlers: + - name: restart network service + shell: "/sbin/ifconfig ens3 0 &&/sbin/ifdown -a && /sbin/ifup -a" + +- hosts: localhost + remote_user: root + tasks: + - name: Generate authorized_keys + shell: "/bin/cat /jumphost/root/.ssh/id_rsa.pub >> ../file/authorized_keys" diff --git a/prototypes/openstack-ansible/playbooks/targethost_configuration.yml b/prototypes/openstack-ansible/playbooks/targethost_configuration.yml new file mode 100644 index 000000000..ffe788f0e --- /dev/null +++ b/prototypes/openstack-ansible/playbooks/targethost_configuration.yml @@ -0,0 +1,61 @@ +--- +- hosts: all + remote_user: root + vars_files: + - ../var/ubuntu.yml + tasks: + - name: add public key to host + copy: + src: ../file/authorized_keys + dest: /root/.ssh/authorized_keys + - name: configure modules + copy: + src: ../file/modules + dest: /etc/modules + +- hosts: controller + remote_user: root + vars_files: + - ../var/ubuntu.yml + tasks: + - name: configure network + template: + src: ../template/bifrost/controller.interface.j2 + dest: /etc/network/interfaces + notify: + - restart network service + handlers: + - name: restart network service + shell: "/sbin/ifconfig ens3 0 &&/sbin/ifdown -a && /sbin/ifup -a" + +- hosts: compute + remote_user: root + vars_files: + - ../var/ubuntu.yml + tasks: + - name: configure network + template: + src: ../template/bifrost/compute.interface.j2 + dest: /etc/network/interfaces + notify: + - restart network service + handlers: + - name: restart network service + shell: "/sbin/ifconfig ens3 0 &&/sbin/ifdown -a && /sbin/ifup -a" + +- hosts: compute01 + remote_user: root + tasks: + - name: make nfs dir + file: "dest=/images mode=777 state=directory" + - name: configure sdrvice + shell: "echo 'nfs 2049/tcp' >> /etc/services && echo 'nfs 2049/udp' >> /etc/services" + - name: configure NFS + copy: + src: ../file/exports + dest: /etc/exports + notify: + - restart nfs service + handlers: + - name: restart nfs service + service: name=nfs-kernel-server state=restarted diff --git a/prototypes/openstack-ansible/scripts/osa_deploy.sh b/prototypes/openstack-ansible/scripts/osa_deploy.sh new file mode 100755 index 000000000..95f593194 --- /dev/null +++ b/prototypes/openstack-ansible/scripts/osa_deploy.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +export OSA_PATH=/opt/openstack-ansible +export LOG_PATH=$OSA_PATH/log +export PLAYBOOK_PATH=$OSA_PATH/playbooks +export OSA_BRANCH=${OSA_BRANCH:-"master"} + +JUMPHOST_IP="192.168.122.2" + +sudo /bin/rm -rf $LOG_PATH +sudo /bin/mkdir -p $LOG_PATH +sudo /bin/cp /root/.ssh/id_rsa.pub ../file/authorized_keys +sudo echo -e '\n'>>../file/authorized_keys + +cd ../playbooks/ +# this will prepare the jump host +# git clone the Openstack-Ansible, bootstrap and configure network +sudo ansible-playbook -i inventory jumphost_configuration.yml -vvv + +# this will prepare the target host +# such as configure network and NFS +sudo ansible-playbook -i inventory targethost_configuration.yml + +# using OpenStack-Ansible deploy the OpenStack + +echo "set UP Host !" +sudo /bin/sh -c "ssh root@$JUMPHOST_IP openstack-ansible \ + $PLAYBOOK_PATH/setup-hosts.yml" | \ + tee $LOG_PATH/setup-host.log + +#check the result of openstack-ansible setup-hosts.yml +#if failed, exit with exit code 1 +grep "failed=1" $LOG_PATH/setup-host.log>/dev/null \ + || grep "unreachable=1" $LOG_PATH/setup-host.log>/dev/null +if [ $? -eq 0 ]; then + echo "failed setup host!" + exit 1 +else + echo "setup host successfully!" +fi + +echo "Set UP Infrastructure !" +sudo /bin/sh -c "ssh root@$JUMPHOST_IP openstack-ansible \ + $PLAYBOOK_PATH/setup-infrastructure.yml" | \ + tee $LOG_PATH/setup-infrastructure.log + +grep "failed=1" $LOG_PATH/setup-infrastructure.log>/dev/null \ + || grep "unreachable=1" $LOG_PATH/setup-infrastructure.log>/dev/null +if [ $? -eq 0 ]; then + echo "failed setup infrastructure!" + exit 1 +else + echo "setup infrastructure successfully!" +fi + +sudo /bin/sh -c "ssh root@$JUMPHOST_IP ansible -i $PLAYBOOK_PATH/inventory/ \ + galera_container -m shell \ + -a "mysql -h localhost -e 'show status like \"%wsrep_cluster_%\";'"" \ + | tee $LOG_PATH/galera.log + +grep "FAILED" $LOG_PATH/galera.log>/dev/null +if [ $? -eq 0 ]; then + echo "failed verify the database cluster!" + exit 1 +else + echo "verify the database cluster successfully!" +fi + +echo "Set UP OpenStack !" +sudo /bin/sh -c "ssh root@$JUMPHOST_IP openstack-ansible \ + $PLAYBOOK_PATH/setup-openstack.yml" | \ + tee $LOG_PATH/setup-openstack.log + +grep "failed=1" $LOG_PATH/setup-openstack.log>/dev/null \ + || grep "unreachable=1" $LOG_PATH/setup-openstack.log>/dev/null +if [ $? -eq 0 ]; then + echo "failed setup openstack!" + exit 1 +else + echo "OpenStack successfully deployed!" + exit 0 +fi diff --git a/prototypes/openstack-ansible/template/bifrost/compute.interface.j2 b/prototypes/openstack-ansible/template/bifrost/compute.interface.j2 new file mode 100644 index 000000000..1719f6a08 --- /dev/null +++ b/prototypes/openstack-ansible/template/bifrost/compute.interface.j2 @@ -0,0 +1,86 @@ +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +# The loopback network interface +auto lo +iface lo inet loopback + + +# Physical interface +auto ens3 +iface ens3 inet manual + +# Container/Host management VLAN interface +auto ens3.10 +iface ens3.10 inet manual + vlan-raw-device ens3 + +# OpenStack Networking VXLAN (tunnel/overlay) VLAN interface +auto ens3.30 +iface ens3.30 inet manual + vlan-raw-device ens3 + +# Storage network VLAN interface (optional) +auto ens3.20 +iface ens3.20 inet manual + vlan-raw-device ens3 + +# Container/Host management bridge +auto br-mgmt +iface br-mgmt inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + bridge_ports ens3.10 + address {{host_info[inventory_hostname].MGMT_IP}} + netmask 255.255.252.0 + +# compute1 VXLAN (tunnel/overlay) bridge config +auto br-vxlan +iface br-vxlan inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + bridge_ports ens3.30 + address {{host_info[inventory_hostname].VXLAN_IP}} + netmask 255.255.252.0 + +# OpenStack Networking VLAN bridge +auto br-vlan +iface br-vlan inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + bridge_ports ens3 + address {{host_info[inventory_hostname].VLAN_IP}} + netmask 255.255.255.0 + gateway 192.168.122.1 + offload-sg off + # Create veth pair, don't bomb if already exists + pre-up ip link add br-vlan-veth type veth peer name eth12 || true + # Set both ends UP + pre-up ip link set br-vlan-veth up + pre-up ip link set eth12 up + # Delete veth pair on DOWN + post-down ip link del br-vlan-veth || true + bridge_ports br-vlan-veth + +# Add an additional address to br-vlan +iface br-vlan inet static + # Flat network default gateway + # -- This needs to exist somewhere for network reachability + # -- from the router namespace for floating IP paths. + # -- Putting this here is primarily for tempest to work. + address {{host_info[inventory_hostname].VLAN_IP_SECOND}} + netmask 255.255.252.0 + dns-nameserver 8.8.8.8 8.8.4.4 + +# compute1 Storage bridge +auto br-storage +iface br-storage inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + bridge_ports ens3.20 + address {{host_info[inventory_hostname].STORAGE_IP}} + netmask 255.255.252.0 diff --git a/prototypes/openstack-ansible/template/bifrost/controller.interface.j2 b/prototypes/openstack-ansible/template/bifrost/controller.interface.j2 new file mode 100644 index 000000000..74aeea99d --- /dev/null +++ b/prototypes/openstack-ansible/template/bifrost/controller.interface.j2 @@ -0,0 +1,71 @@ +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +# The loopback network interface +auto lo +iface lo inet loopback + +# Physical interface +auto ens3 +iface ens3 inet manual + +# Container/Host management VLAN interface +auto ens3.10 +iface ens3.10 inet manual + vlan-raw-device ens3 + +# OpenStack Networking VXLAN (tunnel/overlay) VLAN interface +auto ens3.30 +iface ens3.30 inet manual + vlan-raw-device ens3 + +# Storage network VLAN interface (optional) +auto ens3.20 +iface ens3.20 inet manual + vlan-raw-device ens3 + +# Container/Host management bridge +auto br-mgmt +iface br-mgmt inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + bridge_ports ens3.10 + address {{host_info[inventory_hostname].MGMT_IP}} + netmask 255.255.252.0 + +# OpenStack Networking VXLAN (tunnel/overlay) bridge +# +# Only the COMPUTE and NETWORK nodes must have an IP address +# on this bridge. When used by infrastructure nodes, the +# IP addresses are assigned to containers which use this +# bridge. +# +auto br-vxlan +iface br-vxlan inet manual + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + bridge_ports ens3.30 + +# OpenStack Networking VLAN bridge +auto br-vlan +iface br-vlan inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + bridge_ports ens3 + address {{host_info[inventory_hostname].VLAN_IP}} + netmask 255.255.255.0 + gateway 192.168.122.1 + dns-nameserver 8.8.8.8 8.8.4.4 + +# compute1 Storage bridge +auto br-storage +iface br-storage inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + bridge_ports ens3.20 + address {{host_info[inventory_hostname].STORAGE_IP}} + netmask 255.255.252.0 diff --git a/prototypes/openstack-ansible/var/ubuntu.yml b/prototypes/openstack-ansible/var/ubuntu.yml new file mode 100644 index 000000000..71f54ecb5 --- /dev/null +++ b/prototypes/openstack-ansible/var/ubuntu.yml @@ -0,0 +1,6 @@ +--- +OSA_URL: https://git.openstack.org/openstack/openstack-ansible +OSA_PATH: /opt/openstack-ansible +OSA_ETC_PATH: /etc/openstack_deploy +JUMPHOST_IP: 192.168.122.2 +host_info: {'jumphost':{'MGMT_IP': '172.29.236.10','VLAN_IP': '192.168.122.2', 'STORAGE_IP': '172.29.244.10'},'controller00':{'MGMT_IP': '172.29.236.11','VLAN_IP': '192.168.122.3', 'STORAGE_IP': '172.29.244.11'},'controller01':{'MGMT_IP': '172.29.236.12','VLAN_IP': '192.168.122.4', 'STORAGE_IP': '172.29.244.12'},'controller02':{'MGMT_IP': '172.29.236.13','VLAN_IP': '192.168.122.5', 'STORAGE_IP': '172.29.240.13'},'compute00':{'MGMT_IP': '172.29.236.14','VLAN_IP': '192.168.122.6','VLAN_IP_SECOND': '173.29.241.1','VXLAN_IP': '172.29.240.14', 'STORAGE_IP': '172.29.244.14'},'compute01':{'MGMT_IP': '172.29.236.15','VLAN_IP': '192.168.122.7','VLAN_IP_SECOND': '173.29.241.2','VXLAN_IP': '172.29.240.15', 'STORAGE_IP': '172.29.244.15'}} diff --git a/utils/test/reporting/api/handlers/landing.py b/utils/test/reporting/api/handlers/landing.py index 137c05007..ae1fd2037 100644 --- a/utils/test/reporting/api/handlers/landing.py +++ b/utils/test/reporting/api/handlers/landing.py @@ -6,15 +6,172 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## +import requests + from tornado.web import RequestHandler from tornado.escape import json_encode +from tornado.escape import json_decode -class FiltersHandler(RequestHandler): - def get(self): - return self.write(json_encode({'status': 'SUCCESS'})) +class BaseHandler(RequestHandler): + def _set_header(self): + self.set_header('Access-Control-Allow-Origin', '*') + self.set_header('Access-Control-Allow-Headers', + 'Content-Type, Content-Length, Authorization, \ + Accept, X-Requested-With , PRIVATE-TOKEN') + self.set_header('Access-Control-Allow-Methods', + 'PUT, POST, GET, DELETE, OPTIONS') -class ScenariosHandler(RequestHandler): +class FiltersHandler(BaseHandler): def get(self): - return self.write(json_encode({'status': 'SUCCESS'})) + self._set_header() + + filters = { + 'filters': { + 'status': ['success', 'warning', 'danger'], + 'projects': ['functest', 'yardstick'], + 'installers': ['apex', 'compass', 'fuel', 'joid'], + 'version': ['colorado', 'master'], + 'loops': ['daily', 'weekly', 'monthly'], + 'time': ['10 days', '30 days'] + } + } + return self.write(json_encode(filters)) + + +class ScenariosHandler(BaseHandler): + def post(self): + self._set_header() + + body = json_decode(self.request.body) + args = self._get_args(body) + + scenarios = self._get_result_data(self._get_scenarios(), args) + + return self.write(json_encode(dict(scenarios=scenarios))) + + def _get_result_data(self, data, args): + data = self._filter_status(data, args) + return {s: self._get_scenario_result(s, data[s], args) for s in data} + + def _filter_status(self, data, args): + return {k: v for k, v in data.items() if v['status'] in args['status']} + + def _get_scenario_result(self, scenario, data, args): + result = { + 'status': data.get('status'), + 'installers': self._get_installers_result(data['installers'], args) + } + return result + + def _get_installers_result(self, data, args): + func = self._get_installer_result + return {k: func(k, data.get(k, {}), args) for k in args['installers']} + + def _get_installer_result(self, installer, data, args): + projects = data.get(args['version'], []) + return [self._get_project_data(projects, p) for p in args['projects']] + + def _get_project_data(self, projects, project): + atom = { + 'project': project, + 'score': None, + 'status': None + } + for p in projects: + if p['project'] == project: + return p + return atom + + def _get_scenarios(self): + url = 'http://testresults.opnfv.org/test/api/v1/scenarios' + resp = requests.get(url).json() + data = self._change_to_utf8(resp).get('scenarios', {}) + return {a.get('name'): self._get_scenario(a.get('installers', []) + ) for a in data} + + def _get_scenario(self, data): + installers = {a.get('installer'): self._get_installer(a.get('versions', + []) + ) for a in data} + scenario = { + 'status': self._get_status(), + 'installers': installers + } + return scenario + + def _get_status(self): + return 'success' + + def _get_installer(self, data): + return {a.get('version'): self._get_version(a) for a in data} + + def _get_version(self, data): + try: + scores = data.get('score', {}).get('projects')[0] + trusts = data.get('trust_indicator', {}).get('projects')[0] + except (TypeError, IndexError): + return [] + else: + scores = {key: [dict(date=a.get('date')[:10], + score=a.get('score') + ) for a in scores[key]] for key in scores} + trusts = {key: [dict(date=a.get('date')[:10], + status=a.get('status') + ) for a in trusts[key]] for key in trusts} + atom = self._get_atom(scores, trusts) + return [dict(project=k, + score=sorted(atom[k], reverse=True)[0].get('score'), + status=sorted(atom[k], reverse=True)[0].get('status') + ) for k in atom if atom[k]] + + def _get_atom(self, scores, trusts): + s = {k: {a['date']: a['score'] for a in scores[k]} for k in scores} + t = {k: {a['date']: a['status'] for a in trusts[k]} for k in trusts} + return {k: [dict(score=s[k][a], status=t[k][a], data=a + ) for a in s[k] if a in t[k]] for k in s} + + def _change_to_utf8(self, obj): + if isinstance(obj, dict): + return {str(k): self._change_to_utf8(v) for k, v in obj.items()} + elif isinstance(obj, list): + return [self._change_to_utf8(ele) for ele in obj] + else: + try: + new = eval(obj) + if isinstance(new, int): + return obj + return self._change_to_utf8(new) + except (NameError, TypeError, SyntaxError): + return str(obj) + + def _get_args(self, body): + status = self._get_status_args(body) + projects = self._get_projects_args(body) + installers = self._get_installers_args(body) + + args = { + 'status': status, + 'projects': projects, + 'installers': installers, + 'version': body.get('version', 'master').lower(), + 'loops': body.get('loops', 'daily').lower(), + 'time': body.get('times', '10 days')[:2].lower() + } + return args + + def _get_status_args(self, body): + status_all = ['success', 'warning', 'danger'] + status = [a.lower() for a in body.get('status', ['all'])] + return status_all if 'all' in status else status + + def _get_projects_args(self, body): + project_all = ['functest', 'yardstick'] + projects = [a.lower() for a in body.get('projects', ['all'])] + return project_all if 'all' in projects else projects + + def _get_installers_args(self, body): + installer_all = ['apex', 'compass', 'fuel', 'joid'] + installers = [a.lower() for a in body.get('installers', ['all'])] + return installer_all if 'all' in installers else installers diff --git a/utils/test/reporting/api/install.sh b/utils/test/reporting/api/install.sh new file mode 100755 index 000000000..55d6b77ec --- /dev/null +++ b/utils/test/reporting/api/install.sh @@ -0,0 +1,3 @@ +apt-get install -y python-pip +pip install tornado +pip install requests diff --git a/utils/test/reporting/docker/reporting.sh b/utils/test/reporting/docker/reporting.sh index 78bcc4e82..1de13ae32 100755 --- a/utils/test/reporting/docker/reporting.sh +++ b/utils/test/reporting/docker/reporting.sh @@ -79,10 +79,4 @@ echo "daemon off;" >> /etc/nginx/nginx.conf # supervisor config cp /home/opnfv/utils/test/reporting/docker/supervisor.conf /etc/supervisor/conf.d/ -# build pages -cd pages ln -s /usr/bin/nodejs /usr/bin/node -npm install -npm install -g grunt bower -bower install --allow-root -grunt build diff --git a/utils/test/reporting/docker/supervisor.conf b/utils/test/reporting/docker/supervisor.conf index 0c2207793..1e0eed9c8 100644 --- a/utils/test/reporting/docker/supervisor.conf +++ b/utils/test/reporting/docker/supervisor.conf @@ -14,3 +14,9 @@ autorestart = true user = root command = service nginx restart autorestart = true + +[program:reporting_angular] +user = root +directory = /home/opnfv/utils/test/reporting/pages +command = bash angular.sh +autorestart = true diff --git a/utils/test/reporting/pages/angular.sh b/utils/test/reporting/pages/angular.sh new file mode 100755 index 000000000..a7f167516 --- /dev/null +++ b/utils/test/reporting/pages/angular.sh @@ -0,0 +1,10 @@ +: ${SERVER_URL:='http://testresults.opnfv.org/reporting/api'} + +echo "var BASE_URL = 'http://${SERVER_URL}/landing-page'" > app/scripts/app.config.js + +apt-get install -y nodejs +apt-get install -y npm +npm install +npm install -g grunt bower +bower install --allow-root +grunt build diff --git a/utils/test/reporting/pages/app/images/green.png b/utils/test/reporting/pages/app/images/green.png Binary files differnew file mode 100644 index 000000000..57fc59927 --- /dev/null +++ b/utils/test/reporting/pages/app/images/green.png diff --git a/utils/test/reporting/pages/app/images/green@2x.png b/utils/test/reporting/pages/app/images/green@2x.png Binary files differnew file mode 100644 index 000000000..3bda5beb6 --- /dev/null +++ b/utils/test/reporting/pages/app/images/green@2x.png diff --git a/utils/test/reporting/pages/app/index.html b/utils/test/reporting/pages/app/index.html index 7673a4cc2..1159c2176 100644 --- a/utils/test/reporting/pages/app/index.html +++ b/utils/test/reporting/pages/app/index.html @@ -1,6 +1,7 @@ <!doctype html> <html ng-app="opnfvApp"> - <head> + +<head> <meta charset="utf-8"> <title>OPNFV-DASHBOARD EXAMPLE</title> <meta name="description" content=""> @@ -13,17 +14,22 @@ <link rel="stylesheet" href="bower_components/chosen/chosen.css" /> <link rel="stylesheet" href="bower_components/selectize/dist/css/selectize.css" /> <link rel="stylesheet" href="bower_components/components-font-awesome/css/font-awesome.css" /> + <link rel="stylesheet" href="bower_components/angular-tooltips/dist/angular-tooltips.min.css" /> + <link rel="stylesheet" href="bower_components/animate.css/animate.css" /> + <link rel="stylesheet" href="bower_components/ng-dialog/css/ngDialog.css" /> + <link rel="stylesheet" href="bower_components/ng-dialog/css/ngDialog-theme-default.css" /> + <link rel="stylesheet" href="bower_components/inspiniacss/style.css" /> <!-- endbower --> <!-- endbuild --> <!-- build:css(.tmp) styles/style.css --> - <!--<link rel="stylesheet" href="styles/main.css">--> - <link rel="stylesheet" href="styles/animate.css"> - <link rel="stylesheet" href="styles/style.css"> + <link rel="stylesheet" href="styles/custome.css"> + <!-- endbuild --> - </head> - <body class="{{$state.current.data.specialClass}}" id="page-top"> +</head> + +<body class="{{$state.current.data.specialClass}}" id="page-top"> <!--[if lte IE 8]> <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> <![endif]--> @@ -31,7 +37,7 @@ <!-- Add your site or application content here --> <div ui-view></div> <!-- Google Analytics: change UA-XXXXX-X to be your site's ID --> - <!--<script> + <!--<script> !function(A,n,g,u,l,a,r){A.GoogleAnalyticsObject=l,A[l]=A[l]||function(){ (A[l].q=A[l].q||[]).push(arguments)},A[l].l=+new Date,a=n.createElement(g), r=n.getElementsByTagName(g)[0],a.src=u,r.parentNode.insertBefore(a,r) @@ -59,17 +65,27 @@ <script src="bower_components/microplugin/src/microplugin.js"></script> <script src="bower_components/selectize/dist/js/selectize.js"></script> <script src="bower_components/angular-selectize2/dist/angular-selectize.js"></script> + <script src="bower_components/angular-tooltips/dist/angular-tooltips.min.js"></script> + <script src="bower_components/jQuery-rwdImageMaps/jquery.rwdImageMaps.min.js"></script> + <script src="bower_components/ng-dialog/js/ngDialog.js"></script> <!-- endbower --> <!-- endbuild --> - <!-- build:js({.tmp,app}) scripts/scripts.js --> - <script src="scripts/app.js"></script> - <!--<script src="scripts/controllers/main.js"></script>--> - <script src="scripts/config.router.js"></script> - <script src="scripts/controllers/table.controller.js"></script> - <script src="scripts/config.js"></script> - <script src="scripts/directives/mydirective.js"></script> - <script src="scripts/factory/table.factory.js"></script> - <!-- endbuild --> + <!-- build:js({.tmp,app}) scripts/scripts.js --> + <script src="scripts/app.js"></script> + <!--<script src="scripts/controllers/main.js"></script>--> + <script src="scripts/config.router.js"></script> + <script src="scripts/controllers/table.controller.js"></script> + <script src="scripts/config.js"></script> + <script src="scripts/factory/table.factory.js"></script> + <script src="scripts/controllers/case.controller.js"></script> + <script src="scripts/controllers/auth.controller.js"></script> + <script src="scripts/controllers/admin.controller.js"></script> + <script src="scripts/controllers/main.controller.js"></script> + <script src="scripts/app.config.js"></script> + <script src="scripts/controllers/testvisual.controller.js"></script> + + <!-- endbuild --> </body> -</html> + +</html>
\ No newline at end of file diff --git a/utils/test/reporting/pages/app/scripts/app.config.js b/utils/test/reporting/pages/app/scripts/app.config.js new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/utils/test/reporting/pages/app/scripts/app.config.js diff --git a/utils/test/reporting/pages/app/scripts/app.js b/utils/test/reporting/pages/app/scripts/app.js index 6e99ce3d7..d06019c55 100644 --- a/utils/test/reporting/pages/app/scripts/app.js +++ b/utils/test/reporting/pages/app/scripts/app.js @@ -9,12 +9,13 @@ * Main module of the application. */ angular - .module('opnfvApp', [ - 'ngAnimate', - 'ui.router', - 'oc.lazyLoad', - 'ui.bootstrap', - 'ngResource', - 'selectize' + .module('opnfvApp', [ + 'ngAnimate', + 'ui.router', + 'oc.lazyLoad', + 'ui.bootstrap', + 'ngResource', + 'selectize', + '720kb.tooltips' - ]); + ]);
\ No newline at end of file diff --git a/utils/test/reporting/pages/app/scripts/config.js b/utils/test/reporting/pages/app/scripts/config.js index 838460a38..1010169d3 100644 --- a/utils/test/reporting/pages/app/scripts/config.js +++ b/utils/test/reporting/pages/app/scripts/config.js @@ -7,8 +7,13 @@ * Main config file of the application. */ angular - .module('opnfvApp').config(function () { + .module('opnfvApp').config(['$httpProvider', '$qProvider', function($httpProvider, $qProvider) { - } + $httpProvider.defaults.useXDomain = true; + delete $httpProvider.defaults.headers.common['X-Requested-With']; - ) + $qProvider.errorOnUnhandledRejections(false); + + } + + ]);
\ No newline at end of file diff --git a/utils/test/reporting/pages/app/scripts/config.router.js b/utils/test/reporting/pages/app/scripts/config.router.js index 641ea6a74..d38ad7507 100644 --- a/utils/test/reporting/pages/app/scripts/config.router.js +++ b/utils/test/reporting/pages/app/scripts/config.router.js @@ -23,7 +23,7 @@ angular.module('opnfvApp') $stateProvider .state('landingpage', { url: "/landingpage", - //controller: 'MainCtrl', + controller: 'MainController', templateUrl: "views/main.html", data: { pageTitle: '首页', specialClass: 'landing-page' }, resolve: { diff --git a/utils/test/reporting/pages/app/scripts/controllers/main.controller.js b/utils/test/reporting/pages/app/scripts/controllers/main.controller.js new file mode 100644 index 000000000..2054dc2dd --- /dev/null +++ b/utils/test/reporting/pages/app/scripts/controllers/main.controller.js @@ -0,0 +1,32 @@ +'use strict'; + +/** + * @ngdoc function + * @name opnfvdashBoardAngularApp.controller:MainPageController + * @description + * # TableController + * Controller of the opnfvdashBoardAngularApp + */ +angular.module('opnfvApp') + .controller('MainController', ['$scope', '$state', '$stateParams', function($scope, $state, $stateParams) { + + init(); + + function init() { + $scope.goTest = goTest; + $scope.goLogin = goLogin; + + } + + function goTest() { + $state.go("select.selectTestCase"); + } + + function goLogin() { + $state.go("login"); + } + + + + + }]);
\ No newline at end of file diff --git a/utils/test/reporting/pages/app/scripts/controllers/table.controller.js b/utils/test/reporting/pages/app/scripts/controllers/table.controller.js index 8ca1e474c..0f3a17a03 100644 --- a/utils/test/reporting/pages/app/scripts/controllers/table.controller.js +++ b/utils/test/reporting/pages/app/scripts/controllers/table.controller.js @@ -8,255 +8,131 @@ * Controller of the opnfvdashBoardAngularApp */ angular.module('opnfvApp') - .controller('TableController', ['$scope', '$state', '$stateParams', 'TableFactory', function ($scope, $state, $stateParams, TableFactory) { + .controller('TableController', ['$scope', '$state', '$stateParams', '$http', 'TableFactory', function($scope, $state, $stateParams, $http, TableFactory) { $scope.filterlist = []; $scope.selection = []; - $scope.statusList = ["Success", "Warning", "Danger"]; - $scope.projectList = ["Deployment", "Functest", "Yardstick"]; - $scope.installerList = ["apex", "compass", "fuel", "joid"]; - $scope.versionlist = ["Colorado", "Master"]; - $scope.loopci = ["Daily", "Weekly", "Monthly"]; - $scope.time = ["10 days", "1 Month"]; + $scope.statusList = []; + $scope.projectList = []; + $scope.installerList = []; + $scope.versionlist = []; + $scope.loopci = []; + $scope.time = []; $scope.tableDataAll = {}; $scope.tableInfoAll = {}; + $scope.scenario = {}; + $scope.VersionConfig = { + create: true, + valueField: 'title', + labelField: 'title', + delimiter: '|', + maxItems: 1, + placeholder: 'Version', + onChange: function(value) { + checkElementArrayValue($scope.selection, $scope.VersionOption); + $scope.selection.push(value); + // console.log($scope.selection); + getScenarioData(); + } + } - $scope.scenario = - { - "scenarios": { - "os-nosdn-kvm-noha": { - "status": "Success", - "installers": { - "apex": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS", - - - }, - { - "project": "Functest", - "score": "null", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ], - "compass": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ], - "fuel": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ], - "joid": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ] - } - }, - "os-nosdn-ovs-ha": { - "status": "Danger", - "installers": { - "apex": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS", - - - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ], - "compass": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ], - "fuel": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ], - "joid": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ] - } - }, - "os-nosdn-ovs-noha": { - "status": "Warning", - "installers": { - "apex": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS", - - - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ], - "compass": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ], - "fuel": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ], - "joid": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "score": "13/14", - "status": "SUCCESS" - } - ] - } - } + $scope.LoopConfig = { + create: true, + valueField: 'title', + labelField: 'title', + delimiter: '|', + maxItems: 1, + placeholder: 'Loop', + onChange: function(value) { + checkElementArrayValue($scope.selection, $scope.LoopOption); + $scope.selection.push(value); + // console.log($scope.selection); + getScenarioData(); + + } + } + + $scope.TimeConfig = { + create: true, + valueField: 'title', + labelField: 'title', + delimiter: '|', + maxItems: 1, + placeholder: 'Time', + onChange: function(value) { + checkElementArrayValue($scope.selection, $scope.TimeOption); + $scope.selection.push(value); + // console.log($scope.selection) + getScenarioData(); + + + } + } + + + init(); + + function init() { + $scope.toggleSelection = toggleSelection; + getScenarioData(); + // radioSetting(); + getFilters(); + } + + function getFilters() { + TableFactory.getFilter().get({ + + + }).$promise.then(function(response) { + if (response != null) { + $scope.statusList = response.filters.status; + $scope.projectList = response.filters.projects; + $scope.installerList = response.filters.installers; + $scope.versionlist = response.filters.version; + $scope.loopci = response.filters.loops; + $scope.time = response.filters.time; + + $scope.statusListString = $scope.statusList.toString(); + $scope.projectListString = $scope.projectList.toString(); + $scope.installerListString = $scope.installerList.toString(); + $scope.VersionSelected = $scope.versionlist[1]; + $scope.LoopCiSelected = $scope.loopci[0]; + $scope.TimeSelected = $scope.time[0]; + radioSetting($scope.versionlist, $scope.loopci, $scope.time); + + } else { + alert("网络错误"); } + }) + } + + function getScenarioData() { + + var utl = BASE_URL + '/scenarios'; + var data = { + 'status': ['success', 'danger', 'warning'], + 'projects': ['functest', 'yardstick'], + 'installers': ['apex', 'compass', 'fuel', 'joid'], + 'version': $scope.VersionSelected, + 'loops': $scope.LoopCiSelected, + 'time': $scope.TimeSelected }; + var config = { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;' + } + } + $http.post(utl, data, config).then(function(response) { + if (response.status == 200) { + $scope.scenario = response.data; + constructJson(); + } + }) + } - // var headData = Object.keys($scope.scenario.scenarios.os_nosdn_kvm_noha.installers); - // $scope.headData = headData; - //construct json + //construct json function constructJson() { var colspan; @@ -267,19 +143,22 @@ angular.module('opnfvApp') for (var item in $scope.scenario.scenarios) { - - - - var headData = Object.keys($scope.scenario.scenarios[item].installers); + var headData = Object.keys($scope.scenario.scenarios[item].installers).sort(); var scenarioStatus = $scope.scenario.scenarios[item].status; - + var scenarioStatusDisplay; + if (scenarioStatus == "success") { + scenarioStatusDisplay = "navy"; + } else if (scenarioStatus == "danger") { + scenarioStatusDisplay = "danger"; + } else if (scenarioStatus == "warning") { + scenarioStatusDisplay = "warning"; + } InstallerData = headData; var projectData = []; var datadisplay = []; var projects = []; - for (var j = 0; j < headData.length; j++) { projectData.push($scope.scenario.scenarios[item].installers[headData[j]]); @@ -289,9 +168,30 @@ angular.module('opnfvApp') for (var k = 0; k < projectData[j].length; k++) { projects.push(projectData[j][k].project); var temArray = []; - temArray.push(projectData[j][k].score); - temArray.push(projectData[j][k].project); - temArray.push(headData[j]); + if (projectData[j][k].score == null) { + temArray.push("null"); + temArray.push(projectData[j][k].project); + temArray.push(headData[j]); + } else { + temArray.push(projectData[j][k].score); + temArray.push(projectData[j][k].project); + temArray.push(headData[j]); + } + + + if (projectData[j][k].status == "platinium") { + temArray.push("primary"); + temArray.push("P"); + } else if (projectData[j][k].status == "gold") { + temArray.push("danger"); + temArray.push("G"); + } else if (projectData[j][k].status == "silver") { + temArray.push("warning"); + temArray.push("S"); + } else if (projectData[j][k].status == null) { + temArray.push("null"); + } + datadisplay.push(temArray); } @@ -301,13 +201,21 @@ angular.module('opnfvApp') colspan = projects.length / headData.length; var tabledata = { - scenarioName: item, Installer: InstallerData, projectData: projectData, projects: projects, - datadisplay: datadisplay, colspan: colspan, status: scenarioStatus + scenarioName: item, + Installer: InstallerData, + projectData: projectData, + projects: projects, + datadisplay: datadisplay, + colspan: colspan, + status: scenarioStatus, + statusDisplay: scenarioStatusDisplay }; JSON.stringify(tabledata); $scope.tableDataAll.scenario.push(tabledata); + // console.log(tabledata); + } @@ -315,15 +223,13 @@ angular.module('opnfvApp') var tempHeadData = []; - - for (var i = 0; i < InstallerData.length; i++) { for (var j = 0; j < colspan; j++) { tempHeadData.push(InstallerData[i]); } } - console.log(tempHeadData); + //console.log(tempHeadData); var projectsInfoAll = []; @@ -334,13 +240,14 @@ angular.module('opnfvApp') projectsInfoAll.push(tempA); } - console.log(projectsInfoAll); + //console.log(projectsInfoAll); $scope.tableDataAll["colspan"] = colspan; $scope.tableDataAll["Installer"] = InstallerData; $scope.tableDataAll["Projects"] = projectsInfoAll; - console.log($scope.tableDataAll); + // console.log($scope.tableDataAll); + $scope.colspan = $scope.tableDataAll.colspan; } @@ -353,58 +260,11 @@ angular.module('opnfvApp') return size; } - init(); - function init() { - $scope.toggleSelection = toggleSelection; - - constructJson(); - - } - - // $scope.test=false; + $scope.colspan = $scope.tableDataAll.colspan; + // console.log($scope.colspan); - var statusListString = $scope.statusList.toString(); - var projectListString = $scope.projectList.toString(); - var installerListString = $scope.installerList.toString(); - - $scope.colspan=$scope.tableDataAll.colspan; - //filter function - function filterData() { - - - $scope.selectInstallers = []; - $scope.selectProjects = []; - $scope.selectStatus = []; - for (var i = 0; i < $scope.selection.length; i++) { - if (statusListString.indexOf($scope.selection[i]) > -1) { - $scope.selectStatus.push($scope.selection[i]); - } - if (projectListString.indexOf($scope.selection[i]) > -1) { - $scope.selectProjects.push($scope.selection[i]); - } - if (installerListString.indexOf($scope.selection[i]) > -1) { - $scope.selectInstallers.push($scope.selection[i]); - } - } - - $scope.colspan=$scope.selectProjects.length; - //when some selection is empty, we set it full - if($scope.selectInstallers.length==0){ - $scope.selectInstallers=$scope.installerList; - - } - if($scope.selectProjects.length==0){ - $scope.selectProjects=$scope.projectList; - $scope.colspan=$scope.tableDataAll.colspan; - } - if($scope.selectStatus.length==0){ - $scope.selectStatus=$scope.statusList - } - } - - - //find all same element index + //find all same element index function getSameElementIndex(array, element) { var indices = []; var idx = array.indexOf(element); @@ -424,64 +284,31 @@ angular.module('opnfvApp') } - - $scope.VersionOption = [ - { title: 'Colorado' }, - { title: 'Master' } - ]; - $scope.VersionConfig = { - create: true, - valueField: 'title', - labelField: 'title', - delimiter: '|', - maxItems: 1, - placeholder: 'Version', - onChange: function (value) { - checkElementArrayValue($scope.selection, $scope.VersionOption); - $scope.selection.push(value); - // console.log($scope.selection); - + function radioSetting(array1, array2, array3) { + var tempVersion = []; + var tempLoop = []; + var tempTime = []; + for (var i = 0; i < array1.length; i++) { + var temp = { + title: array1[i] + }; + tempVersion.push(temp); } - - } - - $scope.LoopOption = [ - { title: 'Daily' }, - { title: 'Weekly' }, - { title: 'Monthly' } - ]; - $scope.LoopConfig = { - create: true, - valueField: 'title', - labelField: 'title', - delimiter: '|', - maxItems: 1, - placeholder: 'Loop', - onChange: function (value) { - checkElementArrayValue($scope.selection, $scope.LoopOption); - $scope.selection.push(value); - // console.log($scope.selection); - + for (var i = 0; i < array2.length; i++) { + var temp = { + title: array2[i] + }; + tempLoop.push(temp); } - } - - $scope.TimeOption = [ - { title: '10 days' }, - { title: '1 month' } - ]; - $scope.TimeConfig = { - create: true, - valueField: 'title', - labelField: 'title', - delimiter: '|', - maxItems: 1, - placeholder: 'Time', - onChange: function (value) { - checkElementArrayValue($scope.selection, $scope.TimeOption); - $scope.selection.push(value); - // console.log($scope.selection) - + for (var i = 0; i < array3.length; i++) { + var temp = { + title: array3[i] + }; + tempTime.push(temp); } + $scope.VersionOption = tempVersion; + $scope.LoopOption = tempLoop; + $scope.TimeOption = tempTime; } //remove element in the array @@ -508,13 +335,51 @@ angular.module('opnfvApp') if (idx > -1) { $scope.selection.splice(idx, 1); - } - else { + filterData($scope.selection) + } else { $scope.selection.push(status); + filterData($scope.selection) } - console.log($scope.selection); - filterData(); + // console.log($scope.selection); } - }]); + //filter function + function filterData(selection) { + + $scope.selectInstallers = []; + $scope.selectProjects = []; + $scope.selectStatus = []; + for (var i = 0; i < selection.length; i++) { + if ($scope.statusListString.indexOf(selection[i]) > -1) { + $scope.selectStatus.push(selection[i]); + } + if ($scope.projectListString.indexOf(selection[i]) > -1) { + $scope.selectProjects.push(selection[i]); + } + if ($scope.installerListString.indexOf(selection[i]) > -1) { + $scope.selectInstallers.push(selection[i]); + } + } + + $scope.colspan = $scope.selectProjects.length; + //when some selection is empty, we set it full + if ($scope.selectInstallers.length == 0) { + $scope.selectInstallers = $scope.installerList; + + } + if ($scope.selectProjects.length == 0) { + $scope.selectProjects = $scope.projectList; + $scope.colspan = $scope.tableDataAll.colspan; + } + if ($scope.selectStatus.length == 0) { + $scope.selectStatus = $scope.statusList + } + + // console.log($scope.selectStatus); + // console.log($scope.selectProjects); + + } + + + }]);
\ No newline at end of file diff --git a/utils/test/reporting/pages/app/scripts/data.json b/utils/test/reporting/pages/app/scripts/data.json deleted file mode 100644 index a15fdf37e..000000000 --- a/utils/test/reporting/pages/app/scripts/data.json +++ /dev/null @@ -1,76 +0,0 @@ - -{"scenarios": { - "os-nosdn-kvm-noha": { - "status": "Success", - "installers": { - "apex": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "socre": "13/14", - "status": "SUCCESS" - } - ], - "compass": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "socre": "13/14", - "status": "SUCCESS" - } - ], - "fuel": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "socre": "13/14", - "status": "SUCCESS" - } - ], - "joid": [ - { - "project": "Deployment", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Functest", - "score": "13/14", - "status": "SUCCESS" - }, - { - "project": "Yardstick", - "socre": "13/14", - "status": "SUCCESS" - } - ] - } - } -}} diff --git a/utils/test/reporting/pages/app/scripts/factory/table.factory.js b/utils/test/reporting/pages/app/scripts/factory/table.factory.js index 22443221e..a2e2aeff0 100644 --- a/utils/test/reporting/pages/app/scripts/factory/table.factory.js +++ b/utils/test/reporting/pages/app/scripts/factory/table.factory.js @@ -4,17 +4,23 @@ * get data factory */ angular.module('opnfvApp') - .factory('TableFactory', function ($resource, $rootScope) { - // var baseUrl = base_Url; + .factory('TableFactory', function($resource, $rootScope) { return { - getFilter: function () { - return $resource(baseUrl + '/', {}, { - 'post': { - method: 'POST', + getFilter: function() { + return $resource(BASE_URL + '/filters', {}, { + 'get': { + method: 'GET', } }); + }, + getScenario: function() { + return $resource(BASE_URL + '/scenarios', {}, { + 'post': { + method: 'POST', + } + }) } }; - }); + });
\ No newline at end of file diff --git a/utils/test/reporting/pages/app/styles/custome.css b/utils/test/reporting/pages/app/styles/custome.css index dadc68a03..b498cf04d 100644 --- a/utils/test/reporting/pages/app/styles/custome.css +++ b/utils/test/reporting/pages/app/styles/custome.css @@ -1,8 +1,8 @@ .container-tablesize { - margin: auto 5%; + margin: auto 5%; } -.btn-outline { +.btn-outline { border-color: white; } @@ -29,6 +29,68 @@ } .myhr { - border:0.5px dashed #e7eaec; - border-top:1px;margin-bottom: 3px; -}
\ No newline at end of file + border: 0.5px dashed #e7eaec; + border-top: 1px; + margin-bottom: 3px; +} + +td.null { + background-color: #e7eaec; + color: #e7eaec; +} + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; + display: none; +} + +body, +html { + margin: 0; + padding: 0; + min-height: 100%; +} + + +/*img[usemap] { + border: none; + height: auto; + max-width: 100%; + width: auto; +}*/ + +.popup { + position: absolute; + display: none; + /*background-color: #dd8;*/ + border-radius: 5px 5px 5px 5px; + background-color: #f3f3f4; + opacity: 0.9; +} + + +/* +body { + height: 1200px; +} + +html { + min-height: 100%; +}*/ + + +/*html, +body { + height: 100%; +} + +#page-wrapper { + position: inherit; + margin: 0 0 0 220px; + min-height: 773px; +}*/
\ No newline at end of file diff --git a/utils/test/reporting/pages/app/styles/fonts/glyphicons-halflings-regular.svg b/utils/test/reporting/pages/app/styles/fonts/glyphicons-halflings-regular.svg index 187805af6..94fb5490a 100644 --- a/utils/test/reporting/pages/app/styles/fonts/glyphicons-halflings-regular.svg +++ b/utils/test/reporting/pages/app/styles/fonts/glyphicons-halflings-regular.svg @@ -285,4 +285,4 @@ <glyph unicode="🔑" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" /> <glyph unicode="🚪" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" /> </font> -</defs></svg> +</defs></svg>
\ No newline at end of file diff --git a/utils/test/reporting/pages/app/views/commons/table.html b/utils/test/reporting/pages/app/views/commons/table.html index ed9300edd..f504bd76b 100644 --- a/utils/test/reporting/pages/app/views/commons/table.html +++ b/utils/test/reporting/pages/app/views/commons/table.html @@ -29,81 +29,85 @@ <div class=" col-md-12" data-toggle="buttons" aria-pressed="false"> <label> Status </label> - <label class="btn btn-outline btn-success btn-sm" style="height:25px; margin-right: 5px;" ng-repeat="status in statusList" - value={{status}} ng-checked="selection.indexOf(status)>-1" ng-click="toggleSelection(status)"> + <label class="btn btn-outline btn-success btn-sm" style="height:25px; margin-right: 5px;" ng-repeat="status in statusList" value={{status}} ng-checked="selection.indexOf(status)>-1" ng-click="toggleSelection(status)"> <input type="checkbox" disabled="disabled" > {{status}} + </label> </div> - <hr class="myhr"> + <hr class="myhr"> <div class=" col-md-12" data-toggle="buttons"> - <label> Projects </label> - <label class="btn btn-outline btn-success btn-sm " style="height:25px;margin-right: 5px;" ng-repeat="project in projectList" - value={{project}} ng-checked="selection.indexOf(project)>-1" ng-click="toggleSelection(project)"> + <label> Projects </label> + <label class="btn btn-outline btn-success btn-sm " style="height:25px;margin-right: 5px;" ng-repeat="project in projectList" value={{project}} ng-checked="selection.indexOf(project)>-1" ng-click="toggleSelection(project)"> <input type="checkbox" disabled="disabled"> {{project}} </label> </div> - <hr class="myhr"> + <hr class="myhr"> <div class=" col-md-12" data-toggle="buttons"> <label> Installers </label> - <label class="btn btn-outline btn-success btn-sm" style="height:25px;margin-right: 5px;" ng-repeat="installer in installerList" - value={{installer}} ng-checked="selection.indexOf(installer)" ng-click="toggleSelection(installer)"> + <label class="btn btn-outline btn-success btn-sm" style="height:25px;margin-right: 5px;" ng-repeat="installer in installerList" value={{installer}} ng-checked="selection.indexOf(installer)>-1" ng-click="toggleSelection(installer)"> <input type="checkbox" disabled="disabled"> {{installer}} </label> - </div> + </div> - <hr style="border:0.5px dashed #e7eaec;border-top:1px;margin-bottom:10px;"> + <hr style="border:0.5px dashed #e7eaec;border-top:1px;margin-bottom:10px;"> - <div class=" col-md-1" style="margin-top:5px;margin-right: 5px;"> - <selectize options="VersionOption" ng-model="VersionSelected" config="VersionConfig"></selectize> + <div class=" col-md-1" style="margin-top:5px;margin-right: 5px;"> + <selectize options="VersionOption" ng-model="VersionSelected" config="VersionConfig"></selectize> - </div> + </div> - <div class=" col-md-1" style="margin-top:5px;margin-left: 5px;margin-right: 5px;"> - <selectize options="LoopOption" ng-model="LoopCiSelected" config="LoopConfig"></selectize> + <div class=" col-md-1" style="margin-top:5px;margin-right: 5px;"> + <selectize options="LoopOption" ng-model="LoopCiSelected" config="LoopConfig"></selectize> - </div> + </div> - <div class=" col-md-1" style="margin-top:5px;margin-left: 5px;margin-right: 5px;"> - <selectize options="TimeOption" ng-model="TimeSelected" config="TimeConfig"></selectize> + <div class=" col-md-1" style="margin-top:5px;margin-right: 5px;"> + <selectize options="TimeOption" ng-model="TimeSelected" config="TimeConfig"></selectize> + </div> </div> + <div class="table-responsive"> + + <table class="table table-bordered" id="table" ng-model="tableDataAll"> + <thead class="thead"> + <tr> + <th>Scenario </th> + <th colspan={{colspan}} ng-show="selectInstallers.indexOf(key)!=-1" value={{key}} ng-repeat="key in tableDataAll.Installer"><a href="notfound.html">{{key}}</a> </th> + </tr> + <tr> -</div> + <td></td> + <td ng-show="selectProjects.indexOf(project[0])!=-1 && selectInstallers.indexOf(project[1])!=-1" ng-repeat="project in tableDataAll.Projects track by $index" data={{project[1]}} value={{project[0]}}>{{project[0]}}</td> -<table class="table table-bordered" id="table" ng-model="tableDataAll"> - <thead class="thead"> - <tr > - <th>Scenario </th> - <th colspan={{colspan}} ng-show="selectInstallers.indexOf(key)!=-1" value={{key}} ng-repeat="key in tableDataAll.Installer"><a href="notfound.html">{{key}}</a> </th> - </tr> + </tr> + </thead> + <tbody class="tbody"> + <tr ng-repeat="scenario in tableDataAll.scenario" ng-show="selectStatus.indexOf(scenario.status)!=-1"> - <tr> + <td nowrap="nowrap" data={{scenario.status}}><span class="fa fa-circle text-{{scenario.statusDisplay}}"></span> <a href="notfound.html">{{scenario.scenarioName}}</a> </td> - <td align="justify"></td> - <td align="justify" ng-show="selectProjects.indexOf(project[0])!=-1 && selectInstallers.indexOf(project[1])!=-1" ng-repeat="project in tableDataAll.Projects track by $index" data={{project[1]}} value={{project[0]}}>{{project[0]}}</td> - </tr> - </thead> - <tbody class="tbody"> - <tr ng-repeat="scenario in tableDataAll.scenario" ng-show="selectStatus.indexOf(scenario.status)!=-1" > + <!--<td style="background-color:#e7eaec" align="justify" ng-if="data[0]=='Not Support'" ng-repeat="data in scenario.datadisplay track by $index" data={{data[1]}} value={{data[2]}}></td>--> - <td align="justify" data={{scenario.status}}><span class="fa fa-circle text-warning"><a href="notfound.html">{{scenario.scenarioName}}</a></span> </td> - <td align="justify" ng-show="selectInstallers.indexOf(data[2])!=-1 && selectProjects.indexOf(data[1])!=-1" ng-repeat="data in scenario.datadisplay track by $index" data={{data[1]}} value={{data[2]}} ><span class="label label-danger">D<a href="notfound.html"></a></span> {{data[0]}}</td> - </tr> - </tbody> -</table> + <td nowrap="nowrap" ng-show="selectInstallers.indexOf(data[2])!=-1 && selectProjects.indexOf(data[1])!=-1" ng-repeat="data in scenario.datadisplay track by $index" data={{data[1]}} value={{data[2]}} class={{data[0]}}> + <span class="label label-{{data[3]}}">{{data[4]}}</a></span> {{data[0]}}</td> - <div class="pull-right"> - <span class="label label-danger">D</span>danger<span style="padding-left:20px"></span> - <span class="label label-primary">S</span><span>success</span><span style="padding-left:20px"></span> - <span class="label label-warning">W</span><span>warning</span> + </tr> + </tbody> + </table> + </div> + + <div class="pull-right" style="margin-top: 5px"> + <span class="label label-danger">G</span>gold<span style="padding-left:20px"></span> + <span class="label label-primary">P</span><span>platinium</span><span style="padding-left:20px"></span> + <span class="label label-warning">S</span><span>silver</span> </div> + </div> </div> </div> -</div> -</section> +</section>
\ No newline at end of file diff --git a/utils/test/reporting/pages/app/views/main.html b/utils/test/reporting/pages/app/views/main.html index 1e3fe9e5a..cca893713 100644 --- a/utils/test/reporting/pages/app/views/main.html +++ b/utils/test/reporting/pages/app/views/main.html @@ -1,186 +1,171 @@ - <div class="navbar-wrapper"> - <nav class="navbar navbar-default navbar-fixed-top" role="navigation"> - <div class="container"> - <div class="navbar-header page-scroll"> - <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" - aria-controls="navbar"> + <nav class="navbar navbar-default navbar-fixed-top" role="navigation"> + <div class="container"> + <div class="navbar-header page-scroll"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> - <a class="navbar-brand" href="index.html">OPNFV-DASHBOARD</a> - </div> - <div id="navbar" class="navbar-collapse collapse"> - <ul class="nav navbar-nav navbar-right"> - <li><a href="#page-top">Home</a></li> - <li><a href="#DashBoard">DashBoard</a></li> - <!--<li><a href="#team">Team</a></li> + <a class="navbar-brand" href="index.html">OPNFV-DASHBOARD</a> + </div> + <div class="navbar-collapse collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="#page-top">Home</a></li> + <li><a href="#DashBoard">DashBoard</a></li> + <li><a ui-sref="select.selectTestCase">TestCase</a></li> + <li><a ui-sref="login">Login</a></li> + <!--<li><a href="#team">Team</a></li> <li><a href="#testimonials">Testimonials</a></li> <li><a href="#pricing">Pricing</a></li> <li><a href="#contact">Contact</a></li>--> - </ul> - </div> - </div> - </nav> + </ul> + </div> + </div> + </nav> </div> <div id="inSlider" class="carousel carousel-fade" data-ride="carousel"> - <ol class="carousel-indicators"> - <!--<li data-target="#inSlider" data-slide-to="0" class="active"></li> + <ol class="carousel-indicators"> + <!--<li data-target="#inSlider" data-slide-to="0" class="active"></li> <li data-target="#inSlider" data-slide-to="1"></li>--> - </ol> - <div class="carousel-inner" role="listbox"> - <div class="item active"> - <div class="container"> - <div class="carousel-caption"> - <h1>OPNFV<br/> facilitates the development and evolution<br/> of NFV components across<br/> various open source ecosystems<br/> - </h1> - <!--<p>Lorem Ipsum is simply dummy text of the printing.</p> + </ol> + <div class="carousel-inner" role="listbox"> + <div class="item active"> + <div class="container"> + <div class="carousel-caption"> + <h1>OPNFV<br/> facilitates the development and evolution<br/> of NFV components across<br/> various open source ecosystems<br/> + </h1> + <!--<p>Lorem Ipsum is simply dummy text of the printing.</p> <p>--> - <a class="btn btn-lg btn-primary" href="#" role="button">READ MORE</a> - <!--<a class="caption-link" href="#" role="button">Inspinia Theme</a>--> - <!--</p>--> + <a class="btn btn-lg btn-primary" href="#" role="button">READ MORE</a> + <!--<a class="caption-link" href="#" role="button">Inspinia Theme</a>--> + <!--</p>--> + </div> + + </div> + <!-- Set background for slide in css --> + <div class="header-back one" style="background: url('images/header_one.jpg') 50% 0 no-repeat;"></div> + </div> - <!--<div class="carousel-image wow zoomIn"> - <img src="img/landing/laptop.png" alt="laptop"/> - </div>--> - </div> - <!-- Set background for slide in css --> - <div class="header-back one" style="background: url('images/header_one.jpg') 50% 0 no-repeat;"></div> </div> - <!--<div class="item"> - <div class="container"> - <div class="carousel-caption blank"> - <h1>We create meaningful <br/> interfaces that inspire.</h1> - <p>Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p> - <p><a class="btn btn-lg btn-primary" href="#" role="button">Learn more</a></p> - </div> - </div>--> - <!-- Set background for slide in css --> - <!--<div class="header-back two"></div> - </div>--> - </div> - <!--<a class="left carousel-control" href="#inSlider" role="button" data-slide="prev"> - <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span> - <span class="sr-only">Previous</span> - </a> - <a class="right carousel-control" href="#inSlider" role="button" data-slide="next"> - <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span> - <span class="sr-only">Next</span> - </a>--> + </div> - <section id="DashBoard" class="container services"> - <div class="row"> +<section id="DashBoard" class="container services"> + <div class="row"> - <h1> - OPNFV’s goals are to: - </h1> - <div class="col-sm-3"> + <h1> + OPNFV’s goals are to: + </h1> + <div class="col-sm-3"> - <p>Develop an integrated and tested open source platform that can be used to build NFV functionality--accelerating - the introduction of new products and services</p> - <p><a class="navy-link" href="#" role="button">Details »</a></p> - </div> - <div class="col-sm-3"> + <p>Develop an integrated and tested open source platform that can be used to build NFV functionality--accelerating the introduction of new products and services</p> + <p><a class="navy-link" href="#" role="button">Details »</a></p> + </div> + <div class="col-sm-3"> - <p>Include participation of leading end users to validate that OPNFV meets the needs of user community</p> - <p><a class="navy-link" href="#" role="button">Details »</a></p> - </div> - <div class="col-sm-3"> + <p>Include participation of leading end users to validate that OPNFV meets the needs of user community</p> + <p><a class="navy-link" href="#" role="button">Details »</a></p> + </div> + <div class="col-sm-3"> - <p>Contribute to and participate in relevant open source projects that will be leveraged in the OPNFV platform; - ensuring consistency, performance and interoperability among open source components</p> - <p><a class="navy-link" href="#" role="button">Details »</a></p> - </div> - <div class="col-sm-3"> + <p>Contribute to and participate in relevant open source projects that will be leveraged in the OPNFV platform; ensuring consistency, performance and interoperability among open source components</p> + <p><a class="navy-link" href="#" role="button">Details »</a></p> + </div> + <div class="col-sm-3"> - <p>Establish an ecosystem for NFV solutions based on open standards and software to meet the needs of end users</p> - <p><a class="navy-link" href="#" role="button">Details »</a></p> - </div> - <div class="col-sm-3"> + <p>Establish an ecosystem for NFV solutions based on open standards and software to meet the needs of end users</p> + <p><a class="navy-link" href="#" role="button">Details »</a></p> + </div> + <div class="col-sm-3"> - <p>Promote OPNFV as the preferred platform and community for open source NFV</p> - <p><a class="navy-link" href="#" role="button">Details »</a></p> - </div> + <p>Promote OPNFV as the preferred platform and community for open source NFV</p> + <p><a class="navy-link" href="#" role="button">Details »</a></p> </div> - </section> + </div> +</section> <div ui-view></div> <section id="contact" class="gray-section contact" style="background-image: url(images/word_map.png)"> - <div class="container"> - <div class="row m-b-lg"> - <div class="col-lg-12 text-center"> - <div class="navy-line"></div> - <h1>Contact Us</h1> - </div> - </div> - <div class="row m-b-lg"> - <div class="col-lg-3 col-lg-offset-3"> - <address> + <div class="container"> + <div class="row m-b-lg"> + <div class="col-lg-12 text-center"> + <div class="navy-line"></div> + <h1>Contact Us</h1> + </div> + </div> + <div class="row m-b-lg"> + <div class="col-lg-3 col-lg-offset-3"> + <address> <strong><span class="navy">Press, Analyst, or Speaking Inquiries</span></strong><br/> pr@opnfv.org <br/> </address> - <address> + <address> <strong><span class="navy">OPNFV Events</span></strong><br/> events@opnfv.org <br/> </address> - <address> + <address> <strong><span class="navy">IT Support</span></strong><br/>opnfv-helpdesk@rt.linuxfoundation.org <br/> </address> - </div> + </div> - <div class="col-lg-4"> - <address> + <div class="col-lg-4"> + <address> <strong><span class="navy">To submit and track bugs related to OPNFV</span></strong><br/>Please visit https://jira.opnfv.org <br/> </address> - <address> + <address> <strong><span class="navy">Newsletter</span></strong><br/>Sign up for the OPNFV newsletter <br/> </address> - <address> + <address> <strong><span class="navy">Membership</span></strong><br/>Please visit the Join as a Member page <br/> </address> - </div> - </div> - <div class="row"> - <div class="col-lg-12 text-center"> - <img src="images/logo.png" /> + </div> + </div> + <div class="row"> + <div class="col-lg-12 text-center"> + <img src="images/logo.png" /> - </div> - </div> - <div class="row"> - <div class="col-lg-8 col-lg-offset-2 text-center m-t-lg m-b-lg"> - <p><strong>© 2016 Open Platform for NFV Project, Inc</strong><br/> A Linux Foundation Collaborative Project. All - Rights Reserved. Open Platform for NFV and OPNFV are trademarks of the Open Platform for NFV Project, Inc. Linux - Foundation is a registered trademark of The Linux Foundation. Linux is a registered trademark of Linus Torvalds. - Please see our terms of use, trademark policy, and privacy policy. - </p> - </div> + </div> + </div> + <div class="row"> + <div class="col-lg-8 col-lg-offset-2 text-center m-t-lg m-b-lg"> + <p><strong>© 2016 Open Platform for NFV Project, Inc</strong><br/> A Linux Foundation Collaborative Project. All Rights Reserved. Open Platform for NFV and OPNFV are trademarks of the Open Platform for NFV Project, Inc. Linux Foundation + is a registered trademark of The Linux Foundation. Linux is a registered trademark of Linus Torvalds. Please see our terms of use, trademark policy, and privacy policy. + </p> + </div> + </div> </div> - </div> </section> <script> + $(document).ready(function() { - $(document).ready(function () { + // $('body').scrollspy({ + // target: '.navbar-fixed-top', + // offset: 80 + // }); - $('body').scrollspy({ - target: '.navbar-fixed-top', - offset: 80 + //Page scrolling feature + $('a.page-scroll').bind('click', function(event) { + var link = $(this); + $('html, body').stop().animate({ + scrollTop: $(link.attr('href')).offset().top - 50 + }, 500); + event.preventDefault(); + $("#navbar").collapse('hide'); }); - // Page scrolling feature $('a.page-scroll').bind('click', function(event) { var link = $(this); $('html, body').stop().animate({ @@ -190,63 +175,56 @@ $("#navbar").collapse('hide'); }); - - console.log( $("selectVersion").val()); - }); - // $(".select2_demo_1").select2(); - // $(".select2_demo_2").select2(); - // $(".select2_demo_3").select2({ - // placeholder: "Version", - // allowClear: true - // }); - // $(".select2_demo_4").select2({ - // placeholder: "Period", - // allowClear: true - // }); - - var config = { - '.chosen-select' : {}, - '.chosen-select-deselect' : {allow_single_deselect:true}, - '.chosen-select-no-single' : {disable_search_threshold:10}, - '.chosen-select-no-results': {no_results_text:'Oops, nothing found!'}, - '.chosen-select-width' : {width:"95%"} - } - for (var selector in config) { - $(selector).chosen(config[selector]); - } + '.chosen-select': {}, + '.chosen-select-deselect': { + allow_single_deselect: true + }, + '.chosen-select-no-single': { + disable_search_threshold: 10 + }, + '.chosen-select-no-results': { + no_results_text: 'Oops, nothing found!' + }, + '.chosen-select-width': { + width: "95%" + } + } + for (var selector in config) { + $(selector).chosen(config[selector]); + } var cbpAnimatedHeader = (function() { var docElem = document.documentElement, - header = document.querySelector( '.navbar-default' ), - didScroll = false, - changeHeaderOn = 200; + header = document.querySelector('.navbar-default'), + didScroll = false, + changeHeaderOn = 200; + function init() { - window.addEventListener( 'scroll', function( event ) { - if( !didScroll ) { + window.addEventListener('scroll', function(event) { + if (!didScroll) { didScroll = true; - setTimeout( scrollPage, 250 ); + setTimeout(scrollPage, 250); } - }, false ); + }, false); } + function scrollPage() { var sy = scrollY(); - if ( sy >= changeHeaderOn ) { + if (sy >= changeHeaderOn) { $(header).addClass('navbar-scroll') - } - else { + } else { $(header).removeClass('navbar-scroll') } didScroll = false; } + function scrollY() { return window.pageYOffset || docElem.scrollTop; } init(); })(); - - -</script> +</script>
\ No newline at end of file diff --git a/utils/test/reporting/pages/bower.json b/utils/test/reporting/pages/bower.json index dd0996d18..bfc4df3d9 100644 --- a/utils/test/reporting/pages/bower.json +++ b/utils/test/reporting/pages/bower.json @@ -1,32 +1,47 @@ { - "name": "opnfv", - "version": "0.0.0", - "dependencies": { - "angular": "^1.4.0", - "bootstrap": "^3.2.0", - "angular-animate": "^1.4.0", - "jquery-slimscroll": "slimscroll#^1.3.8", - "metisMenu": "~2.0.2", - "chosen": "^1.6.2", - "oclazyload": "^1.0.9", - "angular-bootstrap": "~1.1.2", - "angular-ui-router": "~0.2.15", - "angular-resource": "^1.6.0", - "angular-selectize2": "^3.0.1", - "components-font-awesome": "^4.7.0" - }, - "devDependencies": { - "angular-mocks": "^1.4.0" - }, - "appPath": "app", - "moduleName": "opnfvApp", - "overrides": { - "bootstrap": { - "main": [ - "less/bootstrap.less", - "dist/css/bootstrap.css", - "dist/js/bootstrap.js" - ] + "name": "opnfv", + "version": "0.0.0", + "dependencies": { + "angular": "^1.4.0", + "bootstrap": "^3.2.0", + "angular-animate": "^1.4.0", + "jquery-slimscroll": "slimscroll#^1.3.8", + "metisMenu": "~2.0.2", + "chosen": "^1.6.2", + "oclazyload": "^1.0.9", + "angular-bootstrap": "~1.1.2", + "angular-ui-router": "~0.2.15", + "angular-resource": "^1.6.0", + "angular-selectize2": "^3.0.1", + "components-font-awesome": "^4.7.0", + "angular-tooltips": "^1.1.8", + "jQuery-rwdImageMaps": "*", + "animate.css": "^3.5.2", + "ng-dialog": "^1.0.0", + "inspiniacss": "^0.0.1" + }, + "devDependencies": { + "angular-mocks": "^1.4.0" + }, + "appPath": "app", + "moduleName": "opnfvApp", + "overrides": { + "bootstrap": { + "main": [ + "less/bootstrap.less", + "dist/css/bootstrap.css", + "dist/js/bootstrap.js" + ] + }, + "jQuery-rwdImageMaps": { + "main": [ + "jquery.rwdImageMaps.min.js" + ] + }, + "inspiniacss": { + "main": [ + "style.css" + ] + } } - } -} +}
\ No newline at end of file diff --git a/utils/test/reporting/pages/test/karma.conf.js b/utils/test/reporting/pages/test/karma.conf.js index 2b0f41cd3..5c2e79b9f 100644 --- a/utils/test/reporting/pages/test/karma.conf.js +++ b/utils/test/reporting/pages/test/karma.conf.js @@ -36,6 +36,7 @@ module.exports = function(config) { 'bower_components/microplugin/src/microplugin.js', 'bower_components/selectize/dist/js/selectize.js', 'bower_components/angular-selectize2/dist/angular-selectize.js', + 'bower_components/angular-tooltips/dist/angular-tooltips.min.js', 'bower_components/angular-mocks/angular-mocks.js', // endbower 'app/scripts/**/*.js', diff --git a/utils/test/reporting/storperf/reporting-status.py b/utils/test/reporting/storperf/reporting-status.py index 674fdd880..888e339f8 100644 --- a/utils/test/reporting/storperf/reporting-status.py +++ b/utils/test/reporting/storperf/reporting-status.py @@ -63,15 +63,23 @@ for version in versions: logger.info("ten_score: %s / %s" % (ten_score, ten_criteria)) - LASTEST_TESTS = rp_utils.get_config( - 'general.nb_iteration_tests_success_criteria') - four_result = s_result[:LASTEST_TESTS] - four_criteria = len(four_result) four_score = 0 - for v in four_result: - if "PASS" in v['criteria']: - four_score += 1 - logger.info("four_score: %s / %s " % (four_score, four_criteria)) + try: + LASTEST_TESTS = rp_utils.get_config( + 'general.nb_iteration_tests_success_criteria') + s_result.sort(key=lambda x: x['start_date']) + four_result = s_result[-LASTEST_TESTS:] + logger.debug("four_result: {}".format(four_result)) + logger.debug("LASTEST_TESTS: {}".format(LASTEST_TESTS)) + # logger.debug("four_result: {}".format(four_result)) + four_criteria = len(four_result) + for v in four_result: + if "PASS" in v['criteria']: + four_score += 1 + logger.info("4 Score: %s / %s " % (four_score, + four_criteria)) + except: + logger.error("Impossible to retrieve the four_score") try: s_status = (four_score * 100) / four_criteria @@ -82,12 +90,20 @@ for version in versions: s_ten_score = str(ten_score) + '/' + str(ten_criteria) s_score_percent = str(s_status) - if '100' == s_status: + logger.debug(" s_status: {}".format(s_status)) + if s_status == 100: logger.info(">>>>> scenario OK, save the information") else: logger.info(">>>> scenario not OK, last 4 iterations = %s, \ last 10 days = %s" % (s_four_score, s_ten_score)) + s_url = "" + if len(s_result) > 0: + build_tag = s_result[len(s_result)-1]['build_tag'] + logger.debug("Build tag: %s" % build_tag) + s_url = s_url = rp_utils.getJenkinsUrl(build_tag) + logger.info("last jenkins url: %s" % s_url) + # Save daily results in a file path_validation_file = ("./display/" + version + "/storperf/scenario_history.txt") @@ -106,7 +122,8 @@ for version in versions: scenario_result_criteria[s] = sr.ScenarioResult(s_status, s_four_score, s_ten_score, - s_score_percent) + s_score_percent, + s_url) logger.info("--------------------------") diff --git a/utils/test/reporting/storperf/template/index-status-tmpl.html b/utils/test/reporting/storperf/template/index-status-tmpl.html index e3a18b1ce..e0fcc6828 100644 --- a/utils/test/reporting/storperf/template/index-status-tmpl.html +++ b/utils/test/reporting/storperf/template/index-status-tmpl.html @@ -25,7 +25,7 @@ } // trend line management - d3.csv("./scenario_history.csv", function(data) { + d3.csv("./scenario_history.txt", function(data) { // *************************************** // Create the trend line {% for scenario in scenario_results.keys() -%} @@ -95,7 +95,7 @@ </tr> {% for scenario,result in scenario_results.iteritems() -%} <tr class="tr-ok"> - <td>{{scenario}}</td> + <td><a href="{{scenario_results[scenario].getLastUrl()}}">{{scenario}}</a></td> <td><div id="gaugeScenario{{loop.index}}"></div></td> <td><div id="trend_svg{{loop.index}}"></div></td> <td>{{scenario_results[scenario].getFourDaysScore()}}</td> diff --git a/utils/test/reporting/utils/scenarioResult.py b/utils/test/reporting/utils/scenarioResult.py index 1f7eb2b24..6029d7f42 100644 --- a/utils/test/reporting/utils/scenarioResult.py +++ b/utils/test/reporting/utils/scenarioResult.py @@ -10,11 +10,12 @@ class ScenarioResult(object): def __init__(self, status, four_days_score='', ten_days_score='', - score_percent=0.0): + score_percent=0.0, last_url=''): self.status = status self.four_days_score = four_days_score self.ten_days_score = ten_days_score self.score_percent = score_percent + self.last_url = last_url def getStatus(self): return self.status @@ -27,3 +28,6 @@ class ScenarioResult(object): def getScorePercent(self): return self.score_percent + + def getLastUrl(self): + return self.last_url diff --git a/utils/test/testapi/opnfv_testapi/resources/models.py b/utils/test/testapi/opnfv_testapi/resources/models.py index f518c97a0..0ea482fd2 100644 --- a/utils/test/testapi/opnfv_testapi/resources/models.py +++ b/utils/test/testapi/opnfv_testapi/resources/models.py @@ -1,98 +1,116 @@ -##############################################################################
-# Copyright (c) 2015 Orange
-# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com
-# 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
-# feng.xiaowei@zte.com.cn mv Pod to pod_models.py 5-18-2016
-# feng.xiaowei@zte.com.cn add MetaCreateResponse/MetaGetResponse 5-18-2016
-# feng.xiaowei@zte.com.cn mv TestProject to project_models.py 5-19-2016
-# feng.xiaowei@zte.com.cn delete meta class 5-19-2016
-# feng.xiaowei@zte.com.cn add CreateResponse 5-19-2016
-# feng.xiaowei@zte.com.cn mv TestCase to testcase_models.py 5-20-2016
-# feng.xiaowei@zte.com.cn mv TestResut to result_models.py 5-23-2016
-# feng.xiaowei@zte.com.cn add ModelBase 12-20-2016
-##############################################################################
-import copy
-
-from opnfv_testapi.tornado_swagger import swagger
-
-
-class ModelBase(object):
-
- def _format(self, excludes):
- new_obj = copy.deepcopy(self)
- dicts = new_obj.__dict__
- for k in dicts.keys():
- if k in excludes:
- del dicts[k]
- elif dicts[k]:
- if hasattr(dicts[k], 'format'):
- dicts[k] = dicts[k].format()
- elif isinstance(dicts[k], list):
- hs = list()
- [hs.append(h.format() if hasattr(h, 'format') else str(h))
- for h in dicts[k]]
- dicts[k] = hs
- elif not isinstance(dicts[k], (str, int, float, dict)):
- dicts[k] = str(dicts[k])
- return dicts
-
- def format(self):
- return self._format(['_id'])
-
- def format_http(self):
- return self._format([])
-
- @staticmethod
- def attr_parser():
- return {}
-
- @classmethod
- def from_dict(cls, a_dict):
- if a_dict is None:
- return None
-
- attr_parser = cls.attr_parser()
- t = cls()
- for k, v in a_dict.iteritems():
- value = v
- if isinstance(v, dict) and k in attr_parser:
- value = attr_parser[k].from_dict(v)
- elif isinstance(v, list) and k in attr_parser:
- value = []
- for item in v:
- value.append(attr_parser[k].from_dict(item))
-
- t.__setattr__(k, value)
-
- return t
-
-
-@swagger.model()
-class CreateResponse(ModelBase):
- def __init__(self, href=''):
- self.href = href
-
-
-@swagger.model()
-class Versions(ModelBase):
- """
- @property versions:
- @ptype versions: C{list} of L{Version}
- """
-
- def __init__(self):
- self.versions = list()
-
- @staticmethod
- def attr_parser():
- return {'versions': Version}
-
-
-@swagger.model()
-class Version(ModelBase):
- def __init__(self, version=None, description=None):
- self.version = version
- self.description = description
+############################################################################## +# Copyright (c) 2015 Orange +# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com +# 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 +# feng.xiaowei@zte.com.cn mv Pod to pod_models.py 5-18-2016 +# feng.xiaowei@zte.com.cn add MetaCreateResponse/MetaGetResponse 5-18-2016 +# feng.xiaowei@zte.com.cn mv TestProject to project_models.py 5-19-2016 +# feng.xiaowei@zte.com.cn delete meta class 5-19-2016 +# feng.xiaowei@zte.com.cn add CreateResponse 5-19-2016 +# feng.xiaowei@zte.com.cn mv TestCase to testcase_models.py 5-20-2016 +# feng.xiaowei@zte.com.cn mv TestResut to result_models.py 5-23-2016 +# feng.xiaowei@zte.com.cn add ModelBase 12-20-2016 +############################################################################## +import copy +import ast + + +from opnfv_testapi.tornado_swagger import swagger + + +class ModelBase(object): + + def format(self): + return self._format(['_id']) + + def format_http(self): + return self._format([]) + + @classmethod + def from_dict(cls, a_dict): + if a_dict is None: + return None + + attr_parser = cls.attr_parser() + t = cls() + for k, v in a_dict.iteritems(): + value = v + if isinstance(v, dict) and k in attr_parser: + value = attr_parser[k].from_dict(v) + elif isinstance(v, list) and k in attr_parser: + value = [] + for item in v: + value.append(attr_parser[k].from_dict(item)) + + t.__setattr__(k, value) + + return t + + @staticmethod + def attr_parser(): + return {} + + def _format(self, excludes): + new_obj = copy.deepcopy(self) + dicts = new_obj.__dict__ + for k in dicts.keys(): + if k in excludes: + del dicts[k] + elif dicts[k]: + dicts[k] = self._obj_format(dicts[k]) + return dicts + + def _obj_format(self, obj): + if self._has_format(obj): + obj = obj.format() + elif isinstance(obj, unicode): + try: + obj = self._obj_format(ast.literal_eval(obj)) + except: + try: + obj = str(obj) + except: + obj = obj + elif isinstance(obj, list): + hs = list() + for h in obj: + hs.append(self._obj_format(h)) + obj = hs + elif not isinstance(obj, (str, int, float, dict)): + obj = str(obj) + return obj + + @staticmethod + def _has_format(obj): + return not isinstance(obj, (str, unicode)) and hasattr(obj, 'format') + + +@swagger.model() +class CreateResponse(ModelBase): + def __init__(self, href=''): + self.href = href + + +@swagger.model() +class Versions(ModelBase): + """ + @property versions: + @ptype versions: C{list} of L{Version} + """ + + def __init__(self): + self.versions = list() + + @staticmethod + def attr_parser(): + return {'versions': Version} + + +@swagger.model() +class Version(ModelBase): + def __init__(self, version=None, description=None): + self.version = version + self.description = description diff --git a/utils/test/testapi/opnfv_testapi/resources/scenario_models.py b/utils/test/testapi/opnfv_testapi/resources/scenario_models.py index 73bcbe99e..b84accf4d 100644 --- a/utils/test/testapi/opnfv_testapi/resources/scenario_models.py +++ b/utils/test/testapi/opnfv_testapi/resources/scenario_models.py @@ -49,6 +49,24 @@ class ScenarioProject(models.ModelBase): return {'scores': ScenarioScore, 'trust_indicators': ScenarioTI} + def __eq__(self, other): + return [self.project == other.project and + self._customs_eq(other) and + self._scores_eq(other) and + self._ti_eq(other)] + + def __ne__(self, other): + return not self.__eq__(other) + + def _customs_eq(self, other): + return set(self.customs) == set(other.customs) + + def _scores_eq(self, other): + return set(self.scores) == set(other.scores) + + def _ti_eq(self, other): + return set(self.trust_indicators) == set(other.trust_indicators) + @swagger.model() class ScenarioVersion(models.ModelBase): @@ -64,6 +82,21 @@ class ScenarioVersion(models.ModelBase): def attr_parser(): return {'projects': ScenarioProject} + def __eq__(self, other): + return [self.version == other.version and self._projects_eq(other)] + + def __ne__(self, other): + return not self.__eq__(other) + + def _projects_eq(self, other): + for s_project in self.projects: + for o_project in other.projects: + if s_project.project == o_project.project: + if s_project != o_project: + return False + + return True + @swagger.model() class ScenarioInstaller(models.ModelBase): @@ -79,6 +112,21 @@ class ScenarioInstaller(models.ModelBase): def attr_parser(): return {'versions': ScenarioVersion} + def __eq__(self, other): + return [self.installer == other.installer and self._versions_eq(other)] + + def __ne__(self, other): + return not self.__eq__(other) + + def _versions_eq(self, other): + for s_version in self.versions: + for o_version in other.versions: + if s_version.version == o_version.version: + if s_version != o_version: + return False + + return True + @swagger.model() class ScenarioCreateRequest(models.ModelBase): @@ -126,6 +174,21 @@ class Scenario(models.ModelBase): def attr_parser(): return {'installers': ScenarioInstaller} + def __ne__(self, other): + return not self.__eq__(other) + + def __eq__(self, other): + return [self.name == other.name and self._installers_eq(other)] + + def _installers_eq(self, other): + for s_install in self.installers: + for o_install in other.installers: + if s_install.installer == o_install.installer: + if s_install != o_install: + return False + + return True + @swagger.model() class Scenarios(models.ModelBase): diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/test_scenario.py b/utils/test/testapi/opnfv_testapi/tests/unit/test_scenario.py index f604c5750..7a6e94a93 100644 --- a/utils/test/testapi/opnfv_testapi/tests/unit/test_scenario.py +++ b/utils/test/testapi/opnfv_testapi/tests/unit/test_scenario.py @@ -39,10 +39,10 @@ class TestScenarioBase(base.TestBase): self.assertEqual(code, constants.HTTP_OK) if req is None: req = self.req_d - scenario_dict = scenario.format_http() - self.assertIsNotNone(scenario_dict['_id']) - self.assertIsNotNone(scenario_dict['creation_date']) - self.assertDictContainsSubset(req, scenario_dict) + self.assertIsNotNone(scenario._id) + self.assertIsNotNone(scenario.creation_date) + + scenario == models.Scenario.from_dict(req) @staticmethod def _set_query(*args): |