Merge "Enable jobs for stable/euphrates branch"
authorSerena Feng <feng.xiaowei@zte.com.cn>
Mon, 18 Sep 2017 07:32:39 +0000 (07:32 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Mon, 18 Sep 2017 07:32:39 +0000 (07:32 +0000)
28 files changed:
jjb/apex/apex-deploy.sh
jjb/apex/apex-snapshot-deploy.sh
jjb/apex/apex.yml
jjb/apex/apex.yml.j2
jjb/bottlenecks/bottlenecks-ci-jobs.yml
jjb/bottlenecks/bottlenecks-project-jobs.yml
jjb/bottlenecks/bottlenecks-run-suite.sh
jjb/compass4nfv/compass-ci-jobs.yml
jjb/daisy4nfv/daisy4nfv-verify-jobs.yml
jjb/fuel/fuel-daily-jobs.yml
jjb/functest/functest-alpine.sh
jjb/functest/functest-daily-jobs.yml
jjb/releng/opnfv-docker-arm.yml
jjb/releng/opnfv-docker.sh
jjb/xci/bifrost-verify-jobs.yml
jjb/yardstick/yardstick-cleanup.sh
utils/test/testapi/3rd_party/static/testapi-ui/components/pods/pods.html
utils/test/testapi/opnfv_testapi/common/check.py
utils/test/testapi/opnfv_testapi/common/message.py
utils/test/testapi/opnfv_testapi/resources/handlers.py
utils/test/testapi/opnfv_testapi/resources/pod_models.py
utils/test/testapi/opnfv_testapi/tests/unit/common/test_config.py
utils/test/testapi/opnfv_testapi/tests/unit/executor.py
utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py
utils/test/testapi/opnfv_testapi/tests/unit/resources/test_base.py
utils/test/testapi/opnfv_testapi/tests/unit/resources/test_pod.py
utils/test/testapi/opnfv_testapi/tests/unit/resources/test_result.py
utils/test/testapi/opnfv_testapi/tests/unit/resources/test_token.py

index bfed67e..a79c9e7 100755 (executable)
@@ -38,7 +38,7 @@ if [[ "$ARTIFACT_VERSION" =~ dev ]]; then
   DEPLOY_SETTINGS_DIR="${WORKSPACE}/config/deploy"
   NETWORK_SETTINGS_DIR="${WORKSPACE}/config/network"
   DEPLOY_CMD="opnfv-deploy --image-dir ${WORKSPACE}/.build"
-  CLEAN_CMD="${WORKSPACE}/ci/clean.sh"
+  CLEAN_CMD="opnfv-clean"
   RESOURCES="${WORKSPACE}/.build/"
   CONFIG="${WORKSPACE}/build"
   BASE=$CONFIG
index 3eb3cf2..a93421c 100644 (file)
@@ -22,7 +22,7 @@ echo
 
 echo "Cleaning server"
 pushd ci > /dev/null
-sudo BASE=../build/ LIB=../lib ./clean.sh
+sudo opnfv-clean
 popd > /dev/null
 
 echo "Downloading latest snapshot properties file"
index c71bee1..baad8d3 100644 (file)
@@ -16,6 +16,7 @@
         - 'apex-upload-snapshot'
         - 'apex-create-snapshot'
         - 'apex-flex-daily-os-nosdn-nofeature-ha-{stream}'
+        - 'apex-dovetail-daily-os-nosdn-nofeature-ha-baremetal-danube'
     # stream:    branch with - in place of / (eg. stable-arno)
     # branch:    branch (eg. stable/arno)
     stream:
                   abort-all-job: false
                   git-revision: false
 
+# Dovetail Danube test job
+- job-template:
+    name: 'apex-dovetail-daily-os-nosdn-nofeature-ha-baremetal-danube'
+
+    project-type: 'multijob'
+
+    node: 'huawei-pod4'
+
+    disabled: false
+
+    parameters:
+        - '{project}-defaults'
+        - project-parameter:
+            project: '{project}'
+            branch: 'stable/danube'
+        - apex-parameter:
+            gs-pathname: '/danube'
+        - string:
+            name: DEPLOY_SCENARIO
+            default: 'os-nosdn-nofeature-ha'
+            description: "Scenario to deploy with."
+
+    properties:
+        - logrotate-default
+        - build-blocker:
+            use-build-blocker: true
+            block-level: 'NODE'
+            blocking-jobs:
+                - 'apex-verify.*'
+                - 'apex-runner.*'
+                - 'apex-.*-promote.*'
+                - 'apex-run.*'
+
+    triggers:
+        - timed: '0 12 * * *'
+
+    builders:
+        - description-setter:
+            description: "Testing on $NODE_NAME - Scenario: $DEPLOY_SCENARIO"
+        - multijob:
+            name: 'Baremetal Deploy'
+            condition: SUCCESSFUL
+            projects:
+                - name: 'apex-deploy-baremetal-danube'
+                  node-parameters: true
+                  current-parameters: true
+                  predefined-parameters: |
+                    OPNFV_CLEAN=yes
+                    GERRIT_BRANCH=$GERRIT_BRANCH
+                    GERRIT_REFSPEC=
+                    DEPLOY_SCENARIO=$DEPLOY_SCENARIO
+                  kill-phase-on: FAILURE
+                  abort-all-job: true
+                  git-revision: false
+        - multijob:
+            name: Dovetail
+            condition: ALWAYS
+            projects:
+                - name: 'dovetail-apex-baremetal-proposed_tests-danube'
+                  node-parameters: true
+                  current-parameters: false
+                  predefined-parameters:
+                    DEPLOY_SCENARIO=$DEPLOY_SCENARIO
+                  kill-phase-on: NEVER
+                  abort-all-job: false
+                  git-revision: false
+
 ########################
 # parameter macros
 ########################
index 356c718..df8cf92 100644 (file)
@@ -16,6 +16,7 @@
         - 'apex-upload-snapshot'
         - 'apex-create-snapshot'
         - 'apex-flex-daily-os-nosdn-nofeature-ha-{stream}'
+        - 'apex-dovetail-daily-os-nosdn-nofeature-ha-baremetal-danube'
     # stream:    branch with - in place of / (eg. stable-arno)
     # branch:    branch (eg. stable/arno)
     stream:
                   abort-all-job: false
                   git-revision: false
 
+# Dovetail Danube test job
+- job-template:
+    name: 'apex-dovetail-daily-os-nosdn-nofeature-ha-baremetal-danube'
+
+    project-type: 'multijob'
+
+    node: 'huawei-pod4'
+
+    disabled: false
+
+    parameters:
+        - '{project}-defaults'
+        - project-parameter:
+            project: '{project}'
+            branch: 'stable/danube'
+        - apex-parameter:
+            gs-pathname: '/danube'
+        - string:
+            name: DEPLOY_SCENARIO
+            default: 'os-nosdn-nofeature-ha'
+            description: "Scenario to deploy with."
+
+    properties:
+        - logrotate-default
+        - build-blocker:
+            use-build-blocker: true
+            block-level: 'NODE'
+            blocking-jobs:
+                - 'apex-verify.*'
+                - 'apex-runner.*'
+                - 'apex-.*-promote.*'
+                - 'apex-run.*'
+
+    triggers:
+        - timed: '0 12 * * *'
+
+    builders:
+        - description-setter:
+            description: "Testing on $NODE_NAME - Scenario: $DEPLOY_SCENARIO"
+        - multijob:
+            name: 'Baremetal Deploy'
+            condition: SUCCESSFUL
+            projects:
+                - name: 'apex-deploy-baremetal-danube'
+                  node-parameters: true
+                  current-parameters: true
+                  predefined-parameters: |
+                    OPNFV_CLEAN=yes
+                    GERRIT_BRANCH=$GERRIT_BRANCH
+                    GERRIT_REFSPEC=
+                    DEPLOY_SCENARIO=$DEPLOY_SCENARIO
+                  kill-phase-on: FAILURE
+                  abort-all-job: true
+                  git-revision: false
+        - multijob:
+            name: Dovetail
+            condition: ALWAYS
+            projects:
+                - name: 'dovetail-apex-baremetal-proposed_tests-danube'
+                  node-parameters: true
+                  current-parameters: false
+                  predefined-parameters:
+                    DEPLOY_SCENARIO=$DEPLOY_SCENARIO
+                  kill-phase-on: NEVER
+                  abort-all-job: false
+                  git-revision: false
+
 ########################
 # parameter macros
 ########################
index a8654d0..bb2a13c 100644 (file)
@@ -89,6 +89,7 @@
       - timeout:
           timeout: 180
           abort: true
+      - fix-workspace-permissions
 
     triggers:
       - '{auto-trigger-name}'
     builders:
       - 'bottlenecks-env-cleanup'
       - 'bottlenecks-run-suite'
+      - 'bottlenecks-workspace-cleanup'
 
     publishers:
       - email:
       - shell:
           !include-raw: ./bottlenecks-run-suite.sh
 
+- builder:
+    name: bottlenecks-workspace-cleanup
+    builders:
+        - shell: |
+            #!/bin/bash
+            set -o errexit
+            set -o nounset
+            set -o pipefail
+
+            # delete everything that is in $WORKSPACE
+            sudo rm -rf $WORKSPACE
+
 ####################
 # parameter macros
 ####################
index c7c9b42..10f73b8 100644 (file)
@@ -28,8 +28,6 @@
           disabled: false
 
     suite:
-      - 'rubbos'
-      - 'vstf'
       - 'posca_stress_traffic'
       - 'posca_stress_ping'
 
 
     builders:
       - 'bottlenecks-builder-upload-artifact'
-      - 'bottlenecks-workspace-cleanup'
+      - 'bottlenecks-artifact-workspace-cleanup'
 
 ####################
 # parameter macros
           done
 
 - builder:
-    name: bottlenecks-workspace-cleanup
+    name: bottlenecks-artifact-workspace-cleanup
     builders:
       - shell: |
           #!/bin/bash
index 6d4d2d8..811f9d5 100644 (file)
@@ -104,6 +104,9 @@ if [[ $SUITE_NAME == *posca* ]]; then
 
     deactivate
 
+    sudo rm -rf ${RELENG_REPO}/modules/venv
+    sudo rm -rf ${RELENG_REPO}/modules/opnfv.egg-info
+
     set -e
 
     cd ${WORKSPACE}
index 8b4a74b..aaa5b57 100644 (file)
         # here the stream means the SUT stream, dovetail stream is defined in its own job
         # only run on os-(nosdn|odl_l2|onos|odl_l3)-nofeature-ha scenario
         # run against SUT master branch, dovetail docker image with latest tag
-        # run against SUT danube branch, dovetail docker image with latest tag(odd days)and cvp.X.X.X tag(even days)
+        # run against SUT danube branch, dovetail docker image with latest tag(Monday and Sunday)
+        # run against SUT danube branch, dovetail docker image with cvp.X.X.X tag(Tuesday, Thursday, Friday and Saturday)
         - conditional-step:
             condition-kind: and
             condition-operands:
                   regex: danube
                   label: '{stream}'
                 - condition-kind: regex-match
-                  regex: os-(nosdn|odl_l2|onos|odl_l3)-nofeature-ha
+                  regex: os-(nosdn|odl_l2|odl_l3)-nofeature-ha
                   label: '{scenario}'
                 - condition-kind: day-of-week
                   day-selector: select-days
                   days:
                       MON: true
-                      WED: true
-                      FRI: true
                       SUN: true
                   use-build-time: true
             steps:
                   regex: danube
                   label: '{stream}'
                 - condition-kind: regex-match
-                  regex: os-(nosdn|odl_l2|onos|odl_l3)-nofeature-ha
+                  regex: os-(nosdn|odl_l2|odl_l3)-nofeature-ha
                   label: '{scenario}'
                 - condition-kind: day-of-week
                   day-selector: select-days
                   days:
                       TUES: true
+                      WED: true
                       THURS: true
+                      FRI: true
                       SAT: true
                   use-build-time: true
             steps:
             condition-kind: and
             condition-operands:
                 - condition-kind: regex-match
-                  regex: os-(nosdn|odl_l2|onos|odl_l3)-nofeature-ha
+                  regex: os-(nosdn|odl_l2|odl_l3)-nofeature-ha
                   label: '{scenario}'
                 - condition-kind: regex-match
                   regex: master
 - trigger:
     name: 'compass-k8-nosdn-nofeature-ha-virtual-master-trigger'
     triggers:
-        - timed: ''
+        - timed: '0 12 * * *'
 - trigger:
     name: 'compass-os-odl-sfc-ha-virtual-master-trigger'
     triggers:
index c8563c1..2cf68a9 100644 (file)
@@ -86,6 +86,8 @@
                         pattern: 'code/**'
                       - compare-type: ANT
                         pattern: 'deploy/**'
+                      - compare-type: ANT
+                        pattern: 'tests/**'
                   disable-strict-forbidden-file-verification: 'true'
                   forbidden-file-paths:
                       - compare-type: ANT
index deadefb..4bdfa5b 100644 (file)
             auto-trigger-name: 'fuel-{scenario}-{pod}-daily-{stream}-trigger'
         - 'os-nosdn-kvm_ovs_dpdk_bar-noha':
             auto-trigger-name: 'fuel-{scenario}-{pod}-daily-{stream}-trigger'
+        # danube scenario for Dovetail only
+        - 'os-odl_l2-bgpvpn-ha':
+            auto-trigger-name: 'fuel-{scenario}-{pod}-daily-{stream}-trigger'
+
+    exclude:
+        - scenario: os-odl_l2-bgpvpn-ha
+          stream: master
+        - scenario: os-odl_l2-bgpvpn-ha
+          stream: euphrates
 
     jobs:
         - 'fuel-{scenario}-{pod}-daily-{stream}'
         # 6.ZTE pod1, os-nosdn-nofeature-ha and os-odl-bgpvpn-ha, run against danube
         - conditional-step:
             condition-kind: regex-match
-            regex: os-(nosdn-nofeature|odl-bgpvpn)-ha
+            regex: os-(nosdn-nofeature|odl_l2-bgpvpn)-ha
             label: '{scenario}'
             steps:
                 - trigger-builds:
 - trigger:
     name: 'fuel-os-nosdn-nofeature-ha-zte-pod3-daily-master-trigger'
     triggers:
-        - timed: '0 10 * * *'
+        - timed: ''    # '0 10 * * *'
 - trigger:
     name: 'fuel-os-odl-nofeature-ha-zte-pod3-daily-master-trigger'
     triggers:
     name: 'fuel-os-nosdn-nofeature-ha-zte-pod1-daily-danube-trigger'
     triggers:
         - timed: '0 2 * * 6'
+- trigger:
+    name: 'fuel-os-odl_l2-bgpvpn-ha-zte-pod1-daily-danube-trigger'
+    triggers:
+        - timed: '0 2 * * 1,3,5'
 - trigger:
     name: 'fuel-os-odl-nofeature-ha-zte-pod1-daily-danube-trigger'
     triggers:
index 34c746e..35311c3 100755 (executable)
@@ -6,16 +6,20 @@ set +o pipefail
 
 [[ $CI_DEBUG == true ]] && redirect="/dev/stdout" || redirect="/dev/null"
 FUNCTEST_DIR=/home/opnfv/functest
+DEPLOY_TYPE=baremetal
+[[ $BUILD_TAG =~ "virtual" ]] && DEPLOY_TYPE=virt
+HOST_ARCH=$(uname -m)
 
 # Prepare OpenStack credentials volume
+rc_file=${HOME}/opnfv-openrc.sh
+
 if [[ ${INSTALLER_TYPE} == 'joid' ]]; then
     rc_file=$LAB_CONFIG/admin-openrc
 elif [[ ${INSTALLER_TYPE} == 'compass' && ${BRANCH} == 'master' ]]; then
     cacert_file_vol="-v ${HOME}/os_cacert:${FUNCTEST_DIR}/conf/os_cacert"
     echo "export OS_CACERT=${FUNCTEST_DIR}/conf/os_cacert" >> ${HOME}/opnfv-openrc.sh
-    rc_file=${HOME}/opnfv-openrc.sh
-else
-    rc_file=${HOME}/opnfv-openrc.sh
+elif [[ ${INSTALLER_TYPE} == 'fuel' && ${DEPLOY_TYPE} == 'baremetal' ]]; then
+    cacert_file_vol="-v ${HOME}/os_cacert:/etc/ssl/certs/mcp_os_cacert"
 fi
 rc_file_vol="-v ${rc_file}:${FUNCTEST_DIR}/conf/openstack.creds"
 
@@ -25,10 +29,6 @@ if ! sudo iptables -C FORWARD -j RETURN 2> ${redirect} || ! sudo iptables -L FOR
     sudo iptables -I FORWARD -j RETURN
 fi
 
-DEPLOY_TYPE=baremetal
-[[ $BUILD_TAG =~ "virtual" ]] && DEPLOY_TYPE=virt
-HOST_ARCH=$(uname -m)
-
 echo "Functest: Start Docker and prepare environment"
 
 echo "Functest: Download images that will be used by test cases"
@@ -71,7 +71,11 @@ set +e
 if [ ${FUNCTEST_SUITE_NAME} == 'healthcheck' ]; then
     tiers=(healthcheck)
 else
-    tiers=(healthcheck smoke features vnf)
+    if [ ${DEPLOY_TYPE} == 'baremetal' ]; then
+        tiers=(healthcheck smoke features vnf)
+    else
+        tiers=(healthcheck smoke features)
+    fi
 fi
 
 cmd_opt='prepare_env start && run_tests -r -t all'
@@ -80,7 +84,7 @@ for tier in ${tiers[@]}; do
     FUNCTEST_IMAGE=opnfv/functest-${tier}
     echo "Functest: Pulling Functest Docker image ${FUNCTEST_IMAGE} ..."
     docker pull ${FUNCTEST_IMAGE}>/dev/null
-    cmd="docker run ${envs} ${volumes} ${FUNCTEST_IMAGE} /bin/bash -c '${cmd_opt}'"
+    cmd="docker run --privileged=true ${envs} ${volumes} ${FUNCTEST_IMAGE} /bin/bash -c '${cmd_opt}'"
     echo "Running Functest tier '${tier}'. CMD: ${cmd}"
     eval ${cmd}
 done
index cbf1755..23c6e49 100644 (file)
     name: functest-daily-builder
     builders:
         - 'functest-cleanup'
-        - 'set-functest-env-alpine'
         - 'functest-daily'
         - 'functest-store-results'
 
     name: functest-daily
     builders:
         - shell:
-            !include-raw: ./functest-alpine.sh
+            !include-raw:
+                - ./functest-env-presetup.sh
+                - ../../utils/fetch_os_creds.sh
+                - ./functest-alpine.sh
 
 - builder:
     name: functest-arm-daily
index ec1d743..21d5698 100644 (file)
@@ -39,6 +39,7 @@
 
     dockerfile: "Dockerfile.aarch64"
     dockerdir: "docker"
+    docker_repo_name: "opnfv/{project}_aarch64"
     arch_tag: ""
 
     dockerrepo:
             description: "To enable/disable pushing the image to Dockerhub."
         - string:
             name: DOCKER_REPO_NAME
-            default: "opnfv/{project}_aarch64"
+            default: "{docker_repo_name}"
             description: "Dockerhub repo to be pushed to."
         - string:
             name: RELEASE_VERSION
             description: "Release version, e.g. 1.0, 2.0, 3.0"
         - string:
             name: DOCKER_DIR
-            default: "docker"
+            default: "{dockerdir}"
             description: "Directory containing files needed by the Dockerfile"
         - string:
             name: DOCKERFILE
index 6ca8e37..b03505e 100644 (file)
@@ -90,6 +90,7 @@ if [[ -n "${COMMIT_ID-}" && -n "${RELEASE_VERSION-}" ]]; then
 fi
 
 ARCH_BUILD_ARG=""
+ARCH_TAG=${ARCH_TAG:-}
 if [[ -n "${ARCH_TAG}" ]]; then
     DOCKER_TAG=${ARCH_TAG}-${DOCKER_TAG}
     ARCH_BUILD_ARG="--build-arg ARCH=${ARCH_TAG}"
index d6eb5ff..f910683 100644 (file)
 #--------------------------------
     distro:
         - 'xenial':
-            disabled: false
+            disabled: true
             dib-os-release: 'xenial'
             dib-os-element: 'ubuntu-minimal'
             dib-os-packages: 'vlan,vim,less,bridge-utils,language-pack-en,iputils-ping,rsyslog,curl'
             extra-dib-elements: 'openssh-server'
         - 'centos7':
-            disabled: false
+            disabled: true
             dib-os-release: '7'
             dib-os-element: 'centos-minimal'
             dib-os-packages: 'vim,less,bridge-utils,iputils,rsyslog,curl'
             extra-dib-elements: 'openssh-server'
         - 'suse':
-            disabled: false
+            disabled: true
             dib-os-release: '42.3'
             dib-os-element: 'opensuse-minimal'
             dib-os-packages: 'vim,less,bridge-utils,iputils,rsyslog,curl'
index 51455b5..47bf9bd 100755 (executable)
@@ -1,36 +1,36 @@
 #!/bin/bash
-[[ $CI_DEBUG == true ]] && redirect="/dev/stdout" || redirect="/dev/null"
+[[ ${CI_DEBUG} == true ]] && redirect="/dev/stdout" || redirect="/dev/null"
 
 # Remove containers along with image opnfv/yardstick*:<none>
-dangling_images=($(docker images -f "dangling=true" | grep opnfv/yardstick | awk '{print $3}'))
-if [[ -n ${dangling_images} ]]; then
+dangling_images=($(docker images -f "dangling=true" | awk '/opnfv[/]yardstick/ {print $3}'))
+if [[ ${#dangling_images[@]} -eq 0 ]] ; then
     echo "Removing opnfv/yardstick:<none> images and their containers..."
     for image_id in "${dangling_images[@]}"; do
         echo "      Removing image_id: $image_id and its containers"
-        containers=$(docker ps -a | grep $image_id | awk '{print $1}')
+        containers=$(docker ps -a | awk "/${image_id}/ {print \$1}")
         if [[ -n "$containers" ]];then
-            docker rm -f $containers >${redirect}
+            docker rm -f "${containers}" >${redirect}
         fi
-        docker rmi $image_id >${redirect}
+        docker rmi "${image_id}" >${redirect}
     done
 fi
 
 echo "Cleaning up docker containers/images..."
 # Remove previous running containers if exist
-if [[ ! -z $(docker ps -a | grep opnfv/yardstick) ]]; then
+if docker ps -a | grep -q opnfv/yardstick; then
     echo "Removing existing opnfv/yardstick containers..."
-    docker ps -a | grep opnfv/yardstick | awk '{print $1}' | xargs docker rm -f >$redirect
+    docker ps -a | awk "/${image_id}/ {print \$1}" | xargs docker rm -f >${redirect}
 
 fi
 
 # Remove existing images if exist
-if [[ ! -z $(docker images | grep opnfv/yardstick) ]]; then
+if docker images | grep -q opnfv/yardstick; then
     echo "Docker images to remove:"
     docker images | head -1 && docker images | grep opnfv/yardstick
-    image_tags=($(docker images | grep opnfv/yardstick | awk '{print $2}'))
-    for tag in "${image_tags[@]}"; do
-        echo "Removing docker image opnfv/yardstick:$tag..."
-        docker rmi opnfv/yardstick:$tag >$redirect
+    image_ids=($(docker images | awk '/opnfv[/]yardstick/ {print $3}'))
+    for id in "${image_ids[@]}"; do
+        echo "Removing docker image id $id..."
+        docker rmi "${id}" >${redirect}
     done
 fi
 
index e366670..22f2934 100644 (file)
@@ -54,6 +54,7 @@
                     <a href="#" ng-click="showPod = !showPod">{{pod.name}}</a>
                     <div class="show-pod" ng-class="{ 'hidden': ! showPod }" style="margin-left:24px;">
                         <p>
+                            owner: {{pod.owner}}<br>
                             role: {{pod.role}}<br>
                             mode: {{pod.mode}}<br>
                             create_date: {{pod.creation_date}}<br>
index acd3317..e80b1c6 100644 (file)
@@ -10,19 +10,33 @@ import functools
 import re
 
 from tornado import gen
-from tornado import web
 
+from opnfv_testapi.common import constants
 from opnfv_testapi.common import message
 from opnfv_testapi.common import raises
 from opnfv_testapi.db import api as dbapi
 
 
-def authenticate(method):
-    @web.asynchronous
-    @gen.coroutine
+def is_authorized(method):
     @functools.wraps(method)
     def wrapper(self, *args, **kwargs):
-        if self.auth:
+        if self.table in ['pods']:
+            testapi_id = self.get_secure_cookie(constants.TESTAPI_ID)
+            if not testapi_id:
+                raises.Unauthorized(message.not_login())
+            user_info = yield dbapi.db_find_one('users', {'user': testapi_id})
+            if not user_info:
+                raises.Unauthorized(message.not_lfid())
+            kwargs['owner'] = testapi_id
+        ret = yield gen.coroutine(method)(self, *args, **kwargs)
+        raise gen.Return(ret)
+    return wrapper
+
+
+def valid_token(method):
+    @functools.wraps(method)
+    def wrapper(self, *args, **kwargs):
+        if self.auth and self.table == 'results':
             try:
                 token = self.request.headers['X-Auth-Token']
             except KeyError:
index 951cbaf..8b5c3fb 100644 (file)
@@ -42,6 +42,14 @@ def invalid_token():
     return 'Invalid Token'
 
 
+def not_login():
+    return 'TestAPI id is not provided'
+
+
+def not_lfid():
+    return 'Not a valid Linux Foundation Account'
+
+
 def no_update():
     return 'Nothing to update'
 
index ed55c70..8e5dab2 100644 (file)
@@ -73,7 +73,10 @@ class GenericApiHandler(web.RequestHandler):
         cls_data = self.table_cls.from_dict(data)
         return cls_data.format_http()
 
-    @check.authenticate
+    @web.asynchronous
+    @gen.coroutine
+    @check.is_authorized
+    @check.valid_token
     @check.no_body
     @check.miss_fields
     @check.carriers_exist
@@ -172,13 +175,15 @@ class GenericApiHandler(web.RequestHandler):
     def _get_one(self, data, query=None):
         self.finish_request(self.format_data(data))
 
-    @check.authenticate
+    @web.asynchronous
+    @gen.coroutine
     @check.not_exist
     def _delete(self, data, query=None):
         yield dbapi.db_delete(self.table, query)
         self.finish_request()
 
-    @check.authenticate
+    @web.asynchronous
+    @gen.coroutine
     @check.no_body
     @check.not_exist
     @check.updated_one_not_exist
@@ -189,7 +194,8 @@ class GenericApiHandler(web.RequestHandler):
         update_req['_id'] = str(data._id)
         self.finish_request(update_req)
 
-    @check.authenticate
+    @web.asynchronous
+    @gen.coroutine
     @check.no_body
     @check.not_exist
     @check.updated_one_not_exist
index 2c3ea97..415d3d6 100644 (file)
@@ -29,13 +29,14 @@ class PodCreateRequest(models.ModelBase):
 class Pod(models.ModelBase):
     def __init__(self,
                  name='', mode='', details='',
-                 role="", _id='', create_date=''):
+                 role="", _id='', create_date='', owner=''):
         self.name = name
         self.mode = mode
         self.details = details
         self.role = role
         self._id = _id
         self.creation_date = create_date
+        self.owner = owner
 
 
 @swagger.model()
index 8cfc513..ea22972 100644 (file)
@@ -1,4 +1,5 @@
 import argparse
+import pytest
 
 
 def test_config_normal(mocker, config_normal):
@@ -13,3 +14,11 @@ def test_config_normal(mocker, config_normal):
     assert CONF.api_debug is True
     assert CONF.api_authenticate is False
     assert CONF.ui_url == 'http://localhost:8000'
+
+
+def test_config_file_not_exist(mocker):
+    mocker.patch('os.path.exists', return_value=False)
+    with pytest.raises(Exception) as m_exc:
+        from opnfv_testapi.common import config
+        config.Config()
+    assert 'not found' in str(m_exc.value)
index b8f696c..aa99b90 100644 (file)
@@ -9,6 +9,39 @@
 import functools
 import httplib
 
+from concurrent.futures import ThreadPoolExecutor
+import mock
+
+
+O_get_secure_cookie = (
+    'opnfv_testapi.resources.handlers.GenericApiHandler.get_secure_cookie')
+
+
+def thread_execute(method, *args, **kwargs):
+        with ThreadPoolExecutor(max_workers=2) as executor:
+            result = executor.submit(method, *args, **kwargs)
+        return result
+
+
+def mock_invalid_lfid():
+    def _mock_invalid_lfid(xstep):
+        def wrap(self, *args, **kwargs):
+            with mock.patch(O_get_secure_cookie) as m_cookie:
+                m_cookie.return_value = 'InvalidUser'
+                return xstep(self, *args, **kwargs)
+        return wrap
+    return _mock_invalid_lfid
+
+
+def mock_valid_lfid():
+    def _mock_valid_lfid(xstep):
+        def wrap(self, *args, **kwargs):
+            with mock.patch(O_get_secure_cookie) as m_cookie:
+                m_cookie.return_value = 'ValidUser'
+                return xstep(self, *args, **kwargs)
+        return wrap
+    return _mock_valid_lfid
+
 
 def upload(excepted_status, excepted_response):
     def _upload(create_request):
index 3320a86..c44a92c 100644 (file)
@@ -288,3 +288,4 @@ testcases = MemDb('testcases')
 results = MemDb('results')
 scenarios = MemDb('scenarios')
 tokens = MemDb('tokens')
+users = MemDb('users')
index 39633e5..89cd7e8 100644 (file)
@@ -6,13 +6,16 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
+from datetime import datetime
 import json
 from os import path
 
+from bson.objectid import ObjectId
 import mock
 from tornado import testing
 
 from opnfv_testapi.resources import models
+from opnfv_testapi.resources import pod_models
 from opnfv_testapi.tests.unit import fake_pymongo
 
 
@@ -26,10 +29,32 @@ class TestBase(testing.AsyncHTTPTestCase):
         self.get_res = None
         self.list_res = None
         self.update_res = None
+        self.pod_d = pod_models.Pod(name='zte-pod1',
+                                    mode='virtual',
+                                    details='zte pod 1',
+                                    role='community-ci',
+                                    _id=str(ObjectId()),
+                                    owner='ValidUser',
+                                    create_date=str(datetime.now()))
+        self.pod_e = pod_models.Pod(name='zte-pod2',
+                                    mode='metal',
+                                    details='zte pod 2',
+                                    role='production-ci',
+                                    _id=str(ObjectId()),
+                                    owner='ValidUser',
+                                    create_date=str(datetime.now()))
         self.req_d = None
         self.req_e = None
         self.addCleanup(self._clear)
         super(TestBase, self).setUp()
+        fake_pymongo.users.insert({"user": "ValidUser",
+                                   'email': 'validuser@lf.com',
+                                   'fullname': 'Valid User',
+                                   'groups': [
+                                       'opnfv-testapi-users',
+                                       'opnfv-gerrit-functest-submitters',
+                                       'opnfv-gerrit-qtip-contributors']
+                                   })
 
     def tearDown(self):
         self.db_patcher.stop()
index d1a19f7..5d9da3a 100644 (file)
@@ -12,24 +12,29 @@ import unittest
 from opnfv_testapi.common import message
 from opnfv_testapi.resources import pod_models
 from opnfv_testapi.tests.unit import executor
+from opnfv_testapi.tests.unit import fake_pymongo
 from opnfv_testapi.tests.unit.resources import test_base as base
 
 
 class TestPodBase(base.TestBase):
     def setUp(self):
         super(TestPodBase, self).setUp()
-        self.req_d = pod_models.PodCreateRequest('zte-1', 'virtual',
-                                                 'zte pod 1', 'ci-pod')
-        self.req_e = pod_models.PodCreateRequest('zte-2', 'metal', 'zte pod 2')
-        self.req_f = pod_models.PodCreateRequest('Zte-1', 'virtual',
-                                                 'zte pod 1', 'ci-pod')
         self.get_res = pod_models.Pod
         self.list_res = pod_models.Pods
         self.basePath = '/api/v1/pods'
+        self.req_d = pod_models.PodCreateRequest(name=self.pod_d.name,
+                                                 mode=self.pod_d.mode,
+                                                 details=self.pod_d.details,
+                                                 role=self.pod_d.role)
+        self.req_e = pod_models.PodCreateRequest(name=self.pod_e.name,
+                                                 mode=self.pod_e.mode,
+                                                 details=self.pod_e.details,
+                                                 role=self.pod_e.role)
 
     def assert_get_body(self, pod, req=None):
         if not req:
             req = self.req_d
+        self.assertEqual(pod.owner, 'ValidUser')
         self.assertEqual(pod.name, req.name)
         self.assertEqual(pod.mode, req.mode)
         self.assertEqual(pod.details, req.details)
@@ -39,38 +44,54 @@ class TestPodBase(base.TestBase):
 
 
 class TestPodCreate(TestPodBase):
+    @executor.create(httplib.BAD_REQUEST, message.not_login())
+    def test_notlogin(self):
+        return self.req_d
+
+    @executor.mock_invalid_lfid()
+    @executor.create(httplib.BAD_REQUEST, message.not_lfid())
+    def test_invalidLfid(self):
+        return self.req_d
+
+    @executor.mock_valid_lfid()
     @executor.create(httplib.BAD_REQUEST, message.no_body())
     def test_withoutBody(self):
         return None
 
+    @executor.mock_valid_lfid()
     @executor.create(httplib.BAD_REQUEST, message.missing('name'))
     def test_emptyName(self):
         return pod_models.PodCreateRequest('')
 
+    @executor.mock_valid_lfid()
     @executor.create(httplib.BAD_REQUEST, message.missing('name'))
     def test_noneName(self):
         return pod_models.PodCreateRequest(None)
 
+    @executor.mock_valid_lfid()
     @executor.create(httplib.OK, 'assert_create_body')
     def test_success(self):
         return self.req_d
 
+    @executor.mock_valid_lfid()
     @executor.create(httplib.FORBIDDEN, message.exist_base)
     def test_alreadyExist(self):
-        self.create_d()
+        fake_pymongo.pods.insert(self.pod_d.format())
         return self.req_d
 
+    @executor.mock_valid_lfid()
     @executor.create(httplib.FORBIDDEN, message.exist_base)
     def test_alreadyExistCaseInsensitive(self):
-        self.create(self.req_f)
+        fake_pymongo.pods.insert(self.pod_d.format())
+        self.req_d.name = self.req_d.name.upper()
         return self.req_d
 
 
 class TestPodGet(TestPodBase):
     def setUp(self):
         super(TestPodGet, self).setUp()
-        self.create_d()
-        self.create_e()
+        fake_pymongo.pods.insert(self.pod_d.format())
+        fake_pymongo.pods.insert(self.pod_e.format())
 
     @executor.get(httplib.NOT_FOUND, message.not_found_base)
     def test_notExist(self):
@@ -78,7 +99,7 @@ class TestPodGet(TestPodBase):
 
     @executor.get(httplib.OK, 'assert_get_body')
     def test_getOne(self):
-        return self.req_d.name
+        return self.pod_d.name
 
     @executor.get(httplib.OK, '_assert_list')
     def test_list(self):
@@ -87,10 +108,10 @@ class TestPodGet(TestPodBase):
     def _assert_list(self, body):
         self.assertEqual(len(body.pods), 2)
         for pod in body.pods:
-            if self.req_d.name == pod.name:
+            if self.pod_d.name == pod.name:
                 self.assert_get_body(pod)
             else:
-                self.assert_get_body(pod, self.req_e)
+                self.assert_get_body(pod, self.pod_e)
 
 
 if __name__ == '__main__':
index 1e83ed3..f5026c9 100644 (file)
@@ -7,17 +7,18 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 import copy
+from datetime import datetime
+from datetime import timedelta
 import httplib
-import unittest
-from datetime import datetime, timedelta
 import json
+import unittest
 
 from opnfv_testapi.common import message
-from opnfv_testapi.resources import pod_models
 from opnfv_testapi.resources import project_models
 from opnfv_testapi.resources import result_models
 from opnfv_testapi.resources import testcase_models
 from opnfv_testapi.tests.unit import executor
+from opnfv_testapi.tests.unit import fake_pymongo
 from opnfv_testapi.tests.unit.resources import test_base as base
 
 
@@ -52,7 +53,8 @@ class Details(object):
 
 class TestResultBase(base.TestBase):
     def setUp(self):
-        self.pod = 'zte-pod1'
+        super(TestResultBase, self).setUp()
+        self.pod = self.pod_d.name
         self.project = 'functest'
         self.case = 'vPing'
         self.installer = 'fuel'
@@ -65,7 +67,6 @@ class TestResultBase(base.TestBase):
         self.stop_date = str(datetime.now() + timedelta(minutes=1))
         self.update_date = str(datetime.now() + timedelta(days=1))
         self.update_step = -0.05
-        super(TestResultBase, self).setUp()
         self.details = Details(timestart='0', duration='9s', status='OK')
         self.req_d = result_models.ResultCreateRequest(
             pod_name=self.pod,
@@ -84,10 +85,6 @@ class TestResultBase(base.TestBase):
         self.list_res = result_models.TestResults
         self.update_res = result_models.TestResult
         self.basePath = '/api/v1/results'
-        self.req_pod = pod_models.PodCreateRequest(
-            self.pod,
-            'metal',
-            'zte pod 1')
         self.req_project = project_models.ProjectCreateRequest(
             self.project,
             'vping test')
@@ -95,7 +92,7 @@ class TestResultBase(base.TestBase):
             self.case,
             '/cases/vping',
             'vping-ssh test')
-        self.create_help('/api/v1/pods', self.req_pod)
+        fake_pymongo.pods.insert(self.pod_d.format())
         self.create_help('/api/v1/projects', self.req_project)
         self.create_help('/api/v1/projects/%s/cases',
                          self.req_testcase,
index 940e256..bd64723 100644 (file)
@@ -9,13 +9,12 @@ import unittest
 from tornado import web
 
 from opnfv_testapi.common import message
-from opnfv_testapi.resources import project_models
 from opnfv_testapi.tests.unit import executor
 from opnfv_testapi.tests.unit import fake_pymongo
-from opnfv_testapi.tests.unit.resources import test_base as base
+from opnfv_testapi.tests.unit.resources import test_result
 
 
-class TestToken(base.TestBase):
+class TestTokenCreateResult(test_result.TestResultBase):
     def get_app(self):
         from opnfv_testapi.router import url_mappings
         return web.Application(
@@ -25,27 +24,23 @@ class TestToken(base.TestBase):
             auth=True
         )
 
-
-class TestTokenCreateProject(TestToken):
     def setUp(self):
-        super(TestTokenCreateProject, self).setUp()
-        self.req_d = project_models.ProjectCreateRequest('vping')
+        super(TestTokenCreateResult, self).setUp()
         fake_pymongo.tokens.insert({"access_token": "12345"})
-        self.basePath = '/api/v1/projects'
 
     @executor.create(httplib.FORBIDDEN, message.invalid_token())
-    def test_projectCreateTokenInvalid(self):
+    def test_resultCreateTokenInvalid(self):
         self.headers['X-Auth-Token'] = '1234'
         return self.req_d
 
     @executor.create(httplib.UNAUTHORIZED, message.unauthorized())
-    def test_projectCreateTokenUnauthorized(self):
+    def test_resultCreateTokenUnauthorized(self):
         if 'X-Auth-Token' in self.headers:
             self.headers.pop('X-Auth-Token')
         return self.req_d
 
     @executor.create(httplib.OK, '_create_success')
-    def test_projectCreateTokenSuccess(self):
+    def test_resultCreateTokenSuccess(self):
         self.headers['X-Auth-Token'] = '12345'
         return self.req_d
 
@@ -53,62 +48,5 @@ class TestTokenCreateProject(TestToken):
         self.assertIn('CreateResponse', str(type(body)))
 
 
-class TestTokenDeleteProject(TestToken):
-    def setUp(self):
-        super(TestTokenDeleteProject, self).setUp()
-        self.req_d = project_models.ProjectCreateRequest('vping')
-        fake_pymongo.tokens.insert({"access_token": "12345"})
-        self.basePath = '/api/v1/projects'
-        self.headers['X-Auth-Token'] = '12345'
-        self.create_d()
-
-    @executor.delete(httplib.FORBIDDEN, message.invalid_token())
-    def test_projectDeleteTokenIvalid(self):
-        self.headers['X-Auth-Token'] = '1234'
-        return self.req_d.name
-
-    @executor.delete(httplib.UNAUTHORIZED, message.unauthorized())
-    def test_projectDeleteTokenUnauthorized(self):
-        self.headers.pop('X-Auth-Token')
-        return self.req_d.name
-
-    @executor.delete(httplib.OK, '_delete_success')
-    def test_projectDeleteTokenSuccess(self):
-        return self.req_d.name
-
-    def _delete_success(self, body):
-        self.assertEqual('', body)
-
-
-class TestTokenUpdateProject(TestToken):
-    def setUp(self):
-        super(TestTokenUpdateProject, self).setUp()
-        self.req_d = project_models.ProjectCreateRequest('vping')
-        fake_pymongo.tokens.insert({"access_token": "12345"})
-        self.basePath = '/api/v1/projects'
-        self.headers['X-Auth-Token'] = '12345'
-        self.create_d()
-
-    @executor.update(httplib.FORBIDDEN, message.invalid_token())
-    def test_projectUpdateTokenIvalid(self):
-        self.headers['X-Auth-Token'] = '1234'
-        req = project_models.ProjectUpdateRequest('newName', 'new description')
-        return req, self.req_d.name
-
-    @executor.update(httplib.UNAUTHORIZED, message.unauthorized())
-    def test_projectUpdateTokenUnauthorized(self):
-        self.headers.pop('X-Auth-Token')
-        req = project_models.ProjectUpdateRequest('newName', 'new description')
-        return req, self.req_d.name
-
-    @executor.update(httplib.OK, '_update_success')
-    def test_projectUpdateTokenSuccess(self):
-        req = project_models.ProjectUpdateRequest('newName', 'new description')
-        return req, self.req_d.name
-
-    def _update_success(self, request, body):
-        self.assertIn(request.name, body)
-
-
 if __name__ == '__main__':
     unittest.main()