Merge "SSH improvements for Ansible"
authormadavi <jm00553988@techmahindra.com>
Tue, 5 Nov 2019 04:51:32 +0000 (05:51 +0100)
committerGerrit Code Review <root@osm.etsi.org>
Tue, 5 Nov 2019 04:51:32 +0000 (05:51 +0100)
58 files changed:
charms/juju-env.sh
descriptor-packages/vnfd/hackfest_cloudinit_vnf/src/hackfest_cloudinit_vnfd.yaml
descriptor-packages/vnfd/hackfest_epasriov_vnf/src/hackfest_epasriov_vnfd.yaml
descriptor-packages/vnfd/hackfest_multivdu_vnf/src/hackfest_multivdu_vnfd.yaml
descriptor-packages/vnfd/hackfest_simplecharm_vnf/src/hackfest_simplecharm_vnfd.yaml
devops-stages/stage-archive.sh
docker/LCM/Dockerfile
docker/NBI/Dockerfile
docker/osmclient/Dockerfile
installers/docker/__lcm__.env
installers/docker/docker-compose.yaml
installers/full_install_osm.sh
jenkins/ci-pipelines/ci_stage_3.groovy
robot-systest/README_Robot_Test.md [new file with mode: 0644]
robot-systest/lib/api/common.robot [new file with mode: 0644]
robot-systest/lib/api/vim_lib.robot [new file with mode: 0644]
robot-systest/lib/cli/ns_lib.robot [new file with mode: 0644]
robot-systest/lib/cli/nsd_lib.robot [new file with mode: 0644]
robot-systest/lib/cli/sdnc_account_lib.robot [new file with mode: 0644]
robot-systest/lib/cli/vim_account_lib.robot [new file with mode: 0644]
robot-systest/lib/cli/vnfd_lib.robot [new file with mode: 0644]
robot-systest/lib/client_lib/client_lib.py [new file with mode: 0644]
robot-systest/lib/custom_lib.py [new file with mode: 0644]
robot-systest/lib/gui/login_gui.robot [new file with mode: 0644]
robot-systest/resource/api/common.robot [new file with mode: 0644]
robot-systest/resource/api/variables.py [new file with mode: 0644]
robot-systest/resource/cli/hackfest_basic_ns_data.py [new file with mode: 0644]
robot-systest/resource/cli/hackfest_cloudinit_ns_data.py [new file with mode: 0644]
robot-systest/resource/cli/hackfest_epa_ns_data.py [new file with mode: 0644]
robot-systest/resource/cli/hackfest_multivdu_ns_data.py [new file with mode: 0644]
robot-systest/resource/cli/hackfest_simplecharm_ns_data.py [new file with mode: 0644]
robot-systest/resource/cli/test_vnf_data.py [new file with mode: 0644]
robot-systest/run_test.sh [new file with mode: 0644]
robot-systest/testsuite/api/TS01__Vim_Account.robot [new file with mode: 0644]
robot-systest/testsuite/cli/TS008__Test_SDNC.robot [new file with mode: 0644]
robot-systest/testsuite/cli/TS01__Test_VNF.robot [new file with mode: 0644]
robot-systest/testsuite/cli/TS02__Test_Vim.robot [new file with mode: 0644]
robot-systest/testsuite/cli/TS03__Hackfest_Basic_NS.robot [new file with mode: 0644]
robot-systest/testsuite/cli/TS04__Hackfest_Simplecharm_NS.robot [new file with mode: 0644]
robot-systest/testsuite/cli/TS05__Hackfest_Multivdu_NS.robot [new file with mode: 0644]
robot-systest/testsuite/cli/TS06__Hackfest_Cloudinit_NS.robot [new file with mode: 0644]
robot-systest/testsuite/cli/TS07__Hackfest_EPA_NS.robot [new file with mode: 0644]
robot-systest/testsuite/client_library/TS01__OSMClient_Library_Test.robot [new file with mode: 0644]
robot-systest/testsuite/gui/TS01__Test_GUI_Login.robot [new file with mode: 0644]
tools/OVF_converter/Usage.txt [new file with mode: 0644]
tools/OVF_converter/converter.py [new file with mode: 0644]
tools/OVF_converter/format_converter/__init__.py [deleted file]
tools/OVF_converter/format_converter/command_progress.py [deleted file]
tools/OVF_converter/format_converter/converter.py [deleted file]
tools/OVF_converter/format_converter/ovf_converter_cli.py [deleted file]
tools/OVF_converter/install.sh
tools/OVF_converter/ovf_converter_cli.py [new file with mode: 0644]
tools/OVF_converter/ovf_template/ide_cdrom.xml
tools/OVF_converter/ovf_template/template.xml
tools/OVF_converter/ovf_uploader_cli.py [new file with mode: 0644]
tools/OVF_converter/readme.txt
tools/OVF_converter/uploader.py [new file with mode: 0644]
tools/vmware_ovf_upload.py

index 59fa9e7..61ef85e 100644 (file)
@@ -1,3 +1,24 @@
+#!/usr/bin/env bash
+
+##
+# Copyright 2019 ETSI
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+
 # Set the Juju env variables for building a layer
 export JUJU_REPOSITORY=`pwd`
 export INTERFACE_PATH=$JUJU_REPOSITORY/interfaces
index 818c62a..24a6548 100644 (file)
@@ -1,3 +1,28 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 ETSI
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com
+# 19-aug-2019 : changed vdu image from hackfest3-mgmt to ubuntu1604
+##
+
 vnfd:vnfd-catalog:
     vnfd:
     -   id: hackfest_cloudinit-vnf
@@ -28,7 +53,7 @@ vnfd:vnfd-catalog:
         vdu:
         -   id: mgmtVM
             name: mgmtVM
-            image: hackfest3-mgmt
+            image: ubuntu1604
             count: '1'
             vm-flavor:
                 vcpu-count: '1'
@@ -55,7 +80,7 @@ vnfd:vnfd-catalog:
             cloud-init-file: cloud-config.txt
         -   id: dataVM
             name: dataVM
-            image: hackfest3-mgmt
+            image: ubuntu1604
             count: '1'
             vm-flavor:
                 vcpu-count: '1'
index f039389..476f126 100644 (file)
@@ -1,3 +1,28 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 ETSI
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com
+# 19-aug-2019 : changed vdu image from hackfest3-mgmt & hackfest-pktgen to ubuntu1604
+##
+
 vnfd:vnfd-catalog:
     vnfd:
     -   id: hackfest_epasriov-vnf
@@ -28,7 +53,7 @@ vnfd:vnfd-catalog:
         vdu:
         -   id: mgmtVM
             name: mgmtVM
-            image: hackfest3-mgmt
+            image: ubuntu1604
             count: '1'
             vm-flavor:
                 vcpu-count: '1'
@@ -64,7 +89,7 @@ vnfd:vnfd-catalog:
             cloud-init-file: cloud-config.txt
         -   id: dataVM
             name: dataVM
-            image: hackfest-pktgen
+            image: ubuntu1604
             count: '1'
             vm-flavor:
                 vcpu-count: '8'
index e8981ff..ff411e0 100644 (file)
@@ -1,3 +1,28 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 ETSI
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com
+# 19-aug-2019 : changed vdu image from US1604 to ubuntu1604
+##
+
 vnfd:vnfd-catalog:
     vnfd:
     -   id: hackfest_multivdu-vnf
@@ -28,7 +53,7 @@ vnfd:vnfd-catalog:
         vdu:
         -   id: mgmtVM
             name: mgmtVM
-            image: US1604
+            image: ubuntu1604
             count: '1'
             vm-flavor:
                 vcpu-count: '1'
@@ -54,7 +79,7 @@ vnfd:vnfd-catalog:
 
         -   id: dataVM
             name: dataVM
-            image: US1604
+            image: ubuntu1604
             count: '1'
             vm-flavor:
                 vcpu-count: '1'
index ad9bdd5..7295c54 100644 (file)
@@ -1,3 +1,28 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 ETSI
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com
+# 19-aug-2019 : changed vdu image from hackfest3-mgmt to ubuntu1604
+##
+
 vnfd:vnfd-catalog:
     vnfd:
     -   id: hackfest-simplecharm-vnf
@@ -28,7 +53,7 @@ vnfd:vnfd-catalog:
         vdu:
         -   id: mgmtVM
             name: mgmtVM
-            image: hackfest3-mgmt
+            image: ubuntu1604
             count: '1'
             vm-flavor:
                 vcpu-count: '1'
@@ -55,7 +80,7 @@ vnfd:vnfd-catalog:
             cloud-init-file: cloud-config.txt
         -   id: dataVM
             name: dataVM
-            image: hackfest3-mgmt
+            image: ubuntu1604
             count: '1'
             vm-flavor:
                 vcpu-count: '1'
index 160b1a3..8dc677e 100755 (executable)
@@ -14,7 +14,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-PKG_DIRECTORIES="jenkins installers systest charms descriptor-packages tools docker"
+PKG_DIRECTORIES="jenkins installers systest charms descriptor-packages tools docker robot-systest"
 MDG_NAME=devops
 DEB_INSTALL=debian/osm-$MDG_NAME.install
 export DEBEMAIL="mmarchetti@sandvine.com"
index 72d6a86..5e81a48 100644 (file)
@@ -115,9 +115,10 @@ ENV OSMLCM_MESSAGE_DRIVER  kafka
 ENV OSMLCM_MESSAGE_HOST    kafka
 ENV OSMLCM_MESSAGE_PORT    9092
 
-HEALTHCHECK --interval=30s --timeout=140s --retries=1 \
-  CMD python3 /usr/lib/python3/dist-packages/osm_lcm/lcm.py --health-check || exit 1
+HEALTHCHECK --start-period=120s --interval=30s --timeout=30s --retries=1 \
+  CMD python3 -m osm_lcm.lcm --health-check || exit 1
 
 
 # Run app.py when the container launches
-CMD ["python3", "/usr/lib/python3/dist-packages/osm_lcm/lcm.py"]
+CMD python3 -m osm_lcm.lcm
+
index 094d029..5d756b3 100644 (file)
 
 # This creates osm/NBI docker from local NBI source code
 
-FROM ubuntu:16.04
+FROM ubuntu:18.04
 
-RUN apt-get update && apt-get -y install curl software-properties-common
+RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install curl software-properties-common
 
-RUN apt-get update && apt-get install -y git python3 python3-jsonschema \
+RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y git python3 python3-jsonschema \
     python3-pymongo python3-yaml python3-pip python3-keystoneclient \
     && pip3 install -U pip \
-    && python3 -m pip install aiokafka aiohttp cherrypy==18.0.0 pyangbind keystoneauth1 \
+    && python3 -m pip install aiokafka aiohttp cherrypy==18.1.2 pyangbind keystoneauth1 \
     && mkdir -p /app/storage/kafka && mkdir -p /app/log
 
 ARG REPOSITORY_BASE=http://osm-download.etsi.org/repository/osm/debian
@@ -65,6 +65,8 @@ VOLUME /app/log
 # server
 ENV OSMNBI_SOCKET_HOST     0.0.0.0
 ENV OSMNBI_SOCKET_PORT     9999
+ENV OSMNBI_SERVER_SSL_CERTIFICATE               /app/osm_nbi/http/cert.pem
+ENV OSMNBI_SERVER_SSL_PRIVATE_KEY               /app/osm_nbi/http/privkey.pem
 # storage
 ENV OSMNBI_STORAGE_PATH    /app/storage
 # database
@@ -75,9 +77,6 @@ ENV OSMNBI_DATABASE_URI   mongodb://mongo:27017
 
 # web
 ENV OSMNBI_STATIC_DIR      /app/osm_nbi/html_public
-# logs
-ENV OSMNBI_LOG_FILE        /app/log
-ENV OSMNBI_LOG_LEVEL       DEBUG
 # message
 ENV OSMNBI_MESSAGE_DRIVER  kafka
 ENV OSMNBI_MESSAGE_HOST    kafka
@@ -103,4 +102,5 @@ HEALTHCHECK --start-period=120s --interval=10s --timeout=5s --retries=5 \
   CMD curl -k https://localhost:9999/osm/ | grep Welcome || exit 1
 
 # Run app.py when the container launches
-CMD ["python3", "/usr/lib/python3/dist-packages/osm_nbi/nbi.py"]
+CMD python3 -m osm_nbi.nbi
+
index 3bf5fb3..6afddbb 100644 (file)
@@ -1,6 +1,8 @@
 ##
 # Copyright 2019 ETSI
 #
+# All Rights Reserved.
+#
 # 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
@@ -14,7 +16,6 @@
 # under the License.
 ##
 
-########################################################################
 
 FROM ubuntu:16.04
 
@@ -25,6 +26,7 @@ RUN apt-get update && apt-get -y install curl software-properties-common
 RUN apt-get update && apt-get -y install python \
     libcurl4-gnutls-dev libgnutls-dev iputils-ping python-pip \
     python-openstackclient wget
+
 RUN pip install -U pip && python -m pip install python-magic pyangbind pytest==4.6.3
 
 ARG REPOSITORY_BASE=http://osm-download.etsi.org/repository/osm/debian
index 466b750..762061a 100644 (file)
@@ -14,3 +14,4 @@
 OSMLCM_VCA_HOST=__JUJU_CONTROLLER_IP__
 OSMLCM_VCA_SECRET=__JUJU_PASSWORD__
 OSMLCM_VCA_PUBKEY=__JUJU_PUBKEY__
+OSMLCM_VCA_APIPROXY=__JUJU_APIPROXY__
index c325776..6675e97 100644 (file)
@@ -44,6 +44,11 @@ services:
       interval: 10s
       timeout: 10s
       retries: 3
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "2"
   kafka:
     image: wurstmeister/kafka:${KAFKA_TAG:-latest}
     ports:
@@ -62,6 +67,11 @@ services:
       interval: 20s
       timeout: 10s
       retries: 5
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "2"
     #depends_on:
     #  - zookeeper
   mongo:
@@ -82,6 +92,11 @@ services:
       - prom_db:/prometheus
     networks:
       - netOSM
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "2"
   keystone:
     image: ${DOCKER_USER:-opensourcemano}/keystone:${TAG:-6}
     networks:
@@ -92,6 +107,11 @@ services:
       - ./keystone.env
     ports:
       - "${OSM_KEYSTONE_PORTS:-5000:5000}"
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "2"
   nbi:
     image: ${DOCKER_USER:-opensourcemano}/nbi:${TAG:-6}
     networks:
@@ -105,6 +125,11 @@ services:
       - ./nbi.env
     ports:
       - "${OSM_NBI_PORTS:-9999:9999}"
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "2"
     #depends_on:
     #  - kafka
     #  - mongo
@@ -120,6 +145,11 @@ services:
       OSMLCM_MESSAGE_HOST: kafka
     env_file:
       - ./lcm.env
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "2"
     #depends_on:
     #  - kafka
     #  - mongo
@@ -134,6 +164,11 @@ services:
       - ro_db:/var/lib/mysql
     env_file:
       - ./ro-db.env
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "2"
 #    ports:
 #      - "3306:3306"
   ro:
@@ -150,6 +185,11 @@ services:
       - ro:/var/log/osm
     ports:
       - "${OSM_RO_PORTS:-9090:9090}"
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "2"
   mon:
     image: ${DOCKER_USER:-opensourcemano}/mon:${TAG:-6}
     networks:
@@ -201,3 +241,8 @@ services:
       - ./lwui.env
     ports:
       - "${OSM_UI_PORTS:-80:80}"
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "100m"
+        max-file: "2"
index 047a84f..e564cfb 100755 (executable)
@@ -31,6 +31,7 @@ function usage(){
     echo -e "     -S <VCA secret> use VCA/juju secret key"
     echo -e "     -P <VCA pubkey> use VCA/juju public key file"
     echo -e "     -C <VCA cacert> use VCA/juju CA certificate file"
+    echo -e "     -A <VCA apiproxy> use VCA/juju API proxy"
     echo -e "     --vimemu:       additionally deploy the VIM emulator as a docker container"
     echo -e "     --elk_stack:    additionally deploy an ELK docker stack for event logging"
     echo -e "     --pm_stack:     additionally deploy a Prometheus+Grafana stack for performance monitoring (PM)"
@@ -644,6 +645,13 @@ function juju_createcontroller() {
     [ $(juju controllers | awk "/^${OSM_STACK_NAME}[\*| ]/{print $1}"|wc -l) -eq 1 ] || FATAL "Juju installation failed"
 }
 
+function juju_createproxy() {
+    if ! sudo iptables -t nat -C PREROUTING -p tcp -m tcp --dport 17070 -j DNAT --to-destination $OSM_VCA_HOST; then
+        sudo iptables -t nat -A PREROUTING -p tcp -m tcp --dport 17070 -j DNAT --to-destination $OSM_VCA_HOST
+        sudo netfilter-persistent save
+    fi
+}
+
 function generate_docker_images() {
     echo "Pulling and generating docker images"
     _build_from=$COMMIT_ID
@@ -747,15 +755,26 @@ function cmp_overwrite() {
     fi
 }
 
-function generate_config_log_folders() {
-    echo "Generating config and log folders"
-    $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/docker-compose.yaml $OSM_DOCKER_WORK_DIR/docker-compose.yaml
-    $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/prometheus.yml $OSM_DOCKER_WORK_DIR/prometheus.yml
-    echo "Finished generation of config and log folders"
-}
 
 function generate_docker_env_files() {
+    echo "Doing a backup of existing env files"
+    $WORKDIR_SUDO cp $OSM_DOCKER_WORK_DIR/keystone-db.env{,~}
+    $WORKDIR_SUDO cp $OSM_DOCKER_WORK_DIR/keystone.env{,~}
+    $WORKDIR_SUDO cp $OSM_DOCKER_WORK_DIR/lcm.env{,~}
+    $WORKDIR_SUDO cp $OSM_DOCKER_WORK_DIR/lwui.env{,~}
+    $WORKDIR_SUDO cp $OSM_DOCKER_WORK_DIR/mon.env{,~}
+    $WORKDIR_SUDO cp $OSM_DOCKER_WORK_DIR/nbi.env{,~}
+    $WORKDIR_SUDO cp $OSM_DOCKER_WORK_DIR/pol.env{,~}
+    $WORKDIR_SUDO cp $OSM_DOCKER_WORK_DIR/ro-db.env{,~}
+    $WORKDIR_SUDO cp $OSM_DOCKER_WORK_DIR/ro.env{,~}
+
     echo "Generating docker env files"
+    # Docker-compose
+    $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/docker-compose.yaml $OSM_DOCKER_WORK_DIR/docker-compose.yaml
+
+    # Prometheus
+    $WORKDIR_SUDO cp -b ${OSM_DEVOPS}/installers/docker/prometheus.yml $OSM_DOCKER_WORK_DIR/prometheus.yml
+
     # LCM
     if [ ! -f $OSM_DOCKER_WORK_DIR/lcm.env ]; then
         echo "OSMLCM_DATABASE_COMMONKEY=${OSM_DATABASE_COMMONKEY}" | $WORKDIR_SUDO tee -a $OSM_DOCKER_WORK_DIR/lcm.env
@@ -785,6 +804,12 @@ function generate_docker_env_files() {
     #    $WORKDIR_SUDO sed -i "s|OSMLCM_VCA_CACERT.*|OSMLCM_VCA_CACERT=\"${OSM_VCA_CACERT}\"|g" $OSM_DOCKER_WORK_DIR/lcm.env
     #fi
 
+    if ! grep -Fq "OSMLCM_VCA_APIPROXY" $OSM_DOCKER_WORK_DIR/lcm.env; then
+        echo "OSMLCM_VCA_APIPROXY=${OSM_VCA_APIPROXY}" | $WORKDIR_SUDO tee -a $OSM_DOCKER_WORK_DIR/lcm.env
+    else
+        $WORKDIR_SUDO sed -i "s|OSMLCM_VCA_APIPROXY.*|OSMLCM_VCA_APIPROXY=${OSM_VCA_APIPROXY}|g" $OSM_DOCKER_WORK_DIR/lcm.env
+    fi
+
     # RO
     MYSQL_ROOT_PASSWORD=$(generate_secret)
     if [ ! -f $OSM_DOCKER_WORK_DIR/ro-db.env ]; then
@@ -1035,6 +1060,12 @@ function install_lightweight() {
        #OSM_VCA_CACERT=$(juju controllers --format json | jq -r '.controllers["osm"]["ca-cert"]' | grep -v "\-\-\-\-\-.*CERTIFICATE\-\-\-\-\-")
     #    [ -z "$OSM_VCA_CACERT" ] && FATAL "Cannot obtain juju CA certificate"
     #fi
+    if [ -z "$OSM_VCA_APIPROXY" ]; then
+        OSM_VCA_APIPROXY=$DEFAULT_IP
+        [ -z "$OSM_VCA_APIPROXY" ] && FATAL "Cannot obtain juju api proxy"
+    fi
+    juju_createproxy
+
     if [ -z "$OSM_DATABASE_COMMONKEY" ]; then
         OSM_DATABASE_COMMONKEY=$(generate_secret)
         [ -z "OSM_DATABASE_COMMONKEY" ] && FATAL "Cannot generate common db secret"
@@ -1049,7 +1080,6 @@ function install_lightweight() {
     [ -z "$DOCKER_NOBUILD" ] && generate_docker_images
     track docker_build
     generate_docker_env_files
-    generate_config_log_folders
 
     # remove old stack
     remove_stack $OSM_STACK_NAME
@@ -1205,7 +1235,7 @@ OSM_DATABASE_COMMONKEY=
 ELASTIC_VERSION=6.4.2
 ELASTIC_CURATOR_VERSION=5.5.4
 
-while getopts ":hy-:b:r:k:u:R:l:p:D:o:m:H:S:s:w:t:U:P:" o; do
+while getopts ":hy-:b:r:k:u:R:l:p:D:o:m:H:S:s:w:t:U:P:A:" o; do
     case "${o}" in
         h)
             usage && exit 0
@@ -1254,6 +1284,9 @@ while getopts ":hy-:b:r:k:u:R:l:p:D:o:m:H:S:s:w:t:U:P:" o; do
         P)
             OSM_VCA_PUBKEY=$(cat ${OPTARG})
             ;;
+        A)
+            OSM_VCA_APIPROXY="${OPTARG}"
+            ;;
         w)
             # when specifying workdir, do not use sudo for access
             WORKDIR_SUDO=
index 42fbe1e..e0d6e05 100644 (file)
@@ -19,7 +19,9 @@
  * 1. Bug 745 : Jayant Madavi, Mrityunjay Yadav : JM00553988@techmahindra.com : 23-july-2019 : Improvement to the code, typically we have 2 *    or more branches whose build gets triggered, ex master & release branch, the previous code was removing any/all docker. 
  *       Now removing previous docker of the same branch, so that the other branch failed docker should not be removed. It also 
  *    acts as clean-up for previous docker remove failure.
+ * 2. Feature 7829 : Mrityunjay Yadav, Jayant Madavi: MY00514913@techmahindra.com : 19-Aug-2019 : Added a parameters & function to invoke Robot test.
  */
+
 properties([
     parameters([
         string(defaultValue: env.GERRIT_BRANCH, description: '', name: 'GERRIT_BRANCH'),
@@ -33,7 +35,7 @@ properties([
         string(defaultValue: '', description: '', name: 'UPSTREAM_JOB_NAME'),
         string(defaultValue: '', description: '', name: 'UPSTREAM_JOB_NUMBER'),
         string(defaultValue: '', description: '', name: 'UPSTREAM_JOB_NUMBER'),
-        string(defaultValue: 'dpkg1', description: '', name: 'GPG_KEY_NAME'),
+        string(defaultValue: 'OSMETSI', description: '', name: 'GPG_KEY_NAME'),
         string(defaultValue: 'artifactory-osm', description: '', name: 'ARTIFACTORY_SERVER'),
         string(defaultValue: 'osm-stage_4', description: '', name: 'DOWNSTREAM_STAGE_NAME'),
         string(defaultValue: 'releasesix-daily', description: '', name: 'DOCKER_TAG'),
@@ -47,6 +49,9 @@ properties([
         booleanParam(defaultValue: true, description: '', name: 'DO_DOCKERPUSH'),
         booleanParam(defaultValue: false, description: '', name: 'SAVE_ARTIFACTS_OVERRIDE'),
         string(defaultValue: '/home/jenkins/hive/openstack-etsi.rc', description: '', name: 'HIVE_VIM_1'),
+        booleanParam(defaultValue: true, description: '', name: 'DO_ROBOT'),
+        string(defaultValue: 'sanity', description: 'smoke/vim/sanity/comprehensive are the options', name: 'TEST_NAME'),
+        string(defaultValue: '/home/jenkins/hive/robot-systest.cfg', description: '', name: 'ROBOT_VIM'),
     ])
 ])
 
@@ -70,6 +75,30 @@ def run_systest(stackName,tagName,testName,envfile=null) {
     junit  '*.xml'
 }
 
+def run_robot_systest(stackName,tagName,testName,envfile=null) {
+    tempdir = sh(returnStdout: true, script: "mktemp -d").trim()
+    if ( !envfile )
+    {
+        sh(script: "touch ${tempdir}/env")
+        envfile="${tempdir}/env"
+    }
+    sh "docker run --network net${stackName} --env-file ${envfile} -v ${tempdir}:/usr/share/osm-devops/robot-systest/reports opensourcemano/osmclient:${tagName} bash -C /usr/share/osm-devops/robot-systest/run_test.sh --do_install -t ${testName}"
+    sh "cp ${tempdir}/* ."
+    outputDirectory = sh(returnStdout: true, script: "pwd").trim()
+    println ("Present Directory is : ${outputDirectory}")
+    step([
+        $class : 'RobotPublisher',
+        outputPath : "${outputDirectory}",
+        outputFileName : "*.xml",
+        disableArchiveOutput : false,
+        reportFileName : "report.html",
+        logFileName : "log.html",
+        passThreshold : 80,
+        unstableThreshold: 60.0,
+        otherFiles : "*.png",
+    ])
+}
+
 node("${params.NODE}") {
 
     sh 'env'
@@ -278,8 +307,12 @@ node("${params.NODE}") {
             if ( params.DO_STAGE_4 ) {
                 // override stage_archive to only archive on stable
                 stage_archive = false
-                stage("stage_4") {
-                    run_systest(container_name,container_name,"openstack_stage_4",params.HIVE_VIM_1)
+                stage("System Integration Test") {
+                    if ( params.DO_ROBOT ) {
+                        run_robot_systest(container_name,container_name,params.TEST_NAME,params.ROBOT_VIM)
+                    } else {
+                        run_systest(container_name,container_name,"openstack_stage_4",params.HIVE_VIM_1)
+                    }
 
                     if ( ! currentBuild.result.equals('UNSTABLE') ) {
                         stage_archive = keep_artifacts
@@ -314,8 +347,6 @@ node("${params.NODE}") {
             currentBuild.result = 'FAILURE'
         }
         finally {
-
-
             if ( params.DO_INSTALL ) {
                 if (error) {
                     if ( !params.SAVE_CONTAINER_ON_FAIL ) {
diff --git a/robot-systest/README_Robot_Test.md b/robot-systest/README_Robot_Test.md
new file mode 100644 (file)
index 0000000..7067946
--- /dev/null
@@ -0,0 +1,86 @@
+<!--
+Copyright 2019 Tech Mahindra Limited
+
+All Rights Reserved.
+
+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.
+-->
+
+
+# Step to run robot framework test standalone linux environment
+
+All installation commands run using root user(`sudo su`)
+## Step 1: Install python packages
+Install below python packages using pip
+>pip install python-magic pyangbind haikunator requests pyvcloud progressbar pathlib robotframework robotframework-seleniumlibrary robotframework-requests
+
+## Step 2: Install linux packages
+Install below linux packages
+>curl http://osm-download.etsi.org/repository/osm/debian/ReleaseSIX/OSM%20ETSI%20Release%20Key.gpg | apt-key add -
+
+>add-apt-repository -y "deb http://osm-download.etsi.org/repository/osm/debian/ReleaseSIX stable devops osmclient IM" && apt update
+
+>curl -sS -o - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
+
+>echo "deb [arch=amd64]  http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list
+
+> apt-get install -y python-osmclient python-osm-im google-chrome-stable chromium-chromedriver
+
+>./git-repo/devops/tools/OVF_converter/install.sh
+
+## Step 3: checkout robot seed code
+Checkout devops from gerrit
+> git clone "https://osm.etsi.org/gerrit/osm/devops"
+
+If robot seed code not merged to to master, pull it
+> git pull "https://osm.etsi.org/gerrit/osm/devops" refs/changes/52/7852/4
+
+## Step 4: Set environmet
+for build test need to create env-file and provide below details and for Standalone testing export them
+```
+export OSM_HOSTNAME=<OSM server IP>
+```
+
+OpenStack Details
+```
+export OS_AUTH_URL=<auth url>
+export OS_PASSWORD=<password>
+export OS_PROJECT_NAME=<project name>
+export OS_VIM_CONFIG=<config value>
+```
+
+VCD Details
+```
+export VCD_AUTH_URL=<VCD auth url>
+export VCD_USERNAME=<VCD username>
+export VCD_PASSWORD=<VCD password>
+export VCD_TENANT_NAME=<VCD Tenant name>
+export VCD_ORGANIZATION=<VCD Org name>
+export VCD_VIM_CONFIG=<config value>
+```
+
+Note:- Optional
+```
+export NS_CONFIG=<NS Config Details>
+e.g. export NS_CONFIG="'{vld: [ {name: mgmtnet, vim-network-name: mgmt}]}'"
+```
+
+## Step 5: Run Test
+There are two ways to run the test-case:
+* use `devops/robot-systest/run_test.sh` file and provide test-name(vim/smoke/sanity/comprehensive).
+  > ./devops/robot-systest/run_test.sh -t smoke
+
+* use `robot` command
+  > robot -d path/to/report/dir -i test-tag-to-be-included -e test-tag-to-be-excluded path/to/testsuiet
+  
+  > robot -d devops/robot-systest/reports -i comprehensive devops/robot-systest/testsuite
\ No newline at end of file
diff --git a/robot-systest/lib/api/common.robot b/robot-systest/lib/api/common.robot
new file mode 100644 (file)
index 0000000..4724016
--- /dev/null
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com
+##
+
+
+*** Variables ***
+${token}=  ${EMPTY}
+${HOST}=  ${EMPTY}
+
+
+*** Keywords ***
+Get Auth Token
+    [Tags]  auth_token
+
+    ${nbi_host}=    Get Environment Variable    OSM_HOSTNAME
+    ${passed}=    Run Keyword And Return Status    Should Contain    ${nbi_host}    :
+    Run Keyword If    ${passed}    Set Dockerized Host    ${nbi_host}
+    ...    ELSE    Set Standalone Host    ${nbi_host}
+
+    Create Session    osmhit    ${HOST}    verify=${FALSE}    debug=1    headers=${HEADERS}
+
+    Log Many    ${auth_token_uri}    @{data}    ${data}
+
+    ${resp}=    Post Request    osmhit    ${auth_token_uri}    data=${data}
+    log    ${resp}
+
+    Pass Execution If   ${resp.status_code} in ${success_status_code_list}   Get Auth Token completed
+
+    ${content}=     To Json   ${resp.content}
+    ${t}=    Get From Dictionary       ${content}          _id
+
+    Set Suite Variable     ${token}   ${t}
+
+
+Set Dockerized Host
+    [Arguments]  ${env_host}
+
+    Set Suite Variable     ${HOST}   https://${env_host}
+
+
+Set Standalone Host
+    [Arguments]  ${env_host}
+
+    Set Suite Variable     ${HOST}   https://${env_host}:9999
diff --git a/robot-systest/lib/api/vim_lib.robot b/robot-systest/lib/api/vim_lib.robot
new file mode 100644 (file)
index 0000000..a52354f
--- /dev/null
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-sep-2019
+##
+
+
+*** Keywords ***
+Create Vim
+    [Arguments]  ${vim_name}     ${account_type}     ${auth_url}     ${user}     ${password}     ${tenant}       ${description}
+
+    &{request_data}=        Create Dictionary      vim_user=${user}    vim_password=${password}    vim_url=${auth_url}     vim_tenant_name=${tenant}   vim_type=${account_type}    description=${description}  name=${vim_name}
+
+    &{headers}=    Create Dictionary     Authorization=Bearer ${token}      Content-Type=application/json   Accept=application/json
+
+    Create Session    osmvim    ${HOST}    verify=${FALSE}    headers=${headers}
+
+    LOG   ${request_data}
+    ${res}=     Post Request    osmvim  ${create_vim_uri}   data=${request_data}
+    log    ${res.content}
+    Pass Execution If   ${res.status_code} in ${success_status_code_list}   Create Vim Request completed
+    Get Vim ID      ${res.content}
+
+
+Delete Vim
+    [Arguments]  ${vim_id}
+
+    ${uri} =   Catenate        SEPARATOR=/     ${create_vim_uri}      ${vim_id}
+    ${resp}=    Delete Request   osmvim   ${uri}
+
+    log   ${resp.content}
+    Pass Execution If      ${resp.status_code} in ${success_status_code_list}   Delete Vim Request completed
+
+
+Get Vim ID
+    [Arguments]  ${res}
+
+#    log to console      ${res}
+    ${content}=     To Json     ${res}
+    ${id}=      Get From Dictionary     ${content}         id
+    Set Suite Variable     ${vim_id}   ${id}
+    log   Vim Id is ${vim_id}
diff --git a/robot-systest/lib/cli/ns_lib.robot b/robot-systest/lib/cli/ns_lib.robot
new file mode 100644 (file)
index 0000000..e3e3a02
--- /dev/null
@@ -0,0 +1,129 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-aug-2019 : Improvement to the code, robot framework initial seed code.
+##
+
+
+*** Variables ***
+${success_return_code}    0
+${ns_launch_max_wait_time}    5min
+${ns_launch_pol_time}    30sec
+${ns_delete_max_wait_time}    1min
+${ns_delete_pol_time}    15sec
+
+
+*** Keywords ***
+Get NS List
+    [Documentation]  Get ns instance list
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm ns-list
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}   ${success_return_code}
+
+
+Launch Network Services and Return
+    [Arguments]  ${vim_name}
+       
+       Should Not Be Empty    ${nsd_ids}    There are no NS descriptors to launch the NS
+    :FOR    ${nsd}    IN    @{nsd_ids}
+    \    ${ns_name}=    GENERATE NAME
+    \    Append To List     ${ns_ids}       ${ns_name}
+    \    Create Network Service    ${nsd}   ${vim_name}    ${ns_name}
+    \    Delete NS   ${ns_name}
+
+       
+Create Network Service
+    [Documentation]  Create ns at osm
+    [Arguments]  ${nsd}   ${vim_name}    ${ns_name}
+
+    ${ns_config}=   Get Environment Variable    NS_CONFIG    ${EMPTY}
+       Run Keyword If   ${ns_config}!='${EMPTY}'   Create Network Service With Config    ${nsd}    ${vim_name}    ${ns_name}    ${ns_config}
+       ...    ELSE    Create Network Service Without Config    ${nsd}   ${vim_name}    ${ns_name}
+       
+    WAIT UNTIL KEYWORD SUCCEEDS     ${ns_launch_max_wait_time}   ${ns_launch_pol_time}   Check For NS Instance To Configured   ${ns_name}
+    Check For NS Instance For Failure    ${ns_name}
+       
+
+Create Network Service Without Config
+    [Documentation]  Create ns at osm
+    [Arguments]  ${nsd}   ${vim_name}    ${ns_name}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm ns-create --ns_name ${ns_name} --nsd_name ${nsd} --vim_account ${vim_name}
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}   ${success_return_code}
+
+
+Create Network Service With Config
+    [Documentation]  Create ns at osm
+    [Arguments]  ${nsd}   ${vim_name}    ${ns_name}    ${ns_config}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm ns-create --ns_name ${ns_name} --nsd_name ${nsd} --vim_account ${vim_name} --config ${ns_config}
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}   ${success_return_code}
+
+       
+Delete NS
+    [Documentation]  Delete ns
+    [Arguments]  ${ns}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm ns-delete ${ns}
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}   ${success_return_code}
+
+    WAIT UNTIL KEYWORD SUCCEEDS  ${ns_delete_max_wait_time}   ${ns_delete_pol_time}   Check For NS Instance To Be Delete   ${ns}
+
+
+Check For NS Instance To Configured
+    [Arguments]  ${ns_name}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm ns-list --filter name="${ns_name}"
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}   ${success_return_code}
+    Should Contain Any      ${stdout}   configured    failed
+
+
+Check For NS Instance For Failure
+    [Arguments]  ${ns_name}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm ns-list --filter name="${ns_name}"
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}   ${success_return_code}
+    Should Not Contain      ${stdout}   failed
+
+
+Check For NS Instance To Be Delete
+    [Arguments]  ${ns}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm ns-list
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}   ${success_return_code}
+    Should Not Contain      ${stdout}   ${ns}
+
+
+Force Delete NS
+    [Documentation]  Forcely Delete ns
+    [Arguments]  ${ns}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm ns-delete ${ns}
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}   ${success_return_code}
+    WAIT UNTIL KEYWORD SUCCEEDS    ${ns_delete_max_wait_time}   ${ns_delete_pol_time}   Check For NS Instance To Be Delete   ${ns}
diff --git a/robot-systest/lib/cli/nsd_lib.robot b/robot-systest/lib/cli/nsd_lib.robot
new file mode 100644 (file)
index 0000000..6a4ccbf
--- /dev/null
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-sep-2019
+##
+
+*** Variables ***
+${success_return_code}    0
+${delete_max_wait_time}    1min
+${delete_pol_time}    15sec
+
+
+*** Keywords ***
+Get NSDs List
+    [Documentation]  Get nsds list
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm nsd-list
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}     ${success_return_code}
+
+
+Create NSD
+    [Documentation]  Create nsd at osm
+    [Arguments]  ${nsd_pkg}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm nsd-create ${nsd_pkg}
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}     ${success_return_code}
+    [Return]  ${stdout}
+
+
+Delete NSD
+    [Documentation]  Delete nsd
+    [Arguments]  ${nsd_id}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm nsd-delete ${nsd_id}
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}     ${success_return_code}
+    WAIT UNTIL KEYWORD SUCCEEDS    ${delete_max_wait_time}   ${delete_pol_time}   Check For NSD   ${nsd_id}
+
+
+Check For NSD
+    [Arguments]  ${nsd_id}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm nsd-list
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}     ${success_return_code}
+    Should Not Contain      ${stdout}   ${nsd_id}
+
+
+Force Delete NSD
+    [Documentation]  Forcely Delete nsd
+    [Arguments]  ${nsd_id}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm nsd-delete ${nsd_id}
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}   ${success_return_code}
+
+
+Build NS Descriptor
+    [Documentation]  Build NS Descriptor from the descriptor-packages
+    [Arguments]  ${nsd path}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           make -C '${CURDIR}${/}../../..${nsd path}'
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}   ${success_return_code}
diff --git a/robot-systest/lib/cli/sdnc_account_lib.robot b/robot-systest/lib/cli/sdnc_account_lib.robot
new file mode 100644 (file)
index 0000000..3085c1c
--- /dev/null
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+
+*** Variables ***
+${success_return_code}    0
+${name}     "OpenSite"
+${user}     "admin"
+${password}     "admin"
+${ip}      "1.1.1.1"
+${type}     "onos"
+${port}     "5858"
+${dpid}   ""
+
+
+*** Keywords ***
+Create SDNC Account
+    [Documentation]  create new sdnc account
+
+     ${rc}    ${stdout}=      Run and Return RC and Output      osm sdnc-create --name ${name} --type ${type} --ip-address ${ip} --user ${user} --password ${password} --port ${port} --switch_dpid ${dpid}     return_rc=True
+    log  ${rc}
+    log  ${stdout}
+    Should Be Equal As Integers    ${rc}    ${success_return_code}
+
+
+Get SDNC List
+    [Documentation]  Get a sdnc account list
+
+    ${rc}    ${stdout}=      Run and Return RC and Output       osm sdnc-list
+    log     ${stdout}
+
+
+Show SDNC Account
+    [Documentation]  Get sdnc account details
+
+    ${rc}    ${stdout}=      Run and Return RC and Output       osm sdnc-show ${name}     return_rc=True
+    log  ${rc}
+    log  ${stdout}
+    Should Be Equal As Integers    ${rc}    ${success_return_code}
+
+
+Delete SDNC Account
+    [Documentation]  Get sdnc account details
+
+    ${rc}    ${stdout}=      Run and Return RC and Output       osm sdnc-delete ${name}     return_rc=True
+    log  ${rc}
+    log  ${stdout}
+    Should Be Equal As Integers    ${rc}    ${success_return_code}
\ No newline at end of file
diff --git a/robot-systest/lib/cli/vim_account_lib.robot b/robot-systest/lib/cli/vim_account_lib.robot
new file mode 100644 (file)
index 0000000..699d199
--- /dev/null
@@ -0,0 +1,115 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-sep-2019
+##
+
+
+*** Variables ***
+${success_return_code}    0
+${name}     "helloworld-os"
+${user}     "robottest"
+${password}     "fred"
+${authurl}      "https://169.254.169.245/"
+${type}     "openstack"
+${desc}     "a test vim"
+${tenant}   "robottest2"
+
+
+*** Keywords ***
+Create Vim Account
+    [Documentation]   Create a new vim account
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm vim-create --name ${name} --user ${user} --password ${password} --auth_url ${authurl} --tenant ${tenant} --account_type ${type} --description ${desc}
+    log  ${stdout}
+    Should Be Equal As Integers        ${rc}    ${success_return_code}
+
+
+Get Vim List
+    [Documentation]  Get a vim account list
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm vim-list
+    log     ${stdout}
+    Log To Console  ${stdout}
+    Should Be Equal As Integers        ${rc}    ${success_return_code}
+
+
+Delete Vim Account
+    [Documentation]  delete vim account details
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm vim-delete ${name}
+    log  ${stdout}
+    Should Be Equal As Integers        ${rc}    ${success_return_code}
+
+
+VIM Setup To Launch Network Services
+    [Documentation]  Setup a VIM to launch network services
+
+    ${vmware_url}=  Get Environment Variable    VCD_AUTH_URL   ${EMPTY}
+    ${openstack_url}=   Get Environment Variable    OS_AUTH_URL   ${EMPTY}
+    ${vmware_vim}=    Run Keyword And Return If   '${vmware_url}'!='${EMPTY}'   Setup Vmware Vim   ${vmware_url}   'vmware'      'pytest system test'
+    ${openstack_vim}=    Run Keyword And Return If   '${openstack_url}'!='${EMPTY}'   Setup Openstack Vim    ${openstack_url}    'openstack'   'pytest system test'
+
+    Log Many   @{vim}
+
+
+Setup Openstack Vim
+    [Documentation]  Openstack Vim Account Setup
+    [Arguments]  ${authurl}  ${type}     ${desc}
+
+    ${user}=  Get Environment Variable    OS_USERNAME   ''
+    ${password}=  Get Environment Variable    OS_PASSWORD   ''
+    ${tenant}=  Get Environment Variable    OS_PROJECT_NAME   ''
+    ${vim-config}=  Get Environment Variable    OS_VIM_CONFIG   ''
+    ${vim_name}=    GENERATE NAME
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm vim-create --name ${vim_name} --user ${user} --password ${password} --auth_url ${authurl} --tenant ${tenant} --account_type ${type} --description ${desc} --config ${vim-config}
+    log  ${stdout}
+    Should Be Equal As Integers    ${rc}    ${success_return_code}
+    Append To List     ${vim}       ${stdout}
+    [Return]  ${stdout}
+
+
+Setup Vmware Vim
+    [Documentation]  Vmware Vim Account Setup
+    [Arguments]  ${authurl}  ${type}     ${desc}
+
+    ${user}=  Get Environment Variable    VCD_USERNAME   ''
+    ${password}=  Get Environment Variable    VCD_PASSWORD   ''
+    ${tenant}=  Get Environment Variable    VCD_TENANT_NAME   ''
+    ${vcd-org}=  Get Environment Variable    VCD_ORGANIZATION   ''
+    ${vim-config}=  Get Environment Variable    VCD_VIM_CONFIG   ''
+    ${vim_name}=    GENERATE NAME
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm vim-create --name ${vim_name} --user ${user} --password ${password} --auth_url ${authurl} --tenant ${tenant} --account_type ${type} --description ${desc} --config ${vim-config}
+    log  ${stdout}
+    Should Be Equal As Integers    ${rc}    ${success_return_code}
+    Append To List     ${vim}       ${stdout}
+    [Return]  ${stdout}
+
+
+Force Delete Vim Account
+    [Documentation]  delete vim account details
+    [Arguments]  ${vim_name}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm vim-delete ${vim_name}
+    log  ${stdout}
+    Should Be Equal As Integers        ${rc}    ${success_return_code}
diff --git a/robot-systest/lib/cli/vnfd_lib.robot b/robot-systest/lib/cli/vnfd_lib.robot
new file mode 100644 (file)
index 0000000..1b99f43
--- /dev/null
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-sep-2019
+##
+
+*** Variables ***
+${success_return_code}    0
+${delete_max_wait_time}    1min
+${delete_pol_time}    15sec
+
+
+*** Keywords ***
+Get VNFDs List
+    [Documentation]  Get vnfds list
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm vnfd-list
+    log     ${stdout}
+    log     ${rc}
+    Should Be Equal As Integers        ${rc}     ${success_return_code}
+
+
+Create VNFD
+    [Documentation]  Create vnfd at osm
+    [Arguments]  ${vnfd_pkg}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm vnfd-create ${vnfd_pkg}
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}     ${success_return_code}
+    [Return]  ${stdout}
+
+
+Delete VNFD
+    [Documentation]  Delete vnfd
+    [Arguments]  ${vnfd_id}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm vnfd-delete ${vnfd_id}
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}     ${success_return_code}
+    WAIT UNTIL KEYWORD SUCCEEDS    ${delete_max_wait_time}   ${delete_pol_time}   Check For VNFD   ${vnfd_id}
+
+
+Check For VNFD
+    [Arguments]  ${vnfd_id}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm vnfd-list
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}     ${success_return_code}
+    Should Not Contain      ${stdout}   ${vnfd_id}
+
+
+Force Delete VNFD
+    [Documentation]  Forcely Delete vnfd
+    [Arguments]  ${vnfd_id}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           osm vnfd-delete ${vnfd_id}
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}     ${success_return_code}
+
+
+Build VNF Descriptor
+    [Documentation]  Build VNF Descriptor from the descriptor-packages
+    [Arguments]  ${vnfd path}
+
+    ${rc}   ${stdout}=      Run and Return RC and Output           make -C '${CURDIR}${/}../../..${vnfd path}'
+    log     ${stdout}
+    Should Be Equal As Integers        ${rc}     ${success_return_code}
diff --git a/robot-systest/lib/client_lib/client_lib.py b/robot-systest/lib/client_lib/client_lib.py
new file mode 100644 (file)
index 0000000..c9390ae
--- /dev/null
@@ -0,0 +1,69 @@
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+
+from osmclient import client
+from robot.api import logger
+import json
+
+
+class ClientLib:
+    def __init__(self, host="127.0.0.1", user=None, password=None, project=None):
+
+        kwargs = {}
+        if user is not None:
+            kwargs['user'] = user
+        if password is not None:
+            kwargs['password'] = password
+        if project is not None:
+            kwargs['project'] = project
+        self.client = client.Client(host=host, sol005=True, **kwargs)
+
+    def get_vim_list(self):
+        resp = self.client.vim.list()
+        logger.info('VIM List: {}'.format(resp))
+        return json.dumps(resp)
+
+    def create_vim_account(self, name, vim_type, user, password, auth_url, tenant, desc='', config=None):
+        vim_access = {}
+        if config is not None:
+            vim_access['config'] = config
+        vim_access['vim-type'] = vim_type
+        vim_access['vim-username'] = user
+        vim_access['vim-password'] = password
+        vim_access['vim-url'] = auth_url
+        vim_access['vim-tenant-name'] = tenant
+        vim_access['description'] = desc
+
+        resp = self.client.vim.create(name, vim_access)
+        logger.info('Create VIM Account: {}'.format(resp))
+        return json.dumps(resp)
+
+    def delete_vim_account(self, name):
+        resp = self.client.vim.delete(name)
+        return json.dumps(resp)
+
+    def get_vnfd_list(self):
+        resp = self.client.vnfd.list()
+        logger.info('VNF Descriptor List: {}'.format(resp))
+        return json.dumps(resp)
+
+    def get_nsd_list(self):
+        resp = self.client.nsd.list()
+        logger.info('NS Descriptor List: {}'.format(resp))
+        return json.dumps(resp)
diff --git a/robot-systest/lib/custom_lib.py b/robot-systest/lib/custom_lib.py
new file mode 100644 (file)
index 0000000..5eb162f
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-aug-2019 : Improvement to the code, robot framework initial seed code.
+##
+
+
+from haikunator import Haikunator
+
+
+def generate_name():
+    haikunator = Haikunator()
+    name = haikunator.haikunate(delimiter='_', token_length=2)
+    return name
diff --git a/robot-systest/lib/gui/login_gui.robot b/robot-systest/lib/gui/login_gui.robot
new file mode 100644 (file)
index 0000000..c125664
--- /dev/null
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-aug-2019 : Improvement to the code, robot framework initial seed code.
+##
+
+
+*** Variables ***
+${DESIRED_CAPABILITIES}    desired_capabilities
+${BROWSER}        Chrome
+${DELAY}          0
+${VALID USER}     admin
+${VALID PASSWORD}    admin
+${LOGIN URL}      /auth/
+${WELCOME URL}    /projects/
+${NS LIST URL}    /packages/ns/list
+${VNF LIST URL}    /packages/vnf/list
+
+
+*** Keywords ***
+Set Server URL
+    ${env_host}=    Get Environment Variable    OSM_HOSTNAME
+    ${passed}=    Run Keyword And Return Status    Should Contain    ${env_host}    :
+    Run Keyword If    ${passed}    Set Dockerized Host
+    ...    ELSE    Set Standalone Host    ${env_host}
+
+
+Open Browser To Login Page
+    ${chrome_options} =     Evaluate    sys.modules['selenium.webdriver'].ChromeOptions()    sys, selenium.webdriver
+    Call Method    ${chrome_options}   add_argument    headless
+    Call Method    ${chrome_options}   add_argument    disable-gpu
+    Call Method    ${chrome_options}   add_argument    no-sandbox
+    ${options}=     Call Method     ${chrome_options}    to_capabilities
+    Open Browser    ${SERVER}${LOGIN URL}    ${BROWSER}    desired_capabilities=${options}
+    Maximize Browser Window
+    Set Selenium Speed    ${DELAY}
+    Login Page Should Be Open
+
+
+Login Page Should Be Open
+    Element Text Should Be    //*[@id="main_content"]/div/div[2]/p    Sign in to start your session
+
+
+Enter Credentials
+    [Arguments]    ${username}    ${password}
+    Input Text    name:username    ${username}
+    Input Password    name:password    ${password}
+
+
+Submit Credentials
+    Click Button    //*[@id="main_content"]/div/div[2]/form/div[3]/div[2]/button
+
+
+Home Page Should Be Open
+    Location Should Be    ${SERVER}${WELCOME URL}
+#    Element Should Contain    id:title_header    6e3a8415-9014-4100-9727-90e0150263be    ignore_case=True
+    Element Attribute Value Should Be    //*[@id="main_content"]/div/div[2]/div[1]/div[1]/div/a    href    ${SERVER}${NS LIST URL}
+    Element Attribute Value Should Be    //*[@id="main_content"]/div/div[2]/div[1]/div[2]/div/a    href    ${SERVER}${VNF LIST URL}
+
+
+Set Dockerized Host
+
+    Set Suite Variable     ${SERVER}   http://light-ui
+
+
+Set Standalone Host
+    [Arguments]  ${env_host}
+
+    Set Suite Variable     ${SERVER}   http://${env_host}
diff --git a/robot-systest/resource/api/common.robot b/robot-systest/resource/api/common.robot
new file mode 100644 (file)
index 0000000..9342316
--- /dev/null
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com
+##
+
+
+*** Variables ***
+&{HEADERS}     Content-Type=application/json       Accept=application/json
+&{data}        username=admin      password=admin      project-id=admin
+@{success_status_code_list}     200     201     202    204
+
+${descriptor_content_type_gzip}   application/gzip
+
+${auth_token_uri}   /osm/admin/v1/tokens
+
+${get_all_vnfd_uri}   /osm/vnfpkgm/v1/vnf_packages
+${create_vnfd_uri}   /osm/vnfpkgm/v1/vnf_packages_content
+${delete_vnfd_uri}   /osm/vnfpkgm/v1/vnf_packages
+
+${get_all_nsd_uri}   /osm/nsd/v1/ns_descriptors
+${create_nsd_uri}   /osm/nsd/v1/ns_descriptors_content
+${delete_nsd_uri}   /osm/nsd/v1/ns_descriptors
+
+${base_ns_uri}   /osm/nslcm/v1/ns_instances_content
+${create_ns_uri}   /osm/nslcm/v1/ns_instances_content
+
+${create_vim_uri}   /osm/admin/v1/vim_accounts
diff --git a/robot-systest/resource/api/variables.py b/robot-systest/resource/api/variables.py
new file mode 100644 (file)
index 0000000..a97763a
--- /dev/null
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-sep-2019
+##
+
+
+# Create/Delete Vim Account
+vim_name = 'API-TEST-VIM'
+account_type = 'openstack'
+auth_url = 'http://127.0.0.1:5000/v3'
+user = 'admin'
+password = 'admin'
+tenant = 'admin'
+description = 'Test OpenStack Vim Account'
diff --git a/robot-systest/resource/cli/hackfest_basic_ns_data.py b/robot-systest/resource/cli/hackfest_basic_ns_data.py
new file mode 100644 (file)
index 0000000..8b8054b
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-aug-2019 : Improvement to the code, robot framework initial seed code.
+##
+
+
+# VNFD Details
+vnfdPckgPath = "/descriptor-packages/vnfd/hackfest_basic_vnf"
+vnfdPckg = '/build/hackfest_basic_vnf.tar.gz'
+
+# NSD Details
+nsdPckgPath = "/descriptor-packages/nsd/hackfest_basic_ns"
+nsdPckg = '/build/hackfest_basic_ns.tar.gz'
diff --git a/robot-systest/resource/cli/hackfest_cloudinit_ns_data.py b/robot-systest/resource/cli/hackfest_cloudinit_ns_data.py
new file mode 100644 (file)
index 0000000..d725a36
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-aug-2019 : Improvement to the code, robot framework initial seed code.
+##
+
+
+# VNFD Details
+vnfdPckgPath = "/descriptor-packages/vnfd/hackfest_cloudinit_vnf"
+vnfdPckg = '/build/hackfest_cloudinit_vnf.tar.gz'
+
+# NSD Details
+nsdPckgPath = "/descriptor-packages/nsd/hackfest_cloudinit_ns"
+nsdPckg = '/build/hackfest_cloudinit_ns.tar.gz'
diff --git a/robot-systest/resource/cli/hackfest_epa_ns_data.py b/robot-systest/resource/cli/hackfest_epa_ns_data.py
new file mode 100644 (file)
index 0000000..8975e31
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-aug-2019 : Improvement to the code, robot framework initial seed code.
+##
+
+
+# VNFD Details
+vnfdPckgPath = "/descriptor-packages/vnfd/hackfest_epasriov_vnf"
+vnfdPckg = '/build/hackfest_epasriov_vnf.tar.gz'
+
+# NSD Details
+nsdPckgPath = "/descriptor-packages/nsd/hackfest_epasriov_ns"
+nsdPckg = '/build/hackfest_epasriov_ns.tar.gz'
diff --git a/robot-systest/resource/cli/hackfest_multivdu_ns_data.py b/robot-systest/resource/cli/hackfest_multivdu_ns_data.py
new file mode 100644 (file)
index 0000000..5ecb9e8
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-aug-2019 : Improvement to the code, robot framework initial seed code.
+##
+
+
+# VNFD Details
+vnfdPckgPath = "/descriptor-packages/vnfd/hackfest_multivdu_vnf"
+vnfdPckg = '/build/hackfest_multivdu_vnf.tar.gz'
+
+# NSD Details
+nsdPckgPath = "/descriptor-packages/nsd/hackfest_multivdu_ns"
+nsdPckg = '/build/hackfest_multivdu_ns.tar.gz'
diff --git a/robot-systest/resource/cli/hackfest_simplecharm_ns_data.py b/robot-systest/resource/cli/hackfest_simplecharm_ns_data.py
new file mode 100644 (file)
index 0000000..5ffcd35
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-aug-2019 : Improvement to the code, robot framework initial seed code.
+##
+
+
+# VNFD Details
+vnfdPckgPath = "/descriptor-packages/vnfd/hackfest_simplecharm_vnf"
+vnfdPckg = '/build/hackfest_simplecharm_vnf.tar.gz'
+
+# NSD Details
+nsdPckgPath = "/descriptor-packages/nsd/hackfest_simplecharm_ns"
+nsdPckg = '/build/hackfest_simplecharm_ns.tar.gz'
diff --git a/robot-systest/resource/cli/test_vnf_data.py b/robot-systest/resource/cli/test_vnf_data.py
new file mode 100644 (file)
index 0000000..02ee065
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com
+##
+
+
+# VNFD Details
+vnfdPckgPath = "/descriptor-packages/vnfd/cirros_vnf"
+vnfdPckg = '/build/cirros_vnf.tar.gz'
+
+# NSD Details
+nsdPckgPath = "/descriptor-packages/nsd/cirros_ns"
+nsdPckg = '/build/cirros_ns.tar.gz'
diff --git a/robot-systest/run_test.sh b/robot-systest/run_test.sh
new file mode 100644 (file)
index 0000000..74f8aa1
--- /dev/null
@@ -0,0 +1,108 @@
+#!/usr/bin/env bash
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+#   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.
+##
+
+## Change log:
+# 1. Feature 7829: Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com : 06-Sep-2019
+# Entry script to start the vim, smoke, openstack_stage_4 and comprehensive test using Robot Framework as a Automation Test Framework
+##
+
+BASEDIR=$(dirname "$0")
+TOPDIR=$(dirname "$BASEDIR")
+DESCRIPTOR_DIR=$TOPDIR/descriptor-packages
+
+
+robot_prerequisite(){
+    echo -e "\nInstalling robot requirements"
+    # installing python packages
+    pip install haikunator requests robotframework robotframework-seleniumlibrary robotframework-requests
+
+    # installing chrome driver and chrome for UI testing
+    curl -sS -o - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
+    echo "deb [arch=amd64]  http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list
+    apt-get update && apt-get -y install google-chrome-stable chromium-chromedriver
+}
+
+while getopts ":t:-:" o; do
+    case "${o}" in
+        t)
+            TEST=${OPTARG}
+            ;;
+        -)
+            [[ "${OPTARG}" == "do_install" ]] && robot_prerequisite && continue
+            ;;
+        \?)
+            echo -e "Invalid option: '-$OPTARG'\n" >&2
+            exit 1
+            ;;
+    esac
+done
+
+if [[ -z $TEST ]]; then
+    printf "Test not provided. \nRunning default test: smoke\n"
+    TEST="smoke"
+fi
+
+if [[ "$TEST" == "vim" ]]; then
+    echo "Robot Framework Vim Test"
+    robot -d $BASEDIR/reports -i vim $BASEDIR/testsuite/
+    exit 0
+elif [[ "$TEST" == "smoke" ]]; then
+    echo "Robot Framework SMOKE test"
+    robot -d $BASEDIR/reports -i smoke $BASEDIR/testsuite/
+    exit 0
+elif [[ "$TEST" == "sanity" ]]; then
+    echo "Robot Framework Cirros VNF Test"
+    mkdir -p $BASEDIR/images/cache
+    if [[ ! -z $OS_AUTH_URL ]]; then
+        (openstack image show cirros-0.3.5-x86_64-disk.img) || (wget -r -nc http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img -O $BASEDIR/images/cache/cirros-0.3.5-x86_64-disk.img && make $BASEDIR/images/cache/cirros-0.3.5-x86_64-disk.img && openstack image create --file $BASEDIR/images/cache/cirros-0.3.5-x86_64-disk.img cirros-0.3.5-x86_64-disk.img)
+    fi
+    if [[ ! -z $VCD_AUTH_URL ]]; then
+#        TODO: Check for image over VIM before downloading
+        if [[ ! -s $BASEDIR/images/cache/cirros-0.3.5-x86_64-disk.img ]]; then
+            wget -r -nc http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img -O $BASEDIR/images/cache/cirros-0.3.5-x86_64-disk.img
+        fi
+        ovf_converter $BASEDIR/images/cache/cirros-0.3.5-x86_64-disk.img -n cirros
+        python $TOPDIR/tools/vmware_ovf_upload.py $VCD_AUTH_URL $VCD_USERNAME $VCD_PASSWORD $VCD_ORGANIZATION $BASEDIR/images/cache/cirros.ovf
+    fi
+    robot -d $BASEDIR/reports -i sanity $BASEDIR/testsuite/
+    exit 0
+elif [[ "$TEST" == "comprehensive" ]]; then
+    echo "Robot Framework Comprehensive Test"
+    mkdir -p $BASEDIR/images/cache
+    if [[ ! -z $OS_AUTH_URL ]]; then
+        (openstack image show ubuntu1604) || (wget -r -nc https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img -O $BASEDIR/images/cache/xenial-server-cloudimg-amd64-disk1.img && make $BASEDIR/images/cache/xenial-server-cloudimg-amd64-disk1.img && openstack image create --file $BASEDIR/images/cache/xenial-server-cloudimg-amd64-disk1.img ubuntu1604)
+        (openstack image show hackfest3-mgmt) || (wget -r -nc https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img -O $BASEDIR/images/cache/xenial-server-cloudimg-amd64-disk1.img && make $BASEDIR/images/cache/xenial-server-cloudimg-amd64-disk1.img && openstack image create --file $BASEDIR/images/cache/xenial-server-cloudimg-amd64-disk1.img hackfest3-mgmt)
+    fi
+    if [[ ! -z $VCD_AUTH_URL ]]; then
+#        TODO: Check for image over VIM before downloading
+        if [[ ! -s $BASEDIR/images/cache/xenial-server-cloudimg-amd64-disk1.img ]]; then
+            wget -r -nc https://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img -O $BASEDIR/images/cache/xenial-server-cloudimg-amd64-disk1.img
+        fi
+        ovf_converter $BASEDIR/images/cache/xenial-server-cloudimg-amd64-disk1.img -n ubuntu1604
+        python $TOPDIR/tools/vmware_ovf_upload.py $VCD_AUTH_URL $VCD_USERNAME $VCD_PASSWORD $VCD_ORGANIZATION $BASEDIR/images/cache/ubuntu1604.ovf
+    fi
+    robot -d $BASEDIR/reports -i comprehensive $BASEDIR/testsuite/
+    exit 0
+else
+    echo "wrong test provided"
+    exit 1
+fi
+
+exit 1
diff --git a/robot-systest/testsuite/api/TS01__Vim_Account.robot b/robot-systest/testsuite/api/TS01__Vim_Account.robot
new file mode 100644 (file)
index 0000000..be04c3f
--- /dev/null
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-aug-2019 : Improvement to the code, robot framework initial seed code.
+##
+
+
+*** Settings ***
+Documentation    Test Suite to create and delete vim account
+Library     Collections
+Library     RequestsLibrary
+Library     OperatingSystem
+Resource    ../../lib/api/common.robot
+Resource    ../../lib/api/vim_lib.robot
+Resource    ../../resource/api/common.robot
+Variables   ../../resource/api/variables.py
+
+Suite Setup     Get Auth Token
+Suite Teardown  Delete All Sessions
+
+
+*** Variables ***
+${vim_id}   ${EMPTY}
+
+
+*** Test Cases ***
+Create Vim Account
+    [Tags]    comprehensive   api_vim_test
+    [Template]  Create Vim
+    ${vim name}     ${account type}     ${auth url}     ${user}     ${password}     ${tenant}       ${description}
+
+
+Delete Vim Account
+    [Tags]    comprehensive   api_vim_test
+    [Template]  Delete Vim
+    ${vim_id}
diff --git a/robot-systest/testsuite/cli/TS008__Test_SDNC.robot b/robot-systest/testsuite/cli/TS008__Test_SDNC.robot
new file mode 100644 (file)
index 0000000..311448c
--- /dev/null
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+
+*** Settings ***
+Documentation    Test suiet to create/delete sdnc account via osmclient
+Library     OperatingSystem
+Library     Collections
+Resource    ../../lib/cli/sdnc_account_lib.robot
+
+
+*** Test Cases ***
+Create SDNC Account Test
+    [Tags]  comprehensive    sdnc
+
+    Create SDNC Account
+
+
+Get SDNC Accounts List Test
+    [Tags]  comprehensive    sdnc
+
+    Get SDNC List
+
+
+Delete SDNC Account Test
+    [Tags]  comprehensive    sdnc
+
+    Delete SDNC Account
diff --git a/robot-systest/testsuite/cli/TS01__Test_VNF.robot b/robot-systest/testsuite/cli/TS01__Test_VNF.robot
new file mode 100644 (file)
index 0000000..08a4e0e
--- /dev/null
@@ -0,0 +1,109 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com : 06-aug-2019
+##
+
+
+*** Settings ***
+Documentation    Test Suite to test basic cirros VNF and NS using osm-client
+Library     OperatingSystem
+Library     String
+Library     Collections
+Resource    ../../lib/cli/vnfd_lib.robot
+Resource    ../../lib/cli/nsd_lib.robot
+Resource    ../../lib/cli/ns_lib.robot
+Resource    ../../lib/cli/vim_account_lib.robot
+Library     ../../lib/custom_lib.py
+Variables   ../../resource/cli/test_vnf_data.py
+
+Suite Teardown     Run Keyword And Ignore Error    Test Cleanup
+
+
+*** Variables ***
+@{vnfd_ids}
+@{nsd_ids}
+@{ns_ids}
+@{vim}
+#${vim_name}     robot_test
+
+
+*** Test Cases ***
+Create VNF Descriptor Test
+    [Tags]    sanity    smoke
+
+    Build VNF Descriptor    ${vnfdPckgPath}
+    ${vnfd_id}=    Create VNFD    '${CURDIR}${/}../../..${vnfdPckgPath}${vnfdPckg}'
+    Append To List     ${vnfd_ids}       ${vnfd_id}
+
+
+Create NS Descriptor Test
+    [Tags]    sanity     smoke
+
+    Build NS Descriptor    ${nsdPckgPath}
+    ${nsd_id}=    Create NSD    '${CURDIR}${/}../../..${nsdPckgPath}${nsdPckg}'
+    Append To List     ${nsd_ids}       ${nsd_id}
+
+
+Network Service Instance Test
+    [Documentation]  Launch and terminate network services
+    [Tags]    sanity
+    [Setup]  VIM Setup To Launch Network Services
+    [Teardown]  Run Keyword And Ignore Error    Network Service Instance Cleanup
+
+    Should Not Be Empty    ${vim}    VIM details not provided
+    :FOR    ${vim_name}    IN    @{vim}
+    \    Launch Network Services and Return    ${vim_name}
+
+
+Delete NS Descriptor Test
+    [Tags]    sanity     smoke
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Delete NSD      ${nsd}
+
+
+Delete VNF Descriptor Test
+    [Tags]    sanity    smoke
+
+    :FOR    ${vnfd}  IN   @{vnfd_ids}
+    \   Delete VNFD     ${vnfd}
+
+
+*** Keywords ***
+Test Cleanup
+    [Documentation]  Test Suit Cleanup: Forcefully delete NSD and VNFD
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Force Delete NSD      ${nsd}
+
+    :FOR    ${vnfd}  IN   @{vnfd_ids}
+    \   Force Delete VNFD     ${vnfd}
+
+
+Network Service Instance Cleanup
+    [Documentation]  Forcefully delete created network service instances and vim account
+
+    :FOR    ${ns}  IN   @{ns_ids}
+    \   Force Delete NS   ${ns}
+
+    :FOR    ${vim_id}  IN   @{vim}
+    \   Force Delete Vim Account    ${vim_id}
diff --git a/robot-systest/testsuite/cli/TS02__Test_Vim.robot b/robot-systest/testsuite/cli/TS02__Test_Vim.robot
new file mode 100644 (file)
index 0000000..18f2a50
--- /dev/null
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com : 06-aug-2019 : Improvement to the code, robot framework initial seed code.
+##
+
+
+*** Settings ***
+Documentation    Test suiet to create/delete vim account via osmclient
+Library     OperatingSystem
+Library     Collections
+Resource    ../../lib/cli/vim_account_lib.robot
+
+
+*** Test Cases ***
+Create Vim Account Test
+    [Tags]  smoke    vim
+
+    Create Vim Account
+
+
+Get Vim Accounts List Test
+    [Tags]  vim
+
+    Get Vim List
+
+
+Delete Vim Account Test
+    [Tags]  smoke    vim
+
+    Delete Vim Account
diff --git a/robot-systest/testsuite/cli/TS03__Hackfest_Basic_NS.robot b/robot-systest/testsuite/cli/TS03__Hackfest_Basic_NS.robot
new file mode 100644 (file)
index 0000000..d55540a
--- /dev/null
@@ -0,0 +1,109 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com : 06-aug-2019
+##
+
+
+*** Settings ***
+Documentation    Test Suite to create hackfest basic nestwork service
+Library     OperatingSystem
+Library     String
+Library     Collections
+Resource    ../../lib/cli/vnfd_lib.robot
+Resource    ../../lib/cli/nsd_lib.robot
+Resource    ../../lib/cli/ns_lib.robot
+Resource    ../../lib/cli/vim_account_lib.robot
+Library     ../../lib/custom_lib.py
+Variables   ../../resource/cli/hackfest_basic_ns_data.py
+
+Suite Teardown     Run Keyword And Ignore Error    Test Cleanup
+
+
+*** Variables ***
+@{vnfd_ids}
+${nsd_id}
+@{nsd_ids}
+@{ns_ids}
+@{vim}
+
+
+*** Test Cases ***
+Create Hackfest Basic VNF Descriptor
+    [Tags]   comprehensive   hackfest_basic_ns
+
+    Build VNF Descriptor    ${vnfdPckgPath}
+    ${vnfd_id}=    Create VNFD    '${CURDIR}${/}../../..${vnfdPckgPath}${vnfdPckg}'
+    Append To List     ${vnfd_ids}       ${vnfd_id}
+
+
+Create Hackfest Basic NS Descriptor
+    [Tags]   comprehensive   hackfest_basic_ns
+
+    Build NS Descriptor    ${nsdPckgPath}
+    ${nsd_id}=    Create NSD    '${CURDIR}${/}../../..${nsdPckgPath}${nsdPckg}'
+    Append To List     ${nsd_ids}       ${nsd_id}
+
+
+Network Service Instance Test
+    [Documentation]  Launch and terminate network services
+    [Tags]   comprehensive   hackfest_basic_ns
+    [Setup]  VIM Setup To Launch Network Services
+    [Teardown]  Run Keyword And Ignore Error    Network Service Instance Cleanup
+
+    Should Not Be Empty    ${vim}    VIM details not provided
+    :FOR    ${vim_name}    IN    @{vim}
+    \    Launch Network Services and Return    ${vim_name}
+
+
+Delete NS Descriptor Test
+    [Tags]   comprehensive   hackfest_basic_ns
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Delete NSD      ${nsd}
+
+
+Delete VNF Descriptor Test
+    [Tags]   comprehensive   hackfest_basic_ns
+
+    :FOR    ${vnfd_id}  IN   @{vnfd_ids}
+    \   Delete VNFD     ${vnfd_id}
+
+
+*** Keywords ***
+Test Cleanup
+    [Documentation]  Test Suit Cleanup: Forcefully delete NSD and VNFD
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Force Delete NSD      ${nsd_id}
+
+    :FOR    ${vnfd_id}  IN   @{vnfd_ids}
+    \   Force Delete VNFD     ${vnfd_id}
+
+
+Network Service Instance Cleanup
+    [Documentation]  Forcefully delete created network service instances and vim account
+
+    :FOR    ${ns_id}  IN   @{ns_ids}
+    \   Force Delete NS   ${ns_id}
+
+    :FOR    ${vim_id}  IN   @{vim}
+    \   Force Delete Vim Account    ${vim_id}
diff --git a/robot-systest/testsuite/cli/TS04__Hackfest_Simplecharm_NS.robot b/robot-systest/testsuite/cli/TS04__Hackfest_Simplecharm_NS.robot
new file mode 100644 (file)
index 0000000..7439259
--- /dev/null
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com : 06-aug-2019
+##
+
+
+*** Settings ***
+Documentation    Test Suite to create hackfest simplecharm ns
+Library     OperatingSystem
+Library     String
+Library     Collections
+Resource    ../../lib/cli/vnfd_lib.robot
+Resource    ../../lib/cli/nsd_lib.robot
+Resource    ../../lib/cli/ns_lib.robot
+Resource    ../../lib/cli/vim_account_lib.robot
+Library     ../../lib/custom_lib.py
+Variables   ../../resource/cli/hackfest_simplecharm_ns_data.py
+
+Suite Teardown     Run Keyword And Ignore Error    Test Cleanup
+
+
+*** Variables ***
+@{vnfd_ids}
+${nsd_id}
+@{nsd_ids}
+@{ns_ids}
+@{vim}
+${vnfdftpPath}    https://osm-download.etsi.org/ftp/osm-6.0-six/7th-hackfest/packages/hackfest_simplecharm_vnf.tar.gz
+${nsdftpPath}    https://osm-download.etsi.org/ftp/osm-6.0-six/7th-hackfest/packages/hackfest_simplecharm_ns.tar.gz
+
+
+*** Test Cases ***
+Create Hackfest Simple Charm VNF Descriptor
+    [Tags]   hackfest_simplecharm    comprehensive
+
+    #Build VNF Descriptor    ${vnfdPckgPath}
+    #Workarround for charm build issue
+    ${rc}   ${stdout}=      Run and Return RC and Output           wget -P '${CURDIR}${/}../../..${vnfdPckgPath}${/}build/' ${vnfdftpPath}
+    ${vnfd_id}=    Create VNFD    '${CURDIR}${/}../../..${vnfdPckgPath}${vnfdPckg}'
+    Append To List     ${vnfd_ids}       ${vnfd_id}
+
+
+Create Hackfest Simple Charm NS Descriptor
+    [Tags]   hackfest_simplecharm    comprehensive
+
+    #Build NS Descriptor    ${nsdPckgPath}
+       ${rc}   ${stdout}=      Run and Return RC and Output        wget -P '${CURDIR}${/}../../..${nsdPckgPath}${/}build/' ${nsdftpPath}
+    ${nsd_id}=    Create NSD    '${CURDIR}${/}../../..${nsdPckgPath}${nsdPckg}'
+    Append To List     ${nsd_ids}       ${nsd_id}
+
+
+Network Service Instance Test
+    [Documentation]  Launch and terminate network services
+    [Tags]   hackfest_simplecharm    comprehensive
+    [Setup]  VIM Setup To Launch Network Services
+    [Teardown]  Run Keyword And Ignore Error    Network Service Instance Cleanup
+
+    Should Not Be Empty    ${vim}    VIM details not provided
+    :FOR    ${vim_name}    IN    @{vim}
+    \    Launch Network Services and Return    ${vim_name}
+
+
+Delete NS Descriptor Test
+    [Tags]   hackfest_simplecharm    comprehensive
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Delete NSD      ${nsd}
+
+
+Delete VNF Descriptor Test
+    [Tags]   hackfest_simplecharm    comprehensive
+
+    :FOR    ${vnfd_id}  IN   @{vnfd_ids}
+    \   Delete VNFD     ${vnfd_id}
+
+
+*** Keywords ***
+Test Cleanup
+    [Documentation]  Test Suit Cleanup: Forcefully delete NSD and VNFD
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Force Delete NSD      ${nsd_id}
+
+    :FOR    ${vnfd_id}  IN   @{vnfd_ids}
+    \   Force Delete VNFD     ${vnfd_id}
+
+
+Network Service Instance Cleanup
+    [Documentation]  Forcefully delete created network service instances and vim account
+
+    :FOR    ${ns_id}  IN   @{ns_ids}
+    \   Force Delete NS   ${ns_id}
+
+    :FOR    ${vim_id}  IN   @{vim}
+    \   Force Delete Vim Account    ${vim_id}
diff --git a/robot-systest/testsuite/cli/TS05__Hackfest_Multivdu_NS.robot b/robot-systest/testsuite/cli/TS05__Hackfest_Multivdu_NS.robot
new file mode 100644 (file)
index 0000000..7fa6c24
--- /dev/null
@@ -0,0 +1,109 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com : 06-aug-2019
+##
+
+
+*** Settings ***
+Documentation    Test Suite to create hackfest multivdu ns
+Library     OperatingSystem
+Library     String
+Library     Collections
+Resource    ../../lib/cli/vnfd_lib.robot
+Resource    ../../lib/cli/nsd_lib.robot
+Resource    ../../lib/cli/ns_lib.robot
+Resource    ../../lib/cli/vim_account_lib.robot
+Library     ../../lib/custom_lib.py
+Variables   ../../resource/cli/hackfest_multivdu_ns_data.py
+
+Suite Teardown     Run Keyword And Ignore Error    Test Cleanup
+
+
+*** Variables ***
+@{vnfd_ids}
+${nsd_id}
+@{nsd_ids}
+@{ns_ids}
+@{vim}
+
+
+*** Test Cases ***
+Create Hackfest Multivdu VNF Descriptor
+    [Tags]   comprehensive   hackfest_multivdu
+
+    Build VNF Descriptor    ${vnfdPckgPath}
+    ${vnfd_id}=    Create VNFD    '${CURDIR}${/}../../..${vnfdPckgPath}${vnfdPckg}'
+    Append To List     ${vnfd_ids}       ${vnfd_id}
+
+
+Create Hackfest Multivdu NS Descriptor
+    [Tags]   comprehensive   hackfest_multivdu
+
+    Build NS Descriptor    ${nsdPckgPath}
+    ${nsd_id}=    Create NSD    '${CURDIR}${/}../../..${nsdPckgPath}${nsdPckg}'
+    Append To List     ${nsd_ids}       ${nsd_id}
+
+
+Network Service Instance Test
+    [Documentation]  Launch and terminate network services
+    [Tags]   comprehensive   hackfest_multivdu
+    [Setup]  VIM Setup To Launch Network Services
+    [Teardown]  Run Keyword And Ignore Error    Network Service Instance Cleanup
+
+    Should Not Be Empty    ${vim}    VIM details not provided
+    :FOR    ${vim_name}    IN    @{vim}
+    \    Launch Network Services and Return    ${vim_name}
+
+
+Delete NS Descriptor Test
+    [Tags]   comprehensive   hackfest_multivdu
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Delete NSD      ${nsd}
+
+
+Delete VNF Descriptor Test
+    [Tags]   comprehensive   hackfest_multivdu
+
+    :FOR    ${vnfd_id}  IN   @{vnfd_ids}
+    \   Delete VNFD     ${vnfd_id}
+
+
+*** Keywords ***
+Test Cleanup
+    [Documentation]  Test Suit Cleanup: Forcefully delete NSD and VNFD
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Force Delete NSD      ${nsd_id}
+
+    :FOR    ${vnfd_id}  IN   @{vnfd_ids}
+    \   Force Delete VNFD     ${vnfd_id}
+
+
+Network Service Instance Cleanup
+    [Documentation]  Forcefully delete created network service instances and vim account
+
+    :FOR    ${ns_id}  IN   @{ns_ids}
+    \   Force Delete NS   ${ns_id}
+
+    :FOR    ${vim_id}  IN   @{vim}
+    \   Force Delete Vim Account    ${vim_id}
diff --git a/robot-systest/testsuite/cli/TS06__Hackfest_Cloudinit_NS.robot b/robot-systest/testsuite/cli/TS06__Hackfest_Cloudinit_NS.robot
new file mode 100644 (file)
index 0000000..a43f3a2
--- /dev/null
@@ -0,0 +1,109 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com : 06-aug-2019
+##
+
+
+*** Settings ***
+Documentation    Test Suite to create hackfest cloudinit ns
+Library     OperatingSystem
+Library     String
+Library     Collections
+Resource    ../../lib/cli/vnfd_lib.robot
+Resource    ../../lib/cli/nsd_lib.robot
+Resource    ../../lib/cli/ns_lib.robot
+Resource    ../../lib/cli/vim_account_lib.robot
+Library     ../../lib/custom_lib.py
+Variables   ../../resource/cli/hackfest_cloudinit_ns_data.py
+
+Suite Teardown     Run Keyword And Ignore Error    Test Cleanup
+
+
+*** Variables ***
+@{vnfd_ids}
+${nsd_id}
+@{nsd_ids}
+@{ns_ids}
+@{vim}
+
+
+*** Test Cases ***
+Create Hackfest Cloudinit VNF Descriptor
+    [Tags]   comprehensive   hackfest_cloudinit
+
+    Build VNF Descriptor    ${vnfdPckgPath}
+    ${vnfd_id}=    Create VNFD    '${CURDIR}${/}../../..${vnfdPckgPath}${vnfdPckg}'
+    Append To List     ${vnfd_ids}       ${vnfd_id}
+
+
+Create Hackfest Cloudinit NS Descriptor
+    [Tags]   comprehensive   hackfest_cloudinit
+
+    Build NS Descriptor    ${nsdPckgPath}
+    ${nsd_id}=    Create NSD    '${CURDIR}${/}../../..${nsdPckgPath}${nsdPckg}'
+    Append To List     ${nsd_ids}       ${nsd_id}
+
+
+Network Service Instance Test
+    [Documentation]  Launch and terminate network services
+    [Tags]   comprehensive   hackfest_cloudinit
+    [Setup]  VIM Setup To Launch Network Services
+    [Teardown]  Run Keyword And Ignore Error    Network Service Instance Cleanup
+
+    Should Not Be Empty    ${vim}    VIM details not provided
+    :FOR    ${vim_name}    IN    @{vim}
+    \    Launch Network Services and Return    ${vim_name}
+
+
+Delete NS Descriptor Test
+    [Tags]   comprehensive   hackfest_cloudinit
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Delete NSD      ${nsd}
+
+
+Delete VNF Descriptor Test
+    [Tags]   comprehensive   hackfest_cloudinit
+
+    :FOR    ${vnfd_id}  IN   @{vnfd_ids}
+    \   Delete VNFD     ${vnfd_id}
+
+
+*** Keywords ***
+Test Cleanup
+    [Documentation]  Test Suit Cleanup: Forcefully delete NSD and VNFD
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Force Delete NSD      ${nsd_id}
+
+    :FOR    ${vnfd_id}  IN   @{vnfd_ids}
+    \   Force Delete VNFD     ${vnfd_id}
+
+
+Network Service Instance Cleanup
+    [Documentation]  Forcefully delete created network service instances and vim account
+
+    :FOR    ${ns_id}  IN   @{ns_ids}
+    \   Force Delete NS   ${ns_id}
+
+    :FOR    ${vim_id}  IN   @{vim}
+    \   Force Delete Vim Account    ${vim_id}
diff --git a/robot-systest/testsuite/cli/TS07__Hackfest_EPA_NS.robot b/robot-systest/testsuite/cli/TS07__Hackfest_EPA_NS.robot
new file mode 100644 (file)
index 0000000..2d8d3be
--- /dev/null
@@ -0,0 +1,109 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Mrityunjay Yadav, Jayant Madavi : MY00514913@techmahindra.com : 06-aug-2019
+##
+
+
+*** Settings ***
+Documentation    Test Suite to create hackfest epa ns
+Library     OperatingSystem
+Library     String
+Library     Collections
+Resource    ../../lib/cli/vnfd_lib.robot
+Resource    ../../lib/cli/nsd_lib.robot
+Resource    ../../lib/cli/ns_lib.robot
+Resource    ../../lib/cli/vim_account_lib.robot
+Library     ../../lib/custom_lib.py
+Variables   ../../resource/cli/hackfest_epa_ns_data.py
+
+Suite Teardown     Run Keyword And Ignore Error    Test Cleanup
+
+
+*** Variables ***
+@{vnfd_ids}
+${nsd_id}
+@{nsd_ids}
+@{ns_ids}
+@{vim}
+
+
+*** Test Cases ***
+Create Hackfest EPA VNF Descriptor
+    [Tags]     hackfest_epa
+
+    Build VNF Descriptor    ${vnfdPckgPath}
+    ${vnfd_id}=    Create VNFD    '${CURDIR}${/}../../..${vnfdPckgPath}${vnfdPckg}'
+    Append To List     ${vnfd_ids}       ${vnfd_id}
+
+
+Create Hackfest EPA NS Descriptor
+    [Tags]     hackfest_epa
+
+    Build NS Descriptor    ${nsdPckgPath}
+    ${nsd_id}=    Create NSD    '${CURDIR}${/}../../..${nsdPckgPath}${nsdPckg}'
+    Append To List     ${nsd_ids}       ${nsd_id}
+
+
+Network Service Instance Test
+    [Documentation]  Launch and terminate network services
+    [Tags]    hackfest_epa
+    [Setup]  VIM Setup To Launch Network Services
+    [Teardown]  Run Keyword And Ignore Error    Network Service Instance Cleanup
+
+    Should Not Be Empty    ${vim}    VIM details not provided
+    :FOR    ${vim_name}    IN    @{vim}
+    \    Launch Network Services and Return    ${vim_name}
+
+
+Delete NS Descriptor Test
+    [Tags]    hackfest_epa
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Delete NSD      ${nsd}
+
+
+Delete VNF Descriptor Test
+    [Tags]    hackfest_epa
+
+    :FOR    ${vnfd_id}  IN   @{vnfd_ids}
+    \   Delete VNFD     ${vnfd_id}
+
+
+*** Keywords ***
+Test Cleanup
+    [Documentation]  Test Suit Cleanup: Forcefully delete NSD and VNFD
+
+    :FOR    ${nsd}  IN   @{nsd_ids}
+    \   Force Delete NSD      ${nsd_id}
+
+    :FOR    ${vnfd_id}  IN   @{vnfd_ids}
+    \   Force Delete VNFD     ${vnfd_id}
+
+
+Network Service Instance Cleanup
+    [Documentation]  Forcefully delete created network service instances and vim account
+
+    :FOR    ${ns_id}  IN   @{ns_ids}
+    \   Force Delete NS   ${ns_id}
+
+    :FOR    ${vim_id}  IN   @{vim}
+    \   Force Delete Vim Account    ${vim_id}
diff --git a/robot-systest/testsuite/client_library/TS01__OSMClient_Library_Test.robot b/robot-systest/testsuite/client_library/TS01__OSMClient_Library_Test.robot
new file mode 100644 (file)
index 0000000..42b455a
--- /dev/null
@@ -0,0 +1,82 @@
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+
+*** Settings ***
+Documentation    Test suite to test osmclient python library
+Library     OperatingSystem
+
+Suite Setup    Setup OSM Client
+
+
+*** Variables ***
+${name}     helloworld-os
+${user}     robottest
+${password}     fred
+${authurl}      https://169.254.169.245/
+${type}     openstack
+${desc}     a test vim
+${tenant}    robottest
+
+
+*** Test Cases ***
+Get VIM Account List Test
+    [Tags]    comprehensive    osmclient_lib
+    [Documentation]    Using python's osmclient library to get vim account list
+
+    ${vim_list}=    osmclient.get_vim_list
+    log to console    ${vim_list}
+    log  ${vim_list}
+
+
+Get VNF Descriptor List Test
+    [Tags]    comprehensive    osmclient_lib
+    [Documentation]    Using python's osmclient library to get vnfd list
+
+    ${vnfd_list}=    osmclient.get_vnfd_list
+    log to console    ${vnfd_list}
+    log  ${vnfd_list}
+
+
+Get NS Descriptor List Test
+    [Tags]    comprehensive    osmclient_lib
+    [Documentation]    Using python's osmclient library to get nsd list
+
+    ${nsd_list}=    osmclient.get_nsd_list
+    log to console    ${nsd_list}
+    log  ${nsd_list}
+
+
+Create Vim Account Test
+    [Tags]    comprehensive    osmclient_lib
+    [Documentation]    Using python's osmclient library to create vim account
+    [Template]    osmclient.create_vim_account
+    ${name}  ${type}  ${user}  ${password}  ${authurl}  ${tenant}  ${desc}
+
+
+Delete Vim Account Test
+    [Tags]    comprehensive    osmclient_lib
+    [Documentation]    Using python's osmclient library to delete vim account
+    osmclient.delete_vim_account    ${name}
+
+
+*** Keywords ***
+Setup OSM Client
+    evaluate    sys.path.append('${CURDIR}${/}../../lib/client_lib')    modules=sys
+    ${host}=    Get Environment Variable    OSM_HOSTNAME    127.0.0.1
+    Import Library    ClientLib    host=${host}    WITH NAME    osmclient
diff --git a/robot-systest/testsuite/gui/TS01__Test_GUI_Login.robot b/robot-systest/testsuite/gui/TS01__Test_GUI_Login.robot
new file mode 100644 (file)
index 0000000..4f20a18
--- /dev/null
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2019 Tech Mahindra Limited
+#
+# All Rights Reserved.
+#
+# 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.
+##
+
+## Change log:
+# 1. Feature 7829: Jayant Madavi, Mrityunjay Yadav : MY00514913@techmahindra.com
+##
+
+
+*** Settings ***
+Documentation    Suite description
+Library          SeleniumLibrary
+Library          OperatingSystem
+Resource         ../../lib/gui/login_gui.robot
+
+
+*** Test Cases ***
+Valid Login
+    [Tags]    comprehensive   gui_login_test
+    [Setup]    Set Server URL
+    Open Browser To Login Page
+    Enter Credentials    admin    admin
+    Submit Credentials
+    Home Page Should Be Open
+    [Teardown]    Close Browser
diff --git a/tools/OVF_converter/Usage.txt b/tools/OVF_converter/Usage.txt
new file mode 100644 (file)
index 0000000..67671b1
--- /dev/null
@@ -0,0 +1,61 @@
+##
+# Copyright 2016-2019 VMware Inc.
+# This file is part of ETSI OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact:  osslegalrouting@vmware.com
+##
+
+The following two tools are provided to help simplify VMware based image
+management:
+
+o  ovf_converter - converts libvirt .qcow2 files to VMware .vmdk format.
+o  ovf_uploader  - uploads .ovf and .vmdk files to vCD, similar to
+                      openstack image upload command.
+
+OVF Converter Usage
+===================
+
+This utility can be used for both VMware Integrated Openstack (VIO) or
+vCloud Director (vCD).  It converts libvirt images, such as files that end
+in .qcow2 or .img to VMware .vmdk format.  Both an .ovf and .vmdk file are
+created and can be used as needed.
+
+OVF Uploader Usage
+==================
+
+This utility is only used for vCD, as there is no equivalent CLI that provides
+the ability to upload images into vCD.  It takes the output OVF from the
+converter and uploads both it and the VMDK file to the vCD catalog.
+
+Examples:
+=========
+
+o  Upload a CentOS .qcow2 file to VIO
+
+   $ ovf_converter CentOS-7-x86_64-GenericCloud.qcow2
+   $ openstack image create --public \
+     --file CentOS-7-x86_64-GenericCloud.vmdk \
+     --disk-format vmdk CentOS-7
+
+o  Upload a CentOS .qcow2 file to vCD
+
+   $ ovf_converter CentOS-7-x86_64-GenericCloud.qcow2
+   $ ovf_uploader -u orgadmin -p password -o osm -l https://vcd \
+     CentOS-7-x86_64-GenericCloud.ovf
+
+Both commands suport -h to display help options.
+
diff --git a/tools/OVF_converter/converter.py b/tools/OVF_converter/converter.py
new file mode 100644 (file)
index 0000000..5f31ed3
--- /dev/null
@@ -0,0 +1,587 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# #
+# Copyright 2016-2017 VMware Inc.
+# This file is part of ETSI OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact:  osslegalrouting@vmware.com
+# #
+
+import logging
+import os
+import subprocess
+import yaml
+from lxml import etree as ET
+
+# file paths
+MODULE_DIR = os.path.dirname(__file__)
+OVF_TEMPLATE_PATH = os.path.join(MODULE_DIR,
+                                 "ovf_template/template.xml")
+IDE_CDROM_XML_PATH = os.path.join(MODULE_DIR,
+                                  "ovf_template/ide_cdrom.xml")
+OS_INFO_FILE_PATH = os.path.join(MODULE_DIR,
+                                 "config/os_type.yaml")
+DISK_CONTROLLER_INFO_FILE_PATH = os.path.join(MODULE_DIR,
+                                              "config/disk_controller.yaml")
+
+# Set logger
+LOG_FILE = os.path.join(MODULE_DIR, "logs/ovf_converter.log")
+os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
+logger = logging.getLogger(__name__)
+hdlr = logging.FileHandler(LOG_FILE)
+formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+hdlr.setFormatter(formatter)
+logger.addHandler(hdlr)
+logger.setLevel(10)
+
+__version__ = "1.2"
+__description__ = "OVF Hardware Version 14 compatible"
+
+
+def get_version(*args, **kwargs):
+    """ get version of this application"""
+    version = str(__version__) + " - " + str(__description__)
+    return version
+
+
+# converter class
+class OVFConverter(object):
+    """ Class to convert input image into OVF format """
+
+    def __init__(self, source_img_path, output_location=None, output_ovf_name=None,
+                 memory=None, cpu=None, disk=None, os_type=None,
+                 disk_controller=None, cdrom=None, hwversion=14):
+        """
+            Constructor to initialize object of class OVFConverter
+            Args:
+            source_img_path - absolute path to source image which will get convert into ovf
+            output_location - location where created OVF will be kept. This location
+                              should have write access. If not given file will get
+                              created at source location  (optional)
+            output_ovf_name - name of output ovf.If not given source image name will
+                              be used (optional)
+            memory -          required memory for VM in MB (optional)
+            cpu -             required number of virtual cpus for VM (optional)
+            disk -            required size of disk for VM in GB (optional)
+            os_type-          required operating system type as specified in user document
+                              (default os type other 32 bit) (optional)
+            disk_controller - required disk controller type
+                              (default controller SCSI with lsilogicsas)
+                              (SATA, IDE, Paravirtual, Buslogic, Lsilogic, Lsilogicsas) (optional)
+            hwversion -       VMware ESXi hardware family version (optional)
+
+            Returns:
+                Nothing.
+        """
+        self.logger = logger
+        self.ovf_template_path = OVF_TEMPLATE_PATH
+
+        self.source_img_path = source_img_path
+        self.source_img_filename, file_extension = os.path.splitext(os.path.basename(self.source_img_path))
+        self.source_img_location = os.path.dirname(self.source_img_path)
+        self.source_format = file_extension[1:]
+
+        self.output_format = "ovf"
+        self.output_ovf_name = output_ovf_name.split('.')[0] if output_ovf_name else self.source_img_filename
+        self.output_location = output_location if output_location else "."
+        self.output_ovf_name_ext = self.output_ovf_name + "." + self.output_format
+        self.output_path = os.path.join(self.output_location, self.output_ovf_name_ext)
+
+        self.output_diskimage_format = "vmdk"
+        self.output_diskimage_name = self.source_img_filename + "." + self.output_diskimage_format
+        self.output_diskimage_path = os.path.join(self.output_location, self.output_diskimage_name)
+
+        self.logger.info("Input parameters to Converter: \n ovf_template_path = {}, \n source_img_path = {}, \n"
+                         "source_img_location ={} , \n source_format = {}, \n source_img_filename = {}".format(
+                             self.ovf_template_path,
+                             self.source_img_path, self.source_img_location,
+                             self.source_format, self.source_img_filename))
+
+        self.logger.info("Output parameters to Converter: \n output_format = {}, \n output_ovf_name = {}, \n"
+                         "output_location ={} , \n output_path = {}, \n output_diskimage_name = {} , \n"
+                         " output_diskimage_path = {} ".format(self.output_format, self.output_ovf_name,
+                                                               self.output_location, self.output_path,
+                                                               self.output_diskimage_name, self.output_diskimage_path))
+
+        self.disk_capacity = 1
+        self.disk_populated_size = 0
+
+        self.vm_name = self.output_ovf_name
+        self.memory = str(memory) if memory is not None else None
+        self.cpu = str(cpu) if cpu is not None else None
+        self.os_type = str(os_type).strip() if os_type else None
+        self.cdrom = cdrom
+        self.hwversion = hwversion
+
+        if self.os_type:
+            self.osID, self.osType = self.__get_osType()
+            if self.osID is None or self.osType is None:
+                error_msg = "ERROR: Invalid input can not find OS type {} ".format(self.os_type)
+                self.__raise_exception(error_msg)
+
+        self.disk_controller = str(disk_controller).strip() if disk_controller else None
+
+        if self.disk_controller:
+            self.disk_controller_info = self.__get_diskcontroller()
+
+            if not self.disk_controller_info:
+                error_msg = "ERROR: Invalid input can not find Disk Controller {} ".format(self.disk_controller)
+                self.__raise_exception(error_msg)
+
+        if disk is not None:
+            # convert disk size from GB to bytes
+            self.disk_size = int(disk) * 1024 * 1024 * 1024
+        else:
+            self.disk_size = None
+
+        self.logger.info("Other input parameters to Converter: \n vm_name = {}, \n memory = {}, \n"
+                         "disk_size ={} \n os type = {} \n disk controller = {}".format(
+                             self.vm_name, self.memory, self.disk_size, self.os_type, self.disk_controller))
+
+        # check access for read input location and write output location return none if no access
+        if not os.access(self.source_img_path, os.F_OK):
+            error_msg = "ERROR: Source image file {} not present".format(self.source_img_path)
+            self.__raise_exception(error_msg, exception_type="IO")
+
+        elif not os.access(self.source_img_path, os.R_OK):
+            error_msg = "ERROR: Cannot read source image file {}".format(self.source_img_path)
+            self.__raise_exception(error_msg, exception_type="IO")
+
+        if not os.access(self.output_location, os.W_OK):
+            error_msg = "ERROR: No write access to location {} to write output OVF ".format(self.output_location)
+            self.__raise_exception(error_msg, exception_type="IO")
+
+    def __get_image_info(self):
+        """
+            Private method to get information about source imager.
+            Args  : None
+            Return : True on success else False
+        """
+        try:
+            print("Getting source image information")
+            command = "qemu-img info \t " + self.source_img_path
+            output, error, returncode = self.__execute_command(command)
+
+            if error or returncode:
+                self.logger.error("ERROR: Error occurred while getting information about source image : {} \n "
+                                  "return code : {} ".format(error, returncode))
+                return False
+
+            elif output:
+                self.logger.info("Get Image Info Output : {} \n ".format(output))
+                split_output = output.decode().split("\n")
+                for line in split_output:
+                    line = line.strip()
+                    if "virtual size" in line:
+                        virtual_size_info = line.split(":")[1].split()
+                        if len(virtual_size_info) == 3 and virtual_size_info[2].strip(")") == "bytes":
+                            self.disk_capacity = int(virtual_size_info[1].strip("("))
+                        else:
+                            self.disk_capacity = self.__convert_size(virtual_size_info[0])
+
+                    elif "disk size" in line:
+                        size = line.split(":")[1].split()[0]
+                        self.disk_populated_size = self.__convert_size(size)
+                    elif "file format" in line:
+                        self.source_format = line.split(":")[1]
+
+                self.logger.info("Updated source image virtual disk capacity : {} ,"
+                                 "Updated source image populated size: {}".format(self.disk_capacity,
+                                                                                  self.disk_populated_size))
+                return True
+        except Exception as exp:
+            error_msg = "ERROR: Error occurred while getting information about source image : {}".format(exp)
+            self.logger.error(error_msg)
+            print(error_msg)
+            return False
+
+    def __convert_image(self):
+        """
+            Private method to convert source disk image into .vmdk disk image.
+            Args  : None
+            Return : True on success else False
+        """
+
+        print("Converting source disk image to .vmdk ")
+
+        command = "qemu-img convert -p -f " + self.source_format + " -O " + self.output_diskimage_format + \
+            " -o subformat=streamOptimized " + self.source_img_path + " " + self.output_diskimage_path
+
+        _, error, returncode = self.__execute_command(command, show_output=True)
+
+        if error or returncode:
+            error_msg = "ERROR: Error occurred while converting source disk image into vmdk: {}\n" + \
+                "return code : {} ".format(error, returncode)
+            self.logger.error(error_msg)
+            print(error_msg)
+            return False
+        else:
+            if os.path.isfile(self.output_diskimage_path):
+                self.logger.info("Successfully converted source image {} into {} \n "
+                                 "return code : {} ".format(self.source_img_path,
+                                                            self.output_diskimage_path,
+                                                            returncode))
+                result = self.__make_image_bootable()
+                if result:
+                    self.logger.info("Made {} bootable".format(self.output_diskimage_path))
+                    print("Output VMDK is at: {}".format(self.output_diskimage_path))
+                    return True
+                else:
+                    self.logger.error("Cannot make {} bootable".format(self.output_diskimage_path))
+                    print("ERROR: Fail to convert source image into .vmdk")
+                    return False
+            else:
+                self.logger.error("Converted vmdk disk file {} is not present \n ".format(
+                    self.output_diskimage_path))
+                print("Fail to convert source image into .vmdk")
+                return False
+
+    def __make_image_bootable(self):
+        """
+            Private method to make source disk image bootable.
+            Args  : None
+            Return : True on success else False
+        """
+        command = "printf '\x03' | dd conv=notrunc of=" + self.output_diskimage_path + "\t bs=1 seek=$((0x4))"
+        output, error, returncode = self.__execute_command(command)
+
+        if error and returncode:
+            error_msg = "ERROR:Error occurred while making source disk image bootable : {} \n "\
+                "return code : {} ".format(error, returncode)
+            self.logger.error(error_msg)
+            print(error_msg)
+            return False
+        else:
+            self.logger.info("Make Image Bootable Output : {} ".format(output))
+            return True
+
+    def __edit_ovf_template(self):
+        """
+            Private method to create new OVF file by editing OVF template
+            Args  : None
+            Return : True on success else False
+        """
+        try:
+            print("Creating OVF")
+            # Read OVF template file
+            OVF_tree = ET.parse(self.ovf_template_path)
+            root = OVF_tree.getroot()
+
+            # Collect namespaces
+            nsmap = {k: v for k, v in root.nsmap.items() if k}
+            nsmap["xmlns"] = "http://schemas.dmtf.org/ovf/envelope/1"
+
+            # Edit OVF template
+            references = root.find('xmlns:References', nsmap)
+            if references is not None:
+                file_tag = references.find('xmlns:File', nsmap)
+                if file_tag is not None:
+                    file_tag.attrib['{' + nsmap['ovf'] + '}href'] = self.output_diskimage_name
+
+            disksection = root.find('xmlns:DiskSection', nsmap)
+            if disksection is not None:
+                diak_tag = disksection.find('xmlns:Disk', nsmap)
+                if diak_tag is not None:
+                    if self.disk_size and self.disk_size > self.disk_capacity:
+                        self.disk_capacity = self.disk_size
+
+                    diak_tag.attrib['{' + nsmap['ovf'] + '}capacity'] = str(self.disk_capacity)
+                    diak_tag.attrib['{' + nsmap['ovf'] + '}populatedSize'] = str(self.disk_populated_size)
+
+            virtuasystem = root.find('xmlns:VirtualSystem', nsmap)
+            if virtuasystem is not None:
+                name_tag = virtuasystem.find('xmlns:Name', nsmap)
+                if name_tag is not None:
+                    name_tag.text = self.vm_name
+
+                if self.os_type is not None:
+                    operatingSystemSection = virtuasystem.find('xmlns:OperatingSystemSection', nsmap)
+                    if self.osID and self.osType:
+                        operatingSystemSection.attrib['{' + nsmap['ovf'] + '}id'] = self.osID
+                        os_discription_tag = operatingSystemSection.find('xmlns:Description', nsmap)
+                        os_discription_tag.text = self.osType
+
+                virtualHardwareSection = virtuasystem.find('xmlns:VirtualHardwareSection', nsmap)
+                system = virtualHardwareSection.find('xmlns:System', nsmap)
+                virtualSystemIdentifier = system.find('vssd:VirtualSystemIdentifier', nsmap)
+                if virtualSystemIdentifier is not None:
+                    virtualSystemIdentifier.text = self.vm_name
+                VirtualSystemType = system.find('vssd:VirtualSystemType', nsmap)
+                if VirtualSystemType is not None:
+                    VirtualSystemType.text = "vmx-{}".format(self.hwversion)
+
+                if self.memory is not None or self.cpu is not None or self.disk_controller is not None:
+                    for item in virtualHardwareSection.iterfind('xmlns:Item', nsmap):
+                        description = item.find("rasd:Description", nsmap)
+
+                        if self.cpu is not None:
+                            if description is not None and description.text == "Number of Virtual CPUs":
+                                cpu_item = item.find("rasd:VirtualQuantity", nsmap)
+                                name_item = item.find("rasd:ElementName", nsmap)
+                                if cpu_item is not None:
+                                    cpu_item.text = self.cpu
+                                    name_item.text = self.cpu + " virtual CPU(s)"
+
+                        if self.memory is not None:
+                            if description is not None and description.text == "Memory Size":
+                                mem_item = item.find("rasd:VirtualQuantity", nsmap)
+                                name_item = item.find("rasd:ElementName", nsmap)
+                                if mem_item is not None:
+                                    mem_item.text = self.memory
+                                    name_item.text = self.memory + " MB of memory"
+
+                        if self.disk_controller is not None:
+                            if description is not None and description.text == "SCSI Controller":
+                                if self.disk_controller_info is not None:
+                                    name_item = item.find("rasd:ElementName", nsmap)
+                                    name_item.text = str(self.disk_controller_info["controllerName"]) + "0"
+
+                                    resource_type = item.find("rasd:ResourceType", nsmap)
+                                    resource_type.text = self.disk_controller_info["resourceType"]
+
+                                    description.text = self.disk_controller_info["controllerName"]
+                                    resource_subtype = item.find("rasd:ResourceSubType", nsmap)
+                                    if self.disk_controller_info["controllerName"] == "IDE Controller":
+                                        # Remove resource subtype item
+                                        resource_subtype.getparent().remove(resource_subtype)
+                                    if "resourceSubType" in self.disk_controller_info:
+                                        resource_subtype.text = self.disk_controller_info["resourceSubType"]
+                if self.cdrom:
+                    last_item = list(virtualHardwareSection.iterfind('xmlns:Item', nsmap))[-1]
+                    ide_cdrom_items_etree = ET.parse(IDE_CDROM_XML_PATH)
+                    ide_cdrom_items = list(ide_cdrom_items_etree.iterfind('Item'))
+                    for item in ide_cdrom_items:
+                        last_item.addnext(item)
+
+            # Save output OVF
+            OVF_tree.write(self.output_path, xml_declaration=True, encoding='utf-8',
+                           method="xml")
+
+            if os.path.isfile(self.output_path):
+                logger.info("Successfully written output OVF at {}".format(self.output_path))
+                print("Output OVF is at: {}".format(self.output_path))
+                return self.output_path
+            else:
+                error_msg = "ERROR: Error occurred while creating OVF file"
+                print(error_msg)
+                return False
+
+        except Exception as exp:
+            error_msg = "ERROR: Error occurred while editing OVF template : {}".format(exp)
+            self.logger.error(error_msg)
+            print(error_msg)
+            return False
+
+    def __convert_size(self, size):
+        """
+            Private method to convert disk size from GB,MB to bytes.
+            Args :
+                size  : disk size with prefix 'G' for GB and 'M' for MB
+            Return :  disk size in bytes
+        """
+        byte_size = 0
+        try:
+            if not size:
+                self.logger.error("No size {} to convert in bytes".format(size))
+            else:
+                size = str(size)
+                disk_size = float(size[:-1])
+                input_type = size[-1].strip()
+
+                self.logger.info("Disk size : {} , size type : {} ".format(disk_size, input_type))
+
+                if input_type == "G":
+                    byte_size = disk_size * 1024 * 1024 * 1024
+                elif input_type == "M":
+                    byte_size = disk_size * 1024 * 1024
+
+                self.logger.info("Disk size in bytes: {} ".format(byte_size))
+
+            return int(byte_size)
+
+        except Exception as exp:
+            error_msg = "ERROR:Error occurred while converting disk size in bytes : {}".format(exp)
+            self.logger.error(error_msg)
+            print(error_msg)
+            return False
+
+    def __get_osType(self):
+        """
+            Private method to get OS ID and Type
+            Args :
+                None
+            Return :
+                osID : OS ID
+                osType: OS Type
+        """
+        osID = None
+        osType = None
+        os_info = self.__read_yaml_file(OS_INFO_FILE_PATH)
+
+        try:
+            if self.os_type and os_info:
+                for os_id, os_type in os_info.items():
+                    if self.os_type.lower() == os_type.lower():
+                        osID = os_id
+                        osType = os_type
+                        break
+        except Exception as exp:
+            error_msg = "ERROR:Error occurred while getting OS details : {}".format(exp)
+            self.logger.error(error_msg)
+            print(error_msg)
+
+        return osID, osType
+
+    def __get_diskcontroller(self):
+        """
+            Private method to get details of Disk Controller
+            Args :
+                None
+            Return :
+                disk_controller : dict with details of Disk Controller
+        """
+        disk_controller = {}
+        scsi_subtype = None
+        if self.disk_controller.lower() in ["paravirtual", "lsilogic", "buslogic", "lsilogicsas"]:
+            scsi_subtype = self.disk_controller
+            self.disk_controller = "SCSI"
+
+        disk_controller_info = self.__read_yaml_file(DISK_CONTROLLER_INFO_FILE_PATH)
+        try:
+            if self.disk_controller and disk_controller_info:
+                for key, value in disk_controller_info.iteritems():
+                    if self.disk_controller.lower() in key.lower():
+                        disk_controller['controllerName'] = key
+                        disk_controller['resourceType'] = str(value["ResourceType"])
+                        resourceSubTypes = value["ResourceSubTypes"] if "ResourceSubTypes" in value else None
+                        if key == "SATA Controller":
+                            disk_controller["resourceSubType"] = resourceSubTypes[0]
+                        elif key == "SCSI Controller":
+                            if scsi_subtype:
+                                if scsi_subtype.lower() == "paravirtual":
+                                    scsi_subtype = "VirtualSCSI"
+                                for subtype in resourceSubTypes:
+                                    if scsi_subtype.lower() == subtype.lower():
+                                        disk_controller["resourceSubType"] = subtype
+                                        break
+                                else:
+                                    error_msg = "ERROR: Invalid inputs can not "\
+                                        "find SCSI subtype {}".format(scsi_subtype)
+                                    self.__raise_exception(error_msg)
+
+        except KeyError as exp:
+            error_msg = "ERROR:Error occurred while getting Disk Controller details : {}".format(exp)
+            self.logger.error(error_msg)
+            print(error_msg)
+
+        return disk_controller
+
+    def __read_yaml_file(self, file_path):
+        """
+            Private method to execute command
+            Args :
+                command  : command to execute
+            Return :
+                Dict of yaml data
+        """
+        with open(file_path) as data_file:
+            data = yaml.load(data_file, Loader=yaml.SafeLoader)
+        return data
+
+    def __raise_exception(self, error_msg, exception_type="Generic"):
+        """
+            Private method to execute command
+            Args :
+                command  : command to execute
+            Return :
+               None
+        """
+        if error_msg:
+            self.logger.debug(error_msg)
+            print(error_msg)
+            if exception_type == "Generic":
+                raise Exception(error_msg)
+            elif exception_type == "IO":
+                raise Exception(error_msg)
+
+    def __execute_command(self, command, show_output=False):
+        """
+            Private method to execute command
+            Args :
+                command  : command to execute
+            Return :
+                stdout : output of command
+                stderr: error occurred while executing command if any
+                returncode : return code of command execution
+        """
+        try:
+            self.logger.info("Execute command: {} ".format(command))
+
+            proc = subprocess.Popen(command, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
+                                    stderr=subprocess.PIPE, shell=True, bufsize=1)
+
+            stdout = b''
+            stderr = b''
+
+            while True:
+                output = proc.stdout.read(1)
+                stdout += output
+                if show_output:
+                    print(output.decode(), end='')
+                returncode = proc.poll()
+                if returncode is not None:
+                    for output in proc.stdout.readlines():
+                        stdout += output
+                        if show_output:
+                            print(output.decode(), end='')
+                    break
+
+            for output in proc.stderr.readlines():
+                stderr += output
+
+        except Exception as exp:
+            self.logger.error("Error {} occurred while executing command {} ".format(exp, command))
+
+        return stdout, stderr, returncode
+
+    def create_ovf(self):
+        """
+            Method to convert source image into OVF
+            Args : None
+            Return : True on success else False
+        """
+        # check output format
+        if self.source_format == self.output_format:
+            self.logger.info("Source format is OVF. No need to convert: {} ")
+            return self.source_img_path
+
+        # Get source img properties
+        img_info = self.__get_image_info()
+        if img_info:
+
+            # Create vmdk disk image
+            disk_img = self.__convert_image()
+            if disk_img:
+
+                # Edit OVF tempalte
+                ovf_path = self.__edit_ovf_template()
+                return ovf_path
+        else:
+            self.logger.error("Error in getting image information cannot convert image")
+            raise Exception("Error in getting image information cannot convert image")
+            return False
diff --git a/tools/OVF_converter/format_converter/__init__.py b/tools/OVF_converter/format_converter/__init__.py
deleted file mode 100644 (file)
index db9e016..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-##
-# Copyright 2016-2017 VMware Inc.
-# This file is part of ETSI OSM
-# All Rights Reserved.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact:  osslegalrouting@vmware.com
-##
diff --git a/tools/OVF_converter/format_converter/command_progress.py b/tools/OVF_converter/format_converter/command_progress.py
deleted file mode 100644 (file)
index cbfb737..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-##
-# Copyright 2016-2017 VMware Inc.
-# This file is part of ETSI OSM
-# All Rights Reserved.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact:  osslegalrouting@vmware.com
-##
-
-import threading
-import sys
-
-class RepeatingTimer(threading._Timer):
-    """ Class to run thread parally """
-    def run(self):
-        """ Method to run thread """
-        while True:
-            self.finished.wait(self.interval)
-            if self.finished.is_set():
-                return
-            else:
-                self.function(*self.args, **self.kwargs)
-
-
-class CommandProgressbar(object):
-    """ Class to show progressbar while waiting fro command output """
-
-    def __init__(self):
-        self.timer = None
-
-    def __show_progressbar(self):
-        """
-            Private method to show progressbar while waiting for command to complete
-            Args  : None
-            Return : None
-        """
-        print '\b.',
-        sys.stdout.flush()
-
-    def start_progressbar(self):
-        """
-            Method to start progressbar thread
-            Args  : None
-            Return : None
-        """
-        self.timer = RepeatingTimer(1.0, self.__show_progressbar)
-        self.timer.daemon = True # Allows program to exit if only the thread is alive
-        self.timer.start()
-
-    def stop_progressbar(self):
-        """
-            Method to stop progressbar thread
-            Args  : None
-            Return : None
-        """
-        self.timer.cancel()
diff --git a/tools/OVF_converter/format_converter/converter.py b/tools/OVF_converter/format_converter/converter.py
deleted file mode 100644 (file)
index ca2a369..0000000
+++ /dev/null
@@ -1,578 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-##
-# Copyright 2016-2017 VMware Inc.
-# This file is part of ETSI OSM
-# All Rights Reserved.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact:  osslegalrouting@vmware.com
-##
-
-import logging
-import os
-import subprocess
-import yaml
-from lxml import etree as ET
-from command_progress import CommandProgressbar
-
-#file paths
-MODULE_DIR = os.path.dirname(__file__)
-OVF_TEMPLATE_PATH = os.path.join(os.path.dirname(MODULE_DIR),
-                                "ovf_template/template.xml")
-IDE_CDROM_XML_PATH = os.path.join(os.path.dirname(MODULE_DIR),
-                                "ovf_template/ide_cdrom.xml")
-OS_INFO_FILE_PATH = os.path.join(os.path.dirname(MODULE_DIR), 
-                                "config/os_type.yaml")
-DISK_CONTROLLER_INFO_FILE_PATH = os.path.join(os.path.dirname(MODULE_DIR),
-                                              "config/disk_controller.yaml")
-
-
-#Set logger
-LOG_FILE = os.path.join(os.path.dirname(MODULE_DIR),"logs/ovf_converter.log")
-logger = logging.getLogger(__name__)
-hdlr = logging.FileHandler(LOG_FILE)
-formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
-hdlr.setFormatter(formatter)
-logger.addHandler(hdlr)
-logger.setLevel(10)
-
-__version__ = "1.0"
-__description__ = "initial Release"
-
-def get_version(*args, **kwargs):
-    """ get version of this application"""
-    version = str(__version__ ) +" - "+ str( __description__ )
-    return version
-
-#converter class
-class OVFConverter(object):
-    """ Class to convert input image into OVF format """
-
-    def __init__(self, source_img_path, output_location=None, output_ovf_name=None,
-                    memory=None, cpu=None, disk=None, os_type=None,
-                    disk_controller=None, cdrom=None, 
-                    options={'subformat':'streamOptimized'}):
-        """
-            Constructor to initialize object of class OVFConverter
-            Args:
-            source_img_path - absolute path to source image which will get convert into ovf
-            output_location - location where created OVF will be kept. This location
-                              should have write access. If not given file will get
-                              created at source location  (optional)
-            output_ovf_name - name of output ovf.If not given source image name will 
-                              be used (optional)
-            memory -          required memory for VM in MB (optional)
-            cpu -             required number of virtual cpus for VM (optional)
-            disk -            required size of disk for VM in GB (optional)
-            os_type-          required operating system type as specified in user document
-                                (default os type other 32 bit) (optional)
-            disk_controller - required disk controller type
-                                (default controller SCSI with lsilogicsas)
-                                (SATA, IDE, Paravirtual, Buslogic, Lsilogic, Lsilogicsas) (optional)
-            options - subformat option for OVF  (optional)
-
-            Returns:
-                Nothing.
-        """
-        self.logger = logger
-        self.ovf_template_path = OVF_TEMPLATE_PATH
-
-        self.source_img_path = source_img_path
-        file_location, file_extension = os.path.splitext(self.source_img_path)
-        self.source_img_location = os.path.dirname(self.source_img_path)
-        self.source_format = file_extension[1:]
-        self.source_img_filename = os.path.basename(self.source_img_path).split('.')[0]
-
-        self.output_format = "ovf"
-        self.output_ovf_name = output_ovf_name.split('.')[0] if output_ovf_name else self.source_img_filename
-        self.output_location = output_location if output_location else self.source_img_location
-        self.output_ovf_name_ext = self.output_ovf_name + "." + self.output_format
-        self.output_path = os.path.join(self.output_location , self.output_ovf_name_ext )
-
-        self.output_diskimage_format = "vmdk"
-        self.output_diskimage_name = self.source_img_filename + "."+ self.output_diskimage_format
-        self.output_diskimage_path = os.path.join(self.output_location,  self.output_diskimage_name)
-
-
-        self.logger.info("Input parameters to Converter: \n ovf_template_path = {}, \n source_img_path = {}, \n"\
-                    "source_img_location ={} , \n source_format = {}, \n source_img_filename = {}".format(
-                                                        self.ovf_template_path,
-                                                        self.source_img_path, self.source_img_location,
-                                                        self.source_format, self.source_img_filename ))
-
-        self.logger.info("Output parameters to Converter: \n output_format = {}, \n output_ovf_name = {}, \n"\
-                    "output_location ={} , \n output_path = {}, \n output_diskimage_name = {} , \n"\
-                    " output_diskimage_path = {} ".format(self.output_format, self.output_ovf_name,
-                                                    self.output_location, self.output_path,
-                                                    self.output_diskimage_name,self.output_diskimage_path ))
-
-
-        self.disk_capacity = 1
-        self.disk_populated_size = 0
-
-        self.vm_name = self.output_ovf_name
-        self.memory = str(memory) if memory is not None else None
-        self.cpu = str(cpu) if cpu is not None else None
-        self.os_type=str(os_type).strip() if os_type else None
-        self.cdrom = cdrom
-
-        if self.os_type:
-            self.osID , self.osType = self.__get_osType()
-            if self.osID is None or self.osType is None:
-               error_msg = "ERROR: Invalid input can not find OS type {} ".format(self.os_type)
-               self.__raise_exception(error_msg)
-
-        self.disk_controller = str(disk_controller).strip() if disk_controller else None
-
-        if self.disk_controller:
-            self.disk_controller_info = self.__get_diskcontroller()
-
-            if not self.disk_controller_info:
-                error_msg = "ERROR: Invalid input can not find Disk Controller {} ".format(self.disk_controller)
-                self.__raise_exception(error_msg)
-
-        if disk is not None:
-            #convert disk size from GB to bytes
-            self.disk_size = int(disk) * 1024 * 1024 * 1024
-        else:
-            self.disk_size = None
-
-        self.logger.info("Other input parameters to Converter: \n vm_name = {}, \n memory = {}, \n"\
-                    "disk_size ={} \n os type = {} \n disk controller = {}".format(
-                                self.vm_name, self.memory, self.disk_size, self.os_type, self.disk_controller
-                                ))
-
-        #check access for read input location and write output location return none if no access
-        if not os.access(self.source_img_path, os.F_OK):
-            error_msg = "ERROR: Source image file {} not present".format(self.source_img_path)
-            self.__raise_exception(error_msg, exception_type="IO")
-
-        elif not os.access(self.source_img_path, os.R_OK):
-            error_msg = "ERROR: Cannot read source image file {}".format(self.source_img_path)
-            self.__raise_exception(error_msg, exception_type="IO")
-
-        if not os.access(self.output_location, os.W_OK):
-            error_msg = "ERROR: Not have write access to location {} to write output OVF ".format(self.source_img_path)
-            self.__raise_exception(error_msg, exception_type="IO")
-
-    def __get_image_info(self):
-        """ 
-            Private method to get information about source imager.
-            Args  : None
-            Return : True on success else False
-        """
-        try:
-            print("Getting source image information")
-            command = "qemu-img info \t " + self.source_img_path
-            output, error, returncode= self.__execute_command(command)
-
-            if error or returncode:
-                self.logger.error("ERROR: Error occurred while getting information about source image : {} \n "\
-                                  "return code : {} ".format(error, returncode))
-                return False
-
-            elif output:
-                self.logger.info("Get Image Info Output : {} \n ".format(output))
-                split_output = output.split("\n")
-                for line in split_output:
-                    line = line.strip()
-                    if "virtual size" in line:
-                        virtual_size_info = line.split(":")[1].split()
-                        if len(virtual_size_info) == 3 and virtual_size_info[2].strip(")") == "bytes":
-                            self.disk_capacity  = int(virtual_size_info[1].strip("("))
-                        else:
-                            self.disk_capacity  = self.__convert_size(virtual_size_info[0])
-
-                    elif "disk size" in line:
-                        size = line.split(":")[1].split()[0]
-                        self.disk_populated_size = self.__convert_size(size)
-                    elif "file format" in line:
-                        self.source_format = line.split(":")[1]
-
-                self.logger.info("Updated source image virtual disk capacity : {} ,"\
-                                 "Updated source image populated size: {}".format(self.disk_capacity,
-                                                                    self.disk_populated_size))
-                return True
-        except Exception as exp:
-            error_msg = "ERROR: Error occurred while getting information about source image : {}".format(exp)
-            self.logger.error(error_msg)
-            print(error_msg)
-            return False
-
-    def __convert_image(self):
-        """ 
-            Private method to convert source disk image into .vmdk disk image.
-            Args  : None
-            Return : True on success else False
-        """
-
-        print("Converting source disk image to .vmdk ")
-
-        progress = CommandProgressbar()
-        progress.start_progressbar()
-
-        command = "qemu-img convert -f "+ self.source_format +" -O " + self.output_diskimage_format + \
-                " -o subformat=streamOptimized " + self.source_img_path + "\t" + self.output_diskimage_path
-
-        output, error , returncode = self.__execute_command(command)
-
-        progress.stop_progressbar()
-
-        if error or returncode :
-            error_msg = "ERROR: Error occurred while converting source disk image into vmdk : {} \n "\
-                                  "return code : {} ".format(error, returncode)
-            self.logger.error(error_msg)
-            print(error_msg)
-            return False
-        else:
-            if os.path.isfile(self.output_diskimage_path):
-                self.logger.info("Successfully converted source image {} into {} \n "\
-                                  "return code : {} ".format(self.source_img_path,
-                                                        self.output_diskimage_path,
-                                                        returncode))
-                result = self.__make_image_bootable()
-                if result:
-                    self.logger.info("Made {} bootable".format(self.output_diskimage_path))
-                    return True
-                else:
-                    self.logger.error("Cannot make {} bootable".format(self.output_diskimage_path))
-                    print("ERROR: Fail to convert source image into .vmdk")
-                    return False
-            else:
-                self.logger.error("Converted vmdk disk file {} is not present \n ".format(
-                                                    self.output_diskimage_path))
-                print("Fail to convert source image into .vmdk")
-                return False
-
-    def __make_image_bootable(self):
-        """ 
-            Private method to make source disk image bootable.
-            Args  : None
-            Return : True on success else False
-        """
-        command = "printf '\x03' | dd conv=notrunc of="+ self.output_diskimage_path + "\t bs=1 seek=$((0x4))"
-        output, error, returncode = self.__execute_command(command)
-
-        if error and returncode :
-            error_msg = "ERROR:Error occurred while making source disk image bootable : {} \n "\
-                                  "return code : {} ".format(error, returncode)
-            self.logger.error(error_msg)
-            print(error_msg)
-            return False
-        else:
-            self.logger.info("Make Image Bootable Output : {} ".format(output))
-            return True
-
-
-    def __edit_ovf_template(self):
-        """ 
-            Private method to create new OVF file by editing OVF template
-            Args  : None
-            Return : True on success else False
-        """
-        try:
-            print("\nCreating OVF")
-            #Read OVF template file
-            OVF_tree = ET.parse(self.ovf_template_path)
-            root = OVF_tree.getroot()
-
-            #Collect namespaces
-            nsmap = {k:v for k,v in root.nsmap.iteritems() if k}
-            nsmap["xmlns"]= "http://schemas.dmtf.org/ovf/envelope/1"
-
-            #Edit OVF template
-            references = root.find('xmlns:References',nsmap)
-            if references is not None:
-                file_tag = references.find('xmlns:File', nsmap)
-                if file_tag is not None:
-                    file_tag.attrib['{'+nsmap['ovf']+'}href'] = self.output_diskimage_name
-
-            disksection = root.find('xmlns:DiskSection',nsmap)
-            if disksection is not None:
-                diak_tag = disksection.find('xmlns:Disk', nsmap)
-                if diak_tag is not None:
-                    if self.disk_size and self.disk_size > self.disk_capacity:
-                        self.disk_capacity = self.disk_size
-                    diak_tag.attrib['{'+nsmap['ovf']+'}capacity'] = str(self.disk_capacity)
-                    diak_tag.attrib['{'+nsmap['ovf']+'}populatedSize'] = str(self.disk_populated_size)
-
-            virtuasystem = root.find('xmlns:VirtualSystem',nsmap)
-            if virtuasystem is not None:
-                name_tag = virtuasystem.find('xmlns:Name', nsmap)
-                if name_tag is not None:
-                    name_tag.text = self.vm_name
-
-                if self.os_type is not None:
-                    operatingSystemSection = virtuasystem.find('xmlns:OperatingSystemSection', nsmap)
-                    if self.osID and self.osType:
-                        operatingSystemSection.attrib['{'+nsmap['ovf']+'}id'] = self.osID
-                        os_discription_tag = operatingSystemSection.find('xmlns:Description', nsmap)
-                        os_discription_tag.text = self.osType
-
-                virtualHardwareSection = virtuasystem.find('xmlns:VirtualHardwareSection', nsmap)
-                system = virtualHardwareSection.find('xmlns:System', nsmap)
-                virtualSystemIdentifier = system.find('vssd:VirtualSystemIdentifier', nsmap)
-                if virtualSystemIdentifier is not None:
-                    virtualSystemIdentifier.text = self.vm_name
-
-                if self.memory is not None or self.cpu is not None or self.disk_controller is not None:
-                    for item in virtualHardwareSection.iterfind('xmlns:Item',nsmap):
-                        description = item.find("rasd:Description",nsmap)
-
-                        if self.cpu is not None:
-                            if description is not None and description.text == "Number of Virtual CPUs":
-                                cpu_item = item.find("rasd:VirtualQuantity", nsmap)
-                                name_item = item.find("rasd:ElementName", nsmap)
-                                if cpu_item is not None:
-                                    cpu_item.text = self.cpu
-                                    name_item.text = self.cpu+" virtual CPU(s)"
-
-                        if self.memory is not None:
-                            if description is not None and description.text == "Memory Size":
-                                mem_item = item.find("rasd:VirtualQuantity", nsmap)
-                                name_item = item.find("rasd:ElementName", nsmap)
-                                if mem_item is not None:
-                                    mem_item.text = self.memory
-                                    name_item.text = self.memory + " MB of memory"
-
-                        if self.disk_controller is not None:
-                            if description is not None and description.text == "SCSI Controller":
-                                if self.disk_controller_info is not None:
-                                    name_item = item.find("rasd:ElementName", nsmap)
-                                    name_item.text = str(self.disk_controller_info["controllerName"])+"0"
-
-                                    resource_type = item.find("rasd:ResourceType", nsmap)
-                                    resource_type.text = self.disk_controller_info["resourceType"]
-
-                                    description.text = self.disk_controller_info["controllerName"]
-                                    resource_subtype = item.find("rasd:ResourceSubType", nsmap)
-                                    if self.disk_controller_info["controllerName"] == "IDE Controller":
-                                        #Remove resource subtype item
-                                        resource_subtype.getparent().remove(resource_subtype)
-                                    if "resourceSubType" in  self.disk_controller_info:
-                                        resource_subtype.text = self.disk_controller_info["resourceSubType"]
-                if self.cdrom:
-                    last_item = list(virtualHardwareSection.iterfind('xmlns:Item',nsmap))[-1]
-                    ide_cdrom_items_etree = ET.parse(IDE_CDROM_XML_PATH)
-                    ide_cdrom_items = list(ide_cdrom_items_etree.iterfind('Item'))
-                    for item in ide_cdrom_items:
-                        last_item.addnext(item)
-
-            # Save output OVF
-            OVF_tree.write(self.output_path, xml_declaration=True,encoding='utf-8',
-               method="xml" )
-
-            if os.path.isfile(self.output_path):
-                logger.info("Successfully written output OVF at {}".format(self.output_path))
-                print("Output OVF is at :  {}".format(self.output_path))
-                return self.output_path
-            else:
-                error_msg = "ERROR: Error occurred while creating OVF file"
-                print(error_msg)
-                return False
-
-        except Exception as exp:
-            error_msg = "ERROR: Error occurred while editing OVF template : {}".format(exp)
-            self.logger.error(error_msg)
-            print(error_msg)
-            return False
-
-
-    def __convert_size(self,size):
-        """ 
-            Private method to convert disk size from GB,MB to bytes.
-            Args :
-                size  : disk size with prefix 'G' for GB and 'M' for MB
-            Return :  disk size in bytes
-        """
-        byte_size= 0
-        try:
-            if not size:
-                self.logger.error("No size {} to convert in bytes".format(size))
-            else:
-                size = str(size)
-                disk_size = float(size[:-1])
-                input_type = size[-1].strip()
-
-                self.logger.info("Disk size : {} , size type : {} ".format(disk_size,input_type))
-
-                if input_type == "G":
-                    byte_size = disk_size * 1024 * 1024 *1024
-                elif input_type == "M":
-                    byte_size = disk_size * 1024 * 1024
-
-                self.logger.info("Disk size in bytes: {} ".format(byte_size))
-
-            return int(byte_size)
-
-        except Exception as exp:
-            error_msg = "ERROR:Error occurred while converting disk size in bytes : {}".format(exp)
-            self.logger.error(error_msg)
-            print(error_msg)
-            return False
-
-    def __get_osType(self):
-        """ 
-            Private method to get OS ID and Type
-            Args :
-                None
-            Return :
-                osID : OS ID
-                osType: OS Type
-        """
-        osID = None
-        osType = None
-        os_info = self.__read_yaml_file(OS_INFO_FILE_PATH)
-        try:
-            if self.os_type and os_info:
-                for os_id , os_type in os_info.iteritems():
-                    if self.os_type.lower() == os_type.lower():
-                        osID = os_id
-                        osType = os_type
-                        break
-        except Exception as exp:
-            error_msg = "ERROR:Error occurred while getting OS details : {}".format(exp)
-            self.logger.error(error_msg)
-            print(error_msg)
-
-        return osID, osType
-
-
-    def __get_diskcontroller(self):
-        """ 
-            Private method to get details of Disk Controller
-            Args :
-                None
-            Return :
-                disk_controller : dict with details of Disk Controller
-        """
-        disk_controller = {}
-        scsi_subtype = None
-        if self.disk_controller.lower() in ["paravirtual", "lsilogic", "buslogic", "lsilogicsas"]:
-            scsi_subtype = self.disk_controller
-            self.disk_controller = "SCSI"
-
-        disk_controller_info = self.__read_yaml_file(DISK_CONTROLLER_INFO_FILE_PATH)
-        try:
-            if self.disk_controller and disk_controller_info:
-                for key , value in disk_controller_info.iteritems():
-                    if self.disk_controller.lower() in key.lower():
-                        disk_controller['controllerName'] = key
-                        disk_controller['resourceType'] = str(value["ResourceType"])
-                        resourceSubTypes = value["ResourceSubTypes"] if "ResourceSubTypes" in value else None
-                        if key == "SATA Controller":
-                            disk_controller["resourceSubType"] = resourceSubTypes[0]
-                        elif key == "SCSI Controller":
-                            if scsi_subtype:
-                                if scsi_subtype.lower() == "paravirtual":
-                                    scsi_subtype = "VirtualSCSI"
-                                for subtype in resourceSubTypes:
-                                    if scsi_subtype.lower() == subtype.lower():
-                                        disk_controller["resourceSubType"] = subtype
-                                        break
-                                else:
-                                    error_msg = "ERROR: Invalid inputs can not "\
-                                    "find SCSI subtype {}".format(scsi_subtype)
-                                    self.__raise_exception(error_msg)
-
-        except KeyError as exp:
-            error_msg = "ERROR:Error occurred while getting Disk Controller details : {}".format(exp)
-            self.logger.error(error_msg)
-            print(error_msg)
-
-        return disk_controller
-
-    def __read_yaml_file(self, file_path):
-        """ 
-            Private method to execute command
-            Args :
-                command  : command to execute
-            Return :
-                Dict of yaml data
-        """
-        with open(file_path) as data_file:    
-            data = yaml.load(data_file)
-        return data
-
-    def __raise_exception(self, error_msg , exception_type="Generic"):
-        """ 
-            Private method to execute command
-            Args :
-                command  : command to execute
-            Return :
-               None
-        """
-        if error_msg:
-            self.logger.debug(error_msg)
-            print(error_msg)
-            if exception_type == "Generic":
-                raise Exception(error_msg)
-            elif exception_type == "IO":
-                raise Exception(error_msg)
-
-    def __execute_command(self, command):
-        """ 
-            Private method to execute command
-            Args :
-                command  : command to execute
-            Return :
-                stdout : output of command
-                stderr: error occurred while executing command if any
-                returncode : return code of command execution
-        """
-        try:
-            self.logger.info("Execute command: {} ".format(command))
-
-            proc = subprocess.Popen(command , stdout = subprocess.PIPE, stdin = subprocess.PIPE,
-                                             stderr = subprocess.PIPE,shell=True)
-            stdout, stderr = proc.communicate()
-            returncode = proc.returncode
-
-        except Exception as exp:
-            self.logger.error("Error {} occurred while executing command {} ".format(exp,command))
-
-        return  stdout, stderr , returncode
-
-
-    def create_ovf(self):
-        """ 
-            Method to convert source image into OVF
-            Args : None
-            Return : True on success else False
-        """
-        #check output format
-        if self.source_format == self.output_format:
-            self.logger.info("Source format is OVF. No need to convert: {} ")
-            return self.source_img_path
-
-        #Get source img properties
-        img_info = self.__get_image_info()
-        if img_info:
-
-            #Create vmdk disk image
-            disk_img = self.__convert_image()
-            if disk_img:
-
-                #Edit OVF tempalte
-                ovf_path = self.__edit_ovf_template()
-                return ovf_path
-        else:
-            self.logger.error("Error in getting image information cannot convert image")
-            raise Exception("Error in getting image information cannot convert image")
-            return False
-
diff --git a/tools/OVF_converter/format_converter/ovf_converter_cli.py b/tools/OVF_converter/format_converter/ovf_converter_cli.py
deleted file mode 100644 (file)
index a505bfe..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-##
-# Copyright 2016-2017 VMware Inc.
-# This file is part of ETSI OSM
-# All Rights Reserved.
-#
-# 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.
-#
-# For those usages not covered by the Apache License, Version 2.0 please
-# contact:  osslegalrouting@vmware.com
-##
-
-import argparse
-from converter import OVFConverter , get_version
-
-def execute_cli():
-
-    """
-        Method to parse CLI arguments and execute commands accordingly
-        Args : None
-        Return : None
-    """
-    parser = argparse.ArgumentParser(description='OVF converter to convert .qcow2 or raw image into OVF')
-
-    parser.add_argument("-v","--version", action="version", version=str(get_version()),
-                            help="shows version of OVF Converter tool")
-
-    parser.add_argument("path", action="store",
-                            help=" absolute path to source image which will get convert into ovf")
-
-    parser.add_argument("-o", "--output_location", action="store",
-                            help="location where created OVF will be kept. This location "\
-                                  "should have write access. If not given file will get "\
-                                  "created at source location  (optional)")
-
-    parser.add_argument("-n","--ovf_name", action="store",
-                            help="name of output ovf file. If not given source image name will "\
-                            " be used (optional)")
-
-    parser.add_argument("-m","--memory", action="store",
-                            help="required memory for VM in MB (default 1 GB)(optional)")
-
-    parser.add_argument("-c","--cpu", action="store",
-                            help="required number of virtual cpus for VM (default 1 cpu) (optional)")
-
-    parser.add_argument("-d","--disk", action="store",
-                            help="required size of disk for VM in GB "\
-                            "(default as in source disk img) (optional)")
-
-    parser.add_argument("-s","--osType", action="store",
-                            help="required operating system type as specified "\
-                            "in user document (default os type other 32 bit) (optional)")
-
-    parser.add_argument("-dc","--disk_Controller", action="store",
-                            help="required disk controller type "\
-                            " (default controller SCSI with lsilogicsas) "\
-                            "(SATA, IDE, Paravirtual, Buslogic, Lsilogic, Lsilogicsas) (optional)")
-
-    parser.add_argument("--cdrom", action="store_true",
-                            help="whether to include a cd/dvd device (optional)")
-
-    args = parser.parse_args()
-
-    if args.path:
-        con = OVFConverter(args.path,
-                           output_location=args.output_location,
-                           output_ovf_name=args.ovf_name,
-                           memory=args.memory,
-                           cpu=args.cpu,
-                           disk=args.disk,
-                           os_type=args.osType,
-                           disk_controller=args.disk_Controller,
-                           cdrom=args.cdrom,
-                           )
-
-        print("#### Start OVF conversion  ####")
-        con.create_ovf()
-        print("#### Completed OVF conversion  ####")
-
-
-if __name__ == "__main__":
-    execute_cli()
-
index 7b184c8..d25c1f6 100755 (executable)
 ##
 
 echo '
- #################################################################
- #####             Installing Require Packages             #####
- #################################################################'
+ ################################################################
+ #####             Installing Required Packages             #####
+ ################################################################'
 
 # Paths to copy application files
 Install_dir="/usr/local/bin"
 App_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-App_CLI_path="${App_dir}/format_converter/ovf_converter_cli.py"
-Install_CLI_path="${Install_dir}/OVF_converter/format_converter/ovf_converter_cli.py"
+Converter_App_CLI_path="${App_dir}/ovf_converter_cli.py"
+Converter_Install_CLI_path="${Install_dir}/OVF_converter/ovf_converter_cli.py"
+Uploader_App_CLI_path="${App_dir}/ovf_uploader_cli.py"
+Uploader_Install_CLI_path="${Install_dir}/OVF_converter/ovf_uploader_cli.py"
 Logs_Folder="${Install_dir}/OVF_converter/logs"
-Log_Path="${Install_dir}/OVF_converter/logs/ovf_converter.log"
 
 #Function to install packages using apt-get
 function install_packages(){
       [ -x /usr/bin/apt-get ] && apt-get install -y $*
-       
+
        #check properly installed
        for PACKAGE in $*
        do
@@ -50,7 +51,7 @@ function install_packages(){
           fi
        done
    }
-  
+
 apt-get update  # To get the latest package lists
 install_packages "libxml2-dev libxslt-dev python-dev python-pip python-lxml python-yaml"
 install_packages "qemu-utils"
@@ -62,18 +63,21 @@ cp -R "${App_dir}"   "${Install_dir}"
 
 #Create logs folder and file
 mkdir "${Logs_Folder}"
-touch "${Log_Path}"
 
 #Change permission
-chmod -R 777 $Install_CLI_path
-chmod -R 777 $Log_Path
+chmod -R 777 ${Converter_Install_CLI_path}
+chmod -R 777 ${Uploader_Install_CLI_path}
+chmod -R 777 ${Logs_Folder}
 
 touch "${Install_dir}/ovf_converter"
 echo  "#!/bin/sh" > "${Install_dir}/ovf_converter"
-echo  "python ${Install_CLI_path} \"\$@\"" >> "${Install_dir}/ovf_converter"
+echo  "python3 ${Converter_Install_CLI_path} \"\$@\"" >> "${Install_dir}/ovf_converter"
 chmod a+x "${Install_dir}/ovf_converter"
 
-echo ' 
- #################################################################
- #####             Done                                #####
- #################################################################'
+touch "${Install_dir}/ovf_uploader"
+echo  "#!/bin/sh" > "${Install_dir}/ovf_uploader"
+echo  "python3 ${Uploader_Install_CLI_path} \"\$@\"" >> "${Install_dir}/ovf_uploader"
+chmod a+x "${Install_dir}/ovf_uploader"
+
+echo "Installation complete.  More information can be found at:"
+echo "  ${Install_dir}/OVF_converter/Usage.txt"
diff --git a/tools/OVF_converter/ovf_converter_cli.py b/tools/OVF_converter/ovf_converter_cli.py
new file mode 100644 (file)
index 0000000..afc7037
--- /dev/null
@@ -0,0 +1,109 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+##
+# Copyright 2016-2017 VMware Inc.
+# This file is part of ETSI OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact:  osslegalrouting@vmware.com
+##
+
+import argparse
+import yaml
+
+from converter import OVFConverter, get_version, OS_INFO_FILE_PATH
+
+
+def execute_cli():
+
+    """
+        Method to parse CLI arguments and execute commands accordingly
+        Args : None
+        Return : None
+    """
+
+    with open(OS_INFO_FILE_PATH) as data_file:
+        os_info = yaml.load(data_file, Loader=yaml.SafeLoader)
+
+    valid_os_strings = "Valid values for osType are:\n"
+    for os_name in os_info.values():
+        valid_os_strings += os_name + ", "
+
+    valid_os_strings = valid_os_strings[:-2]
+
+    parser = argparse.ArgumentParser(description='OVF converter to convert .qcow2 or raw image into OVF')
+
+    parser.add_argument("-v", "--version", action="version", version=str(get_version()),
+                        help="shows version of OVF Converter tool")
+
+    parser.add_argument("path", action="store",
+                        help="absolute path to source image which will get converted into ovf")
+
+    parser.add_argument("-o", "--output_location", action="store",
+                        help="location where created OVF will be kept. This location "
+                        "should have write access. If not given file will get "
+                        "created at source location  (optional)")
+
+    parser.add_argument("-n", "--ovf_name", action="store",
+                        help="name of output ovf file. If not given source image name will "
+                        " be used (optional)")
+
+    parser.add_argument("-m", "--memory", action="store",
+                        help="required memory for VM in MB (default 1 GB)(optional)")
+
+    parser.add_argument("-c", "--cpu", action="store",
+                        help="required number of virtual cpus for VM (default 1 cpu) (optional)")
+
+    parser.add_argument("-d", "--disk", action="store",
+                        help="required size of disk for VM in GB "
+                        "(default as in source disk img) (optional)")
+
+    parser.add_argument("-s", "--osType", action="store",
+                        help="required operating system type as specified "
+                        "in user document (default os type other 32 bit) (optional) " + valid_os_strings)
+
+    parser.add_argument("-dc", "--disk_Controller", action="store",
+                        help="required disk controller type "
+                        "(default controller SCSI with lsilogicsas) "
+                        "(SATA, IDE, Paravirtual, Buslogic, Lsilogic, Lsilogicsas) (optional)")
+
+    parser.add_argument("--cdrom", action="store_true", default=True,
+                        help="whether to include a cd/dvd device (optional)")
+
+    parser.add_argument("-hw", "--hwversion", action="store", default=14,
+                        help="Virtual hardware version (default 14)")
+
+    args = parser.parse_args()
+
+    if args.path:
+        con = OVFConverter(args.path,
+                           output_location=args.output_location,
+                           output_ovf_name=args.ovf_name,
+                           memory=args.memory,
+                           cpu=args.cpu,
+                           disk=args.disk,
+                           os_type=args.osType,
+                           disk_controller=args.disk_Controller,
+                           cdrom=args.cdrom,
+                           hwversion=args.hwversion,
+                           )
+
+        con.create_ovf()
+
+
+if __name__ == "__main__":
+    execute_cli()
index ffab392..431f38a 100644 (file)
@@ -1,3 +1,23 @@
+<!--
+ Copyright 2016-2019 VMware Inc.
+ This file is part of ETSI OSM
+ All Rights Reserved.
+
+ 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.
+
+ For those usages not covered by the Apache License, Version 2.0 please
+ contact:  osslegalrouting@vmware.com
+-->
 <Items>
         <Item xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">
             <rasd:AddressOnParent>0</rasd:AddressOnParent>
index 5cbb328..a963582 100644 (file)
-<?xml version="1.0" encoding="UTF-8"?>\r
-<Envelope xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:cim="http://schemas.dmtf.org/wbem/wscim/1/common" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" xmlns:vmw="http://www.vmware.com/schema/ovf" xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
-  <References>\r
-     <File ovf:href="disk_img_filename.vmdk" ovf:id="file1" />\r
-  </References>\r
-   <DiskSection>\r
-    <Info>Virtual disk information</Info>\r
-    <Disk ovf:capacity="1" ovf:capacityAllocationUnits="byte" ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" ovf:populatedSize="0"/>\r
-  </DiskSection>\r
-  \r
-  <NetworkSection>\r
-       <Info>List of logical networks used in the package</Info> \r
- </NetworkSection>\r
-       \r
- <VirtualSystem ovf:id="vm">\r
-    <Info>A virtual machine</Info>\r
-    <Name>Virtual machine name</Name>\r
-    \r
-    <OperatingSystemSection ovf:id="1">\r
-      <Info>The kind of installed guest operating system</Info>\r
-      <Description>Other (32-bit)</Description>\r
-    </OperatingSystemSection>\r
-\r
-    <VirtualHardwareSection>\r
-      <Info>Virtual hardware requirements</Info>\r
-      <System>\r
-               <vssd:ElementName>Virtual Hardware Family</vssd:ElementName>\r
-               <vssd:InstanceID>0</vssd:InstanceID>\r
-               <vssd:VirtualSystemIdentifier>Test1</vssd:VirtualSystemIdentifier>\r
-               <vssd:VirtualSystemType>vmx-7</vssd:VirtualSystemType>\r
-         </System>\r
-           \r
-      <Item>\r
-        <rasd:AllocationUnits>hertz * 10^6</rasd:AllocationUnits>\r
-        <rasd:Description>Number of Virtual CPUs</rasd:Description>\r
-        <rasd:ElementName>1 virtual CPU(s)</rasd:ElementName>\r
-        <rasd:InstanceID>1</rasd:InstanceID>\r
-        <rasd:ResourceType>3</rasd:ResourceType>\r
-        <rasd:VirtualQuantity>1</rasd:VirtualQuantity>\r
-      </Item>\r
-      <Item>\r
-        <rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>\r
-        <rasd:Description>Memory Size</rasd:Description>\r
-        <rasd:ElementName>1GB of memory</rasd:ElementName>\r
-        <rasd:InstanceID>2</rasd:InstanceID>\r
-        <rasd:ResourceType>4</rasd:ResourceType>\r
-        <rasd:VirtualQuantity>1024</rasd:VirtualQuantity>\r
-      </Item>\r
-      <Item>\r
-        <rasd:Address>0</rasd:Address>\r
-        <rasd:Description>SCSI Controller</rasd:Description>\r
-        <rasd:ElementName>scsiController0</rasd:ElementName>\r
-        <rasd:InstanceID>3</rasd:InstanceID>\r
-        <rasd:ResourceSubType>lsilogicsas</rasd:ResourceSubType>\r
-        <rasd:ResourceType>6</rasd:ResourceType>\r
-      </Item>\r
-      <Item>\r
-        <rasd:AddressOnParent>0</rasd:AddressOnParent>\r
-        <rasd:ElementName>disk0</rasd:ElementName>\r
-        <rasd:HostResource>ovf:/disk/vmdisk1</rasd:HostResource>\r
-        <rasd:InstanceID>4</rasd:InstanceID>\r
-        <rasd:Parent>3</rasd:Parent>\r
-        <rasd:ResourceType>17</rasd:ResourceType>\r
-      </Item>\r
-      <Item ovf:required="false">\r
-        <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>\r
-        <rasd:ElementName>video</rasd:ElementName>\r
-        <rasd:InstanceID>5</rasd:InstanceID>\r
-        <rasd:ResourceType>24</rasd:ResourceType>\r
-      </Item>\r
-      <Item ovf:required="false">\r
-        <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>\r
-        <rasd:ElementName>vmci</rasd:ElementName>\r
-        <rasd:InstanceID>6</rasd:InstanceID>\r
-        <rasd:ResourceSubType>vmware.vmci</rasd:ResourceSubType>\r
-        <rasd:ResourceType>1</rasd:ResourceType>\r
-      </Item>\r
-      <vmw:Config ovf:required="false" vmw:key="cpuHotAddEnabled" vmw:value="true"/>\r
-      <vmw:Config ovf:required="false" vmw:key="powerOpInfo.powerOffType" vmw:value="soft"/>\r
-      <vmw:Config ovf:required="false" vmw:key="powerOpInfo.resetType" vmw:value="soft"/>\r
-      <vmw:Config ovf:required="false" vmw:key="powerOpInfo.suspendType" vmw:value="soft"/>\r
-      <vmw:Config ovf:required="false" vmw:key="tools.syncTimeWithHost" vmw:value="true"/>\r
-      <vmw:Config ovf:required="false" vmw:key="tools.toolsUpgradePolicy" vmw:value="upgradeAtPowerCycle"/>\r
-    </VirtualHardwareSection>\r
-               \r
-  </VirtualSystem>\r
-</Envelope>
\ No newline at end of file
+<!--
+ Copyright 2016-2019 VMware Inc.
+ This file is part of ETSI OSM
+ All Rights Reserved.
+
+ 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.
+
+ For those usages not covered by the Apache License, Version 2.0 please
+ contact:  osslegalrouting@vmware.com
+-->
+<?xml version="1.0" encoding="UTF-8"?>
+<Envelope xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:cim="http://schemas.dmtf.org/wbem/wscim/1/common" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" xmlns:vmw="http://www.vmware.com/schema/ovf" xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <References>
+     <File ovf:href="disk_img_filename.vmdk" ovf:id="file1" />
+  </References>
+   <DiskSection>
+    <Info>Virtual disk information</Info>
+    <Disk ovf:capacity="1" ovf:capacityAllocationUnits="byte" ovf:diskId="vmdisk1" ovf:fileRef="file1" ovf:format="http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized" ovf:populatedSize="0"/>
+  </DiskSection>
+
+  <NetworkSection>
+    <Info>List of logical networks used in the package</Info>
+ </NetworkSection>
+
+ <VirtualSystem ovf:id="vm">
+    <Info>A virtual machine</Info>
+    <Name>Virtual machine name</Name>
+
+    <OperatingSystemSection ovf:id="1">
+      <Info>The kind of installed guest operating system</Info>
+      <Description>Other (32-bit)</Description>
+    </OperatingSystemSection>
+
+    <VirtualHardwareSection>
+      <Info>Virtual hardware requirements</Info>
+      <System>
+        <vssd:ElementName>Virtual Hardware Family</vssd:ElementName>
+        <vssd:InstanceID>0</vssd:InstanceID>
+        <vssd:VirtualSystemIdentifier>Test1</vssd:VirtualSystemIdentifier>
+        <vssd:VirtualSystemType>vmx-14</vssd:VirtualSystemType>
+      </System>
+
+      <Item>
+        <rasd:AllocationUnits>hertz * 10^6</rasd:AllocationUnits>
+        <rasd:Description>Number of Virtual CPUs</rasd:Description>
+        <rasd:ElementName>1 virtual CPU(s)</rasd:ElementName>
+        <rasd:InstanceID>1</rasd:InstanceID>
+        <rasd:ResourceType>3</rasd:ResourceType>
+        <rasd:VirtualQuantity>1</rasd:VirtualQuantity>
+      </Item>
+      <Item>
+        <rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>
+        <rasd:Description>Memory Size</rasd:Description>
+        <rasd:ElementName>1GB of memory</rasd:ElementName>
+        <rasd:InstanceID>2</rasd:InstanceID>
+        <rasd:ResourceType>4</rasd:ResourceType>
+        <rasd:VirtualQuantity>1024</rasd:VirtualQuantity>
+      </Item>
+      <Item>
+        <rasd:Address>0</rasd:Address>
+        <rasd:Description>SCSI Controller</rasd:Description>
+        <rasd:ElementName>scsiController0</rasd:ElementName>
+        <rasd:InstanceID>3</rasd:InstanceID>
+        <rasd:ResourceSubType>lsilogicsas</rasd:ResourceSubType>
+        <rasd:ResourceType>6</rasd:ResourceType>
+      </Item>
+      <Item>
+        <rasd:AddressOnParent>0</rasd:AddressOnParent>
+        <rasd:ElementName>disk0</rasd:ElementName>
+        <rasd:HostResource>ovf:/disk/vmdisk1</rasd:HostResource>
+        <rasd:InstanceID>4</rasd:InstanceID>
+        <rasd:Parent>3</rasd:Parent>
+        <rasd:ResourceType>17</rasd:ResourceType>
+      </Item>
+      <Item ovf:required="false">
+        <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
+        <rasd:ElementName>video</rasd:ElementName>
+        <rasd:InstanceID>5</rasd:InstanceID>
+        <rasd:ResourceType>24</rasd:ResourceType>
+      </Item>
+      <Item ovf:required="false">
+        <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
+        <rasd:ElementName>vmci</rasd:ElementName>
+        <rasd:InstanceID>6</rasd:InstanceID>
+        <rasd:ResourceSubType>vmware.vmci</rasd:ResourceSubType>
+        <rasd:ResourceType>1</rasd:ResourceType>
+      </Item>
+      <vmw:Config ovf:required="false" vmw:key="cpuHotAddEnabled" vmw:value="true"/>
+      <vmw:Config ovf:required="false" vmw:key="powerOpInfo.powerOffType" vmw:value="soft"/>
+      <vmw:Config ovf:required="false" vmw:key="powerOpInfo.resetType" vmw:value="soft"/>
+      <vmw:Config ovf:required="false" vmw:key="powerOpInfo.suspendType" vmw:value="soft"/>
+      <vmw:Config ovf:required="false" vmw:key="tools.syncTimeWithHost" vmw:value="true"/>
+      <vmw:Config ovf:required="false" vmw:key="tools.toolsUpgradePolicy" vmw:value="upgradeAtPowerCycle"/>
+    </VirtualHardwareSection>
+
+  </VirtualSystem>
+</Envelope>
diff --git a/tools/OVF_converter/ovf_uploader_cli.py b/tools/OVF_converter/ovf_uploader_cli.py
new file mode 100644 (file)
index 0000000..e487877
--- /dev/null
@@ -0,0 +1,75 @@
+##
+# Copyright 2019 VMware Inc.
+# This file is part of ETSI OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact:  osslegalrouting@vmware.com
+##
+
+import argparse
+from uploader import OVFUploader, get_version
+
+
+def execute_cli():
+
+    """
+        Method to parse CLI arguments and execute commands accordingly
+        Args : None
+        Return : None
+    """
+    parser = argparse.ArgumentParser(description='Utility to upload an OVF package to vCD')
+
+    parser.add_argument("-v", "--version", action="version", version=str(get_version()),
+                        help="shows version of vCD Uploader tool")
+
+    parser.add_argument("ovf_file", action="store",
+                        help="filename of OVF file to upload to vCD")
+
+    parser.add_argument("-l", "--vcd_url", action="store",
+                        required=True,
+                        help="URL for vCD login (ie: https://vcd.local/")
+
+    parser.add_argument("-u", "--username", action="store",
+                        required=True,
+                        help="Username for vCD login")
+
+    parser.add_argument("-p", "--password", action="store",
+                        required=True,
+                        help="Password for vCD login")
+
+    parser.add_argument("-o", "--orgname", action="store",
+                        required=True,
+                        help="Organization name for vCD login")
+
+    args = parser.parse_args()
+
+    if args.ovf_file:
+        try:
+            uploader = OVFUploader(args.ovf_file,
+                                   vcd_url=args.vcd_url,
+                                   username=args.username,
+                                   password=args.password,
+                                   orgname=args.orgname)
+            uploader.make_catalog()
+            uploader.upload_ovf()
+            uploader.wait_for_task_completion()
+        except Exception as exp:
+            print(exp)
+            exit(1)
+
+
+if __name__ == "__main__":
+    execute_cli()
index f74acb1..1804a1d 100644 (file)
@@ -1,5 +1,5 @@
 ##
-# Copyright 2016-2017 VMware Inc.
+# Copyright 2016-2019 VMware Inc.
 # This file is part of ETSI OSM
 # All Rights Reserved.
 #
@@ -19,6 +19,7 @@
 # contact:  osslegalrouting@vmware.com
 ##
 
+
 This README file explains how to use OVF Converter Tool to generate OVF file from .qcow2, .img (raw) disk images.
 
 CONTENTS OF THIS FILE
@@ -35,9 +36,14 @@ o Release History
 
 Introduction
 ==================
-OVF Converter Tool is a Command Line Interface (CLI) basically designed to generate OVF files from disk image such as .qcow2, and .img (raw format) which are other than .vmdk. 
-Given a path to .qcow2 image this tool can generate .vmdk and .ovf files.
-User can optionally specify name and location of ovf file. Also, one can use command line options to give disk size (GB), memory (MB), number of cpus, OS type, disk controller required for VM which will get deployed using generated OVF.
+OVF Converter Tool is a Command Line Interface (CLI) basically designed to generate OVF files from disk image such as
+.qcow2, and .img (raw format) which are other than .vmdk.  Given a path to .qcow2 image this tool can generate .vmdk
+and .ovf files.
+
+The user can optionally specify name and location of ovf file. Also, one can use command line options to give disk
+size (GB), memory (MB), number of cpus, OS type, disk controller required for VM which will get deployed using
+generated OVF.
+
 Generated OVF file can be used to deploy VM in Vmware vSphere or vCloud Director.
 
 Note- Currently this tool supports only Ubuntu platform.
@@ -47,17 +53,16 @@ Tool Requirements
 ==================
 
 This tool requires the following software package:
-o      apt-get package manager
-o      qemu-utils
-o      python 2.7
-o      python-lxml
-o      libxml2-dev 
-o      libxslt-dev 
-o      python-dev 
-o      python-pip
-        
-Install.sh script in this folder will install all of these
-software packages.
+o    apt-get package manager
+o    qemu-utils
+o    python 2.7
+o    python-lxml
+o    libxml2-dev
+o    libxslt-dev
+o    python-dev
+o    python-pip
+
+Install.sh script in this folder will install all of these software packages.
 
 
 Installation
@@ -68,35 +73,35 @@ Follow below setups for installation of OVF Converter Tool.
    chmod a+x install.sh
 2. Run install.sh script as:
    ./install.sh
-   
+
    Sample output -
-               #################################################################
-               #####             Installing Require Packages             #####
-               #################################################################
-               Hit:1 http://us.archive.ubuntu.com/ubuntu xenial InRelease
-               Get:2 http://us.archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]
-               Get:3 http://security.ubuntu.com/ubuntu xenial-security InRelease [102 kB]
-               Get:4 http://us.archive.ubuntu.com/ubuntu xenial-backports InRelease [102 kB]
-               Fetched 306 kB in 1s (286 kB/s)
-               Reading package lists... Done
-               Reading package lists... Done
-               Building dependency tree
-               Reading state information... Done
-               Note, selecting 'libxslt1-dev' instead of 'libxslt-dev'
-               libxslt1-dev is already the newest version (1.1.28-2.1).
-               python-dev is already the newest version (2.7.11-1).
-               python-lxml is already the newest version (3.5.0-1build1).
-               libxml2-dev is already the newest version (2.9.3+dfsg1-1ubuntu0.1).
-
-               t version (1:2.5+dfsg-5ubuntu10.6).
-               0 upgraded, 0 newly installed, 0 to remove and 72 not upgraded.
-
-               #################################################################
-               #####             Done                                #####
-               #################################################################
-               root@ubuntu:/home/vmware/OVF_converter#
-               root@ubuntu:/home/vmware/OVF_converter#
-     
+        #################################################################
+        #####             Installing Require Packages             #####
+        #################################################################
+        Hit:1 http://us.archive.ubuntu.com/ubuntu xenial InRelease
+        Get:2 http://us.archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]
+        Get:3 http://security.ubuntu.com/ubuntu xenial-security InRelease [102 kB]
+        Get:4 http://us.archive.ubuntu.com/ubuntu xenial-backports InRelease [102 kB]
+        Fetched 306 kB in 1s (286 kB/s)
+        Reading package lists... Done
+        Reading package lists... Done
+        Building dependency tree
+        Reading state information... Done
+        Note, selecting 'libxslt1-dev' instead of 'libxslt-dev'
+        libxslt1-dev is already the newest version (1.1.28-2.1).
+        python-dev is already the newest version (2.7.11-1).
+        python-lxml is already the newest version (3.5.0-1build1).
+        libxml2-dev is already the newest version (2.9.3+dfsg1-1ubuntu0.1).
+
+        t version (1:2.5+dfsg-5ubuntu10.6).
+        0 upgraded, 0 newly installed, 0 to remove and 72 not upgraded.
+
+        #################################################################
+        #####             Done                                #####
+        #################################################################
+        root@ubuntu:/home/vmware/OVF_converter#
+        root@ubuntu:/home/vmware/OVF_converter#
+
 3. Now tool is installed at /usr/local/bin and available for all users
 4. User can access commands of OVF Generator Tool as:
     ovf_converter path [output location] [ovf name][memory][cpu][disk][ostype][disk_controller]
@@ -104,67 +109,69 @@ Follow below setups for installation of OVF Converter Tool.
 
 Usage
 ===================
-o      Get version of tool as:
-
-       Command -      ovf_converter -v
-       Sample output -
-                               root@ubuntu:/home/vmware/OVF_converter# ovf_converter -v
-                               1.0 - Initial Realse
-                               root@ubuntu:/home/vmware/OVF_converter#
-
-o      See all command line options of tool as:
-       Command -       ovf_converter -h
-       Sample output -
-                               root@ubuntu:/home/vmware/OVF_converter#
-                               root@ubuntu:/home/vmware/OVF_converter# ovf_converter -h
-                               Usage: ovf_converter_cli.py [-h] [-v] [-o OUTPUT_LOCATION] [-n OVF_NAME]
+o    Get version of tool as:
+
+    Command -      ovf_converter -v
+    Sample output -
+                root@ubuntu:/home/vmware/OVF_converter# ovf_converter -v
+                1.0 - Initial Realse
+                root@ubuntu:/home/vmware/OVF_converter#
+
+o    See all command line options of tool as:
+    Command -       ovf_converter -h
+    Sample output -
+                root@ubuntu:/home/vmware/OVF_converter#
+                root@ubuntu:/home/vmware/OVF_converter# ovf_converter -h
+                Usage: ovf_converter_cli.py [-h] [-v] [-o OUTPUT_LOCATION] [-n OVF_NAME]
                             [-m MEMORY] [-c CPU] [-d DISK] [-s OSTYPE]
-                            [-dc DISK_CONTROLLER] [--cdrom]
+                            [-dc DISK_CONTROLLER] [--cdrom] [-w 14]
                             path
 
-                               OVF converter to convert .qcow2 or raw image into OVF
-                               
-                               positional arguments:
-                                 path                  absolute path to source image which will get convert
-                                                       into ovf
-                               
-                               optional arguments:
-                                 -h, --help            show this help message and exit
-                                 -v, --version         shows version of OVF Converter tool
-                                 -o OUTPUT_LOCATION, --output_location OUTPUT_LOCATION
-                                                       location where created OVF will be kept. This location
-                                                       should have write access. If not given file will get
-                                                       created at source location (optional)
-                                 -n OVF_NAME, --ovf_name OVF_NAME
-                                                       name of output ovf file. If not given source image
-                                                       name will be used (optional)
-                                 -m MEMORY, --memory MEMORY
-                                                       required memory for VM in MB (default 1 GB)(optional)
-                                 -c CPU, --cpu CPU     required number of virtual cpus for VM (default 1 cpu)
-                                                       (optional)
-                                 -d DISK, --disk DISK  required size of disk for VM in GB (default as
-                                                       in source disk img) (optional)
-                                 -s OSTYPE, --osType OSTYPE
-                                                       required operating system type as specified in user
-                                                       document (default os type other 32 bit) (optional)
-                                 -dc DISK_CONTROLLER, --disk_Controller DISK_CONTROLLER
-                                                       required disk controller type (default controller SCSI
-                                                       with lsilogicsas) (SATA, IDE, Paravirtual, Buslogic,
-                                                       lsilogic, lsilogicsas) (optional)
-                                 --cdrom               whether to include a cd/dvd device (optional) 
-
-                                 
-o      Create OVF file from qcow2 or raw disk image as:
-       Command -     ovf_converter /home/vmware/centos_ovf/CentOS-7-x86_64-GenericCloud-1503.qcow2 -n centos_qcow2.ovf -m 2048 -c 4 -d 10 -s "Centos 32-bit" -dc "SATA"
-       Sample output -
-                               root@ubuntu:/home/vmware/OVF_converter# ovf_converter /home/vmware/centos_ovf/CentOS-7-x86_64-GenericCloud-1503.qcow2 -n centos_qcow2.ovf -m 2048 -c 4 -d 10
-                               #### Start OVF conversion ####
-                               Getting source image information
-                               Converting source disk image to .vmdk                                                                         
-                               .....................................................
-                               Creating OVF
-                               Output OVF is at:  /home/vmware/centos_ovf/centos_qcow2.ovf
-                               #### Completed OVF conversion ####
+                OVF converter to convert .qcow2 or raw image into OVF
+
+                positional arguments:
+                  path                  absolute path to source image which will get convert
+                                        into ovf
+
+                optional arguments:
+                  -h, --help            show this help message and exit
+                  -v, --version         shows version of OVF Converter tool
+                  -o OUTPUT_LOCATION, --output_location OUTPUT_LOCATION
+                                        location where created OVF will be kept. This location
+                                        should have write access. If not given file will get
+                                        created at source location (optional)
+                  -n OVF_NAME, --ovf_name OVF_NAME
+                                        name of output ovf file. If not given source image
+                                        name will be used (optional)
+                  -m MEMORY, --memory MEMORY
+                                        required memory for VM in MB (default 1 GB)(optional)
+                  -c CPU, --cpu CPU     required number of virtual cpus for VM (default 1 cpu)
+                                        (optional)
+                  -d DISK, --disk DISK  required size of disk for VM in GB (default as
+                                        in source disk img) (optional)
+                  -s OSTYPE, --osType OSTYPE
+                                        required operating system type as specified in user
+                                        document (default os type other 32 bit) (optional)
+                  -dc DISK_CONTROLLER, --disk_Controller DISK_CONTROLLER
+                                        required disk controller type (default controller SCSI
+                                        with lsilogicsas) (SATA, IDE, Paravirtual, Buslogic,
+                                        lsilogic, lsilogicsas) (optional)
+                  --cdrom               whether to include a cd/dvd device (optional)
+                  -hw VERSION, --hwversion VERSION
+                                        VMware ESXi hardware family version (optional)
+
+
+o    Create OVF file from qcow2 or raw disk image as:
+    Command -     ovf_converter /home/vmware/centos_ovf/CentOS-7-x86_64-GenericCloud-1503.qcow2 -n centos_qcow2.ovf -m 2048 -c 4 -d 10 -s "Centos 32-bit" -dc "SATA"
+    Sample output -
+                root@ubuntu:/home/vmware/OVF_converter# ovf_converter /home/vmware/centos_ovf/CentOS-7-x86_64-GenericCloud-1503.qcow2 -n centos_qcow2.ovf -m 2048 -c 4 -d 10
+                #### Start OVF conversion ####
+                Getting source image information
+                Converting source disk image to .vmdk
+                .....................................................
+                Creating OVF
+                Output OVF is at:  /home/vmware/centos_ovf/centos_qcow2.ovf
+                #### Completed OVF conversion ####
 
 
 Trouble shooting
@@ -179,4 +186,15 @@ Release History
 Version 1.0
 -------------
 
-Initial release  
+Initial release
+
+Version 1.1
+-------------
+
+Adds support for cdrom
+
+Version 1.2
+-------------
+
+Adds support for hardware version
+Improves progress indicator
diff --git a/tools/OVF_converter/uploader.py b/tools/OVF_converter/uploader.py
new file mode 100644 (file)
index 0000000..3702d38
--- /dev/null
@@ -0,0 +1,220 @@
+# #
+# Copyright 2019 VMware Inc.
+# This file is part of ETSI OSM
+# All Rights Reserved.
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact:  osslegalrouting@vmware.com
+# #
+
+import logging
+from lxml import etree
+import os
+from pyvcloud.vcd.client import BasicLoginCredentials, Client, QueryResultFormat, ResourceType, TaskStatus
+from pyvcloud.vcd.exceptions import EntityNotFoundException, InternalServerException
+from pyvcloud.vcd.org import Org
+import sys
+import tarfile
+import time
+
+MODULE_DIR = os.path.dirname(__file__)
+
+# Set logger
+LOG_FILE = os.path.join(MODULE_DIR, "logs/ovf_uploader.log")
+os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
+logger = logging.getLogger(__name__)
+file_handler = logging.FileHandler(LOG_FILE)
+file_handler.setLevel(logging.DEBUG)
+formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+file_handler.setFormatter(formatter)
+logger.addHandler(file_handler)
+stdout_handler = logging.StreamHandler(sys.stdout)
+stdout_handler.setLevel(logging.INFO)
+logger.addHandler(stdout_handler)
+logger.setLevel(10)
+logging.captureWarnings(True)
+
+__version__ = "1.0"
+__description__ = "Initial Release"
+
+
+def get_version():
+    """ get version of this application"""
+    version = str(__version__) + " - " + str(__description__)
+    return version
+
+
+def report_progress(bytes_written, total_size):
+    percent_complete = int((bytes_written * 100) / total_size)
+    print("{}% complete  \r".format(percent_complete), end='')
+
+
+class OVFUploader(object):
+    """ Class to convert input image into OVF format """
+
+    def __init__(self, ovf_file, vcd_url=None, username=None, password=None, orgname=None):
+        self.ovf_file = os.path.abspath(ovf_file)
+        self.vcd_url = vcd_url
+        self.username = username
+        self.password = password
+        self.orgname = orgname
+        try:
+            client = Client(self.vcd_url, verify_ssl_certs=False)
+            client.set_highest_supported_version()
+            client.set_credentials(BasicLoginCredentials(self.username, self.orgname,
+                                                         self.password))
+            logger.info("Logged into {} using version {}".format(self.vcd_url, client.get_api_version()))
+            self.client = client
+            self.org = Org(self.client, resource=self.client.get_org())
+
+        except Exception as exp:
+            problem = Exception("Failed to connect to vCD at {}, org {}, username {}:\n{}".format(
+                self.vcd_url, self.orgname, self.username, exp))
+            logger.error(problem)
+            raise problem
+
+        try:
+            # Retrieve the VM name from the OVF.  We will use this as both the image and catalog name
+            OVF_tree = etree.parse(self.ovf_file)
+            root = OVF_tree.getroot()
+            nsmap = {k: v for k, v in root.nsmap.items() if k}
+            nsmap["xmlns"] = "http://schemas.dmtf.org/ovf/envelope/1"
+
+            virtuasystem = root.find('xmlns:VirtualSystem', nsmap)
+            name_tag = virtuasystem.find('xmlns:Name', nsmap)
+            self.image_name = name_tag.text
+            info_tag = virtuasystem.find('xmlns:Info', nsmap)
+            self.image_description = info_tag.text
+
+            references = root.find('xmlns:References', nsmap)
+            file = references.find('xmlns:File', nsmap)
+            self.vmdk_file = "{}/{}".format(
+                os.path.dirname(self.ovf_file),
+                file.attrib['{http://schemas.dmtf.org/ovf/envelope/1}href'])
+            logger.info("Loaded VM {}: {}".format(self.image_name, self.image_description))
+
+        except Exception as exp:
+            problem = Exception("Failed to fetch VirtualSystem Name element from OVF {}:\n{}".format(
+                self.ovf_file, exp))
+            logger.error(problem)
+            raise problem
+
+    def make_catalog(self):
+        try:
+            try:
+                catalog = self.org.get_catalog(self.image_name)
+                self.catalog_id = catalog.attrib['id'].split(':')[-1]
+            except EntityNotFoundException:
+                logger.info("Creating a new catalog entry {} in vCD".format(self.image_name))
+                result = self.org.create_catalog(self.image_name, self.image_description)
+                if result is None:
+                    raise Exception("Failed to create new catalog entry")
+                self.catalog_id = result.attrib['id'].split(':')[-1]
+                self.org.reload()
+
+            logger.debug("Using catalog {}, id {}".format(self.image_name, self.catalog_id))
+
+        except Exception as exp:
+            problem = Exception("Failed to fetch catalog for {}:\n{} ".format(self.image_name, exp))
+            logger.error(problem)
+            raise problem
+
+    def upload_ovf(self):
+
+        try:
+            # Check if the content already exists:
+            items = self.org.list_catalog_items(self.image_name)
+            for item in items:
+                if item['name'] == self.image_name:
+                    logger.info("Removing old version from catalog")
+                    try:
+                        self.org.delete_catalog_item(self.image_name, self.image_name)
+                    except InternalServerException as exp:
+                        problem = Exception(
+                            "Cannot delete vAppTemplate {}. Please check in vCD if "
+                            "the content is still being imported into the catalog".format(
+                                self.image_name))
+                        raise problem
+
+            # Create a single OVA bundle
+            ova_tarfilename, _ = os.path.splitext(self.ovf_file)
+            ova_tarfilename += '.ova'
+            ova = tarfile.open(name=ova_tarfilename,
+                               mode='w')
+            ova.add(self.ovf_file, arcname=os.path.basename(self.ovf_file))
+            ova.add(self.vmdk_file, arcname=os.path.basename(self.vmdk_file))
+            ova.close()
+            logger.info("Uploading content to vCD")
+            self.org.upload_ovf(self.image_name,
+                                ova_tarfilename,
+                                item_name=self.image_name,
+                                description=self.image_description,
+                                callback=report_progress)
+        except Exception as exp:
+            problem = Exception("Failed to upload OVF {}:\n{} ".format(self.ovf_file, exp))
+            logger.error(problem)
+            raise problem
+        finally:
+            if os.path.exists(ova_tarfilename):
+                os.remove(ova_tarfilename)
+
+    def wait_for_task_completion(self):
+
+        logger.info("Importing content to vCD")
+        try:
+
+            query = self.client.get_typed_query(
+                query_type_name=ResourceType.TASK.value,
+                qfilter='ownerName==' + self.username + ';(status==queued,status==preRunning,status==running)',
+                query_result_format=QueryResultFormat.REFERENCES)
+
+            upload_task = None
+            tasks = list(query.execute())
+            for task in tasks:
+                if task.get('name') == 'VDC_UPLOAD_OVF_CONTENTS':
+                    upload_task = self.client.get_resource(task.get('href'))
+                    break
+
+            bad_statuses = [
+                TaskStatus.ABORTED,
+                TaskStatus.CANCELED,
+                TaskStatus.ERROR
+            ]
+
+        except Exception as exp:
+            problem = Exception("Failed to import OVF {}:\n{} ".format(self.ovf_file, exp))
+            logger.error(problem)
+            raise problem
+
+        while(True):
+            task_status = upload_task.get('status').lower()
+            if(hasattr(upload_task, 'Progress')):
+                print("{}% complete  \r".format(upload_task.Progress), end='')
+
+            for status in bad_statuses:
+                if task_status == status.value.lower():
+                    problem = Exception(
+                        "vCD failed to import OVF {}:\n{}: {} ".format(self.ovf_file,
+                                                                       task_status,
+                                                                       upload_task.Error.get('Message')))
+                    logger.error(problem)
+                    raise problem
+            if task_status == str(TaskStatus.SUCCESS.value).lower():
+                break
+
+            time.sleep(2)
+            upload_task = self.client.get_resource(upload_task.get('href'))
+
+        logger.info("OVF upload and import complete, content is ready to use")
index 4f3f0e7..834068d 100755 (executable)
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 
-##
+# #
 # Copyright 2016-2017 VMware Inc.
 # This file is part of ETSI OSM
 # All Rights Reserved.
 #
 # For those usages not covered by the Apache License, Version 2.0 please
 # contact:  osslegalrouting@vmware.com
-##
+# #
 
-
-from xml.etree import ElementTree as XmlElementTree
-from pyvcloud.vcd.client import BasicLoginCredentials,Client
-from pyvcloud.vcd.vdc import VDC
-from pyvcloud.vcd.org import Org
-import sys,os
 import logging
+import os
+from progressbar import Percentage, Bar, ETA, FileTransferSpeed, ProgressBar
+from pyvcloud.vcd.client import BasicLoginCredentials, Client
+from pyvcloud.vcd.org import Org
+import re
 import requests
+import sys
 import time
-import re
-import hashlib
-from progressbar import Percentage, Bar, ETA, FileTransferSpeed, ProgressBar
-
+from xml.etree import ElementTree as XmlElementTree
 
 API_VERSION = '5.6'
 
+
 class vCloudconfig(object):
-    def __init__(self, host=None, user=None, password=None,orgname=None, logger=None):
+
+    def __init__(self, host=None, user=None, password=None, orgname=None, logger=None):
         self.url = host
         self.user = user
         self.password = password
@@ -55,12 +54,12 @@ class vCloudconfig(object):
 
         try:
             self.logger.debug("Logging in to a vcd {} as user {}".format(self.org,
-                                                                       self.user))
+                                                                         self.user))
             client = Client(self.url, verify_ssl_certs=False)
             client.set_credentials(BasicLoginCredentials(self.user, self.org, self.password))
-        except:
+        except Exception:
             raise Exception("Can't connect to a vCloud director org: "
-                                                     "{} as user: {}".format(self.org, self.user))
+                            "{} as user: {}".format(self.org, self.user))
 
         return client
 
@@ -84,19 +83,19 @@ class vCloudconfig(object):
 
         self.logger.debug("get_catalog_id_from_path() client requesting {} ".format(path))
 
-        dirpath, filename = os.path.split(path)
-        flname, file_extension = os.path.splitext(path)
+        _, filename = os.path.split(path)
+        _, file_extension = os.path.splitext(path)
         if file_extension != '.ovf':
             self.logger.debug("Wrong file extension {} connector support only OVF container.".format(file_extension))
             raise Exception("Wrong container.  vCloud director supports only OVF.")
 
         self.logger.debug("File name {} Catalog Name {} file path {} ".format(filename,
-                                                                          catalog_name,
-                                                                                 path))
+                                                                              catalog_name,
+                                                                              path))
         try:
             client = self.connect()
             if not client:
-                raise Exception("Failed to connect vCD") 
+                raise Exception("Failed to connect vCD")
             org = Org(client, resource=client.get_org())
             catalogs = org.list_catalogs()
         except Exception as exp:
@@ -109,7 +108,7 @@ class vCloudconfig(object):
             if result is None:
                 raise Exception("Failed to create new catalog {} ".format(catalog_name))
             result = self.upload_ovf(org=org, catalog_name=catalog_name, image_name=filename.split(".")[0],
-                               media_file_name=path, description='medial_file_name', progress=progress)
+                                     media_file_name=path, description='medial_file_name', progress=progress)
             if not result:
                 raise Exception("Failed to create vApp template for catalog {} ".format(catalog_name))
             return self.get_catalogid(catalog_name, catalogs)
@@ -118,18 +117,18 @@ class vCloudconfig(object):
                 # search for existing catalog if we find same name we return ID
                 if catalog['name'] == catalog_name:
                     self.logger.debug("Found existing catalog entry for {} "
-                                        "catalog id {}".format(catalog_name,
-                                  self.get_catalogid(catalog_name, catalogs)))
+                                      "catalog id {}".format(catalog_name,
+                                                             self.get_catalogid(catalog_name, catalogs)))
                     return self.get_catalogid(catalog_name, catalogs)
 
         # if we didn't find existing catalog we create a new one and upload image.
         self.logger.debug("Creating new catalog entry {} - {}".format(catalog_name, catalog_name))
-        result = org.create_catalog(catalog_name, catalog_name) 
+        result = org.create_catalog(catalog_name, catalog_name)
         if result is None:
             raise Exception("Failed to create new catalog {} ".format(catalog_name))
 
         result = self.upload_ovf(org=org, catalog_name=catalog_name, image_name=filename.split(".")[0],
-                               media_file_name=path, description='medial_file_name', progress=progress)
+                                 media_file_name=path, description='medial_file_name', progress=progress)
         if not result:
             raise Exception("Failed create vApp template for catalog {} ".format(catalog_name))
 
@@ -176,21 +175,23 @@ class vCloudconfig(object):
                     continue
                 catalog_href = "{}/api/catalog/{}/action/upload".format(self.url, catalog['id'])
                 data = """
-                <UploadVAppTemplateParams name="{}" xmlns="http://www.vmware.com/vcloud/v1.5" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"><Description>{} vApp Template</Description></UploadVAppTemplateParams>
+                <UploadVAppTemplateParams name="{}" xmlns="http://www.vmware.com/vcloud/v1.5"
+                xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1">
+                <Description>{} vApp Template</Description></UploadVAppTemplateParams>
                 """.format(catalog_name, description)
 
                 if client:
-                    headers = {'Accept':'application/*+xml;version=' + API_VERSION,
-                           'x-vcloud-authorization': client._session.headers['x-vcloud-authorization']}
+                    headers = {'Accept': 'application/*+xml;version=' + API_VERSION,
+                               'x-vcloud-authorization': client._session.headers['x-vcloud-authorization']}
                     headers['Content-Type'] = 'application/vnd.vmware.vcloud.uploadVAppTemplateParams+xml'
 
                 response = requests.post(url=catalog_href,
-                                          headers=headers,
-                                                data=data,
-                                             verify=False)
+                                         headers=headers,
+                                         data=data,
+                                         verify=False)
                 if response.status_code != 201:
                     self.logger.debug("Failed to create vApp template")
-                    raise Exception("Failed to create vApp template")   
+                    raise Exception("Failed to create vApp template")
 
                 if response.status_code == requests.codes.created:
                     catalogItem = XmlElementTree.fromstring(response.content)
@@ -200,45 +201,48 @@ class vCloudconfig(object):
                     template = href
 
                     response = requests.get(url=href,
-                                    headers=headers,
-                                       verify=False)
+                                            headers=headers,
+                                            verify=False)
                     if response.status_code == requests.codes.ok:
                         headers['Content-Type'] = 'Content-Type text/xml'
-                        result = re.search('rel="upload:default"\shref="(.*?\/descriptor.ovf)"',response.content)
+                        result = re.search('rel="upload:default"\shref="(.*?\/descriptor.ovf)"', response.content)
                         if result:
                             transfer_href = result.group(1)
 
                         response = requests.put(url=transfer_href, headers=headers,
-                                        data=open(media_file_name, 'rb'),
-                                                            verify=False)
+                                                data=open(media_file_name, 'rb'),
+                                                verify=False)
 
                         if response.status_code != requests.codes.ok:
                             self.logger.debug(
-                                "Failed create vApp template for catalog name {} and image {}".format(catalog_name,
-                                                                                                      media_file_name))
+                                "Failed create vApp template for catalog name {} and image {}".format(
+                                    catalog_name,
+                                    media_file_name))
                             return False
 
                     # TODO fix this with aync block
                     time.sleep(5)
 
-                    self.logger.debug("vApp template for catalog name {} and image {}".format(catalog_name, media_file_name))
+                    self.logger.debug("vApp template for catalog name {} and image {}".format(
+                        catalog_name,
+                        media_file_name))
 
                     # uploading VMDK file
                     # check status of OVF upload and upload remaining files.
 
                     response = requests.get(url=template,
-                                         headers=headers,
+                                            headers=headers,
                                             verify=False)
 
                     if response.status_code == requests.codes.ok:
-                        result = re.search('rel="upload:default"\s*href="(.*?vmdk)"',response.content)
+                        result = re.search('rel="upload:default"\s*href="(.*?vmdk)"', response.content)
                         if result:
                             link_href = result.group(1)
                         # we skip ovf since it already uploaded.
                         if 'ovf' in link_href:
                             continue
                         # The OVF file and VMDK must be in a same directory
-                        head, tail = os.path.split(media_file_name)
+                        head, _ = os.path.split(media_file_name)
                         file_vmdk = head + '/' + link_href.split("/")[-1]
                         if not os.path.isfile(file_vmdk):
                             return False
@@ -248,7 +252,7 @@ class vCloudconfig(object):
                         hrefvmdk = link_href
                         if progress:
                             widgets = ['Uploading file: ', Percentage(), ' ', Bar(), ' ', ETA(), ' ',
-                                           FileTransferSpeed()]
+                                       FileTransferSpeed()]
                             progress_bar = ProgressBar(widgets=widgets, maxval=statinfo.st_size).start()
 
                         bytes_transferred = 0
@@ -260,9 +264,9 @@ class vCloudconfig(object):
                                     bytes_transferred, len(my_bytes) - 1, statinfo.st_size)
                                 headers['Content-Length'] = str(len(my_bytes))
                                 response = requests.put(url=hrefvmdk,
-                                                         headers=headers,
-                                                         data=my_bytes,
-                                                         verify=False)
+                                                        headers=headers,
+                                                        data=my_bytes,
+                                                        verify=False)
                                 if response.status_code == requests.codes.ok:
                                     bytes_transferred += len(my_bytes)
                                     if progress:
@@ -270,7 +274,7 @@ class vCloudconfig(object):
                                 else:
                                     self.logger.debug(
                                         'file upload failed with error: [%s] %s' % (response.status_code,
-                                                                                        response.content))
+                                                                                    response.content))
 
                                     f.close()
                                     return False
@@ -282,18 +286,21 @@ class vCloudconfig(object):
                 else:
                     self.logger.debug("Failed retrieve vApp template for catalog name {} for OVF {}".
                                       format(catalog_name, media_file_name))
-                    return False 
+                    return False
         except Exception as exp:
             self.logger.debug("Failed while uploading OVF to catalog {} for OVF file {} with Exception {}"
-                .format(catalog_name,media_file_name, exp))
+                              .format(catalog_name, media_file_name, exp))
             raise Exception(
                 "Failed while uploading OVF to catalog {} for OVF file {} with Exception {}"
-                .format(catalog_name,media_file_name, exp))  
+                .format(catalog_name, media_file_name, exp))
         self.logger.debug("Failed to retrieve catalog name {} for OVF file {}".format(catalog_name, media_file_name))
-        return False   
+        return False
+
 
 if __name__ == "__main__":
 
+    print("This file is deprecated.  Please use ovf_uplader_cli instead.")
+
     # vmware vcloud director credentials
     vcd_hostname = sys.argv[1]
     vcd_username = sys.argv[2]
@@ -302,17 +309,7 @@ if __name__ == "__main__":
     # OVF image path to be upload to vCD
     ovf_file_path = sys.argv[5]
 
-    # changing virtual system type in ovf file
-    fh = open(ovf_file_path,'r')
-    content = fh.read()
-    content = content.replace('<vssd:VirtualSystemType>vmx-7','<vssd:VirtualSystemType>vmx-07')
-    fh.close() 
-    fh1 = open(ovf_file_path,'w')
-    fh1.write(content)
-    fh1.close() 
-     
-
-    logging.basicConfig(filename='ovf_upload.log',level=logging.DEBUG)
+    logging.basicConfig(filename='ovf_upload.log', level=logging.DEBUG)
     logger = logging.getLogger(__name__)
 
     obj = vCloudconfig(vcd_hostname, vcd_username, vcd_password, orgname, logger)
@@ -322,10 +319,11 @@ if __name__ == "__main__":
 
     # Get image name from cirros vnfd
     cirros_yaml = '../descriptor-packages/vnfd/cirros_vnf/src/cirros_vnfd.yaml'
-    rh = open(cirros_yaml,'r')
-    match = re.search("image:\s'(.*?)'\n",rh.read())
-    if match: catalog = match.group(1)
+    rh = open(cirros_yaml, 'r')
+    match = re.search("image:\s'(.*?)'\n", rh.read())
+    if match:
+        catalog = match.group(1)
 
     if file_extension == '.ovf':
         obj.get_catalog_id_from_path(catalog_name=catalog, path=ovf_file_path,
-                                                               progress=True)
+                                     progress=True)