From: Cédric Ollivier <cedric.ollivier@orange.com>
Date: Wed, 14 Feb 2018 15:02:53 +0000 (+0100)
Subject: Get properly env vars or their default values
X-Git-Tag: opnfv-6.0.0~149
X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F21%2F52221%2F4;p=functest.git

Get properly env vars or their default values

It defines env.get() as an unique way to get Functest env vars or
their default values. It can be considered as a wrapper above os.environ.

It enforces backward compatibility via CONST which mustn't be used
for that purpose. It should be noted that it also stops using CONST
for getting OpenStack env vars.

Change-Id: I333dc1afbc0123166a7eaff8b551370098efa341
Signed-off-by: Cédric Ollivier <cedric.ollivier@orange.com>
---

diff --git a/docs/testing/user/configguide/configguide.rst b/docs/testing/user/configguide/configguide.rst
index c4d9a6d77..f65810817 100644
--- a/docs/testing/user/configguide/configguide.rst
+++ b/docs/testing/user/configguide/configguide.rst
@@ -197,9 +197,13 @@ Environment variables
 
 Several environement variables may be specified:
   * INSTALLER_TYPE=(apex|compass|daisy|fuel|joid)
+  * INSTALLER_IP=<Specific IP Address>
   * DEPLOY_SCENARIO=<vim>-<controller>-<nfv_feature>-<ha_mode>
 
 
+INSTALLER_IP is required by Barometer in order to access the installer node and
+the deployment.
+
 The format for the DEPLOY_SCENARIO env variable can be described as follows:
   * vim: (os|k8s) = OpenStack or Kubernetes
   * controller is one of ( nosdn | odl )
diff --git a/functest/api/resources/v1/testcases.py b/functest/api/resources/v1/testcases.py
index bc21c6fae..064661c8b 100644
--- a/functest/api/resources/v1/testcases.py
+++ b/functest/api/resources/v1/testcases.py
@@ -11,22 +11,23 @@
 Resources to handle testcase related requests
 """
 
+import ConfigParser
 import logging
 import os
 import re
-import pkg_resources
 import socket
 import uuid
 
-import ConfigParser
 from flask import jsonify
 from flasgger.utils import swag_from
+import pkg_resources
 
 from functest.api.base import ApiResource
 from functest.api.common import api_utils, thread
 from functest.cli.commands.cli_testcase import Testcase
 from functest.api.database.v1.handlers import TasksHandler
 from functest.utils.constants import CONST
+from functest.utils import env
 import functest.utils.functest_utils as ft_utils
 
 LOGGER = logging.getLogger(__name__)
@@ -127,10 +128,10 @@ class V1Testcase(ApiResource):
             result = 'FAIL'
 
         env_info = {
-            'installer': os.environ.get('INSTALLER_TYPE', None),
-            'scenario': os.environ.get('DEPLOY_SCENARIO', None),
-            'build_tag': os.environ.get('BUILD_TAG', None),
-            'ci_loop': os.environ.get('CI_LOOP', 'daily')
+            'installer': env.get('INSTALLER_TYPE'),
+            'scenario': env.get('DEPLOY_SCENARIO'),
+            'build_tag': env.get('BUILD_TAG'),
+            'ci_loop': env.get('CI_LOOP')
         }
         result = {
             'task_id': args.get('task_id'),
diff --git a/functest/ci/run_tests.py b/functest/ci/run_tests.py
index ff38720d6..ca101ce6b 100644
--- a/functest/ci/run_tests.py
+++ b/functest/ci/run_tests.py
@@ -27,8 +27,9 @@ import enum
 import prettytable
 import yaml
 
-import functest.ci.tier_builder as tb
-import functest.core.testcase as testcase
+from functest.ci import tier_builder
+from functest.core import testcase
+from functest.utils import env
 
 LOGGER = logging.getLogger('functest.ci.run_tests')
 ENV_FILE = "/home/opnfv/functest/conf/env_file"
@@ -88,9 +89,9 @@ class Runner(object):
         self.overall_result = Result.EX_OK
         self.clean_flag = True
         self.report_flag = False
-        self.tiers = tb.TierBuilder(
-            os.environ.get('INSTALLER_TYPE', None),
-            os.environ.get('DEPLOY_SCENARIO', None),
+        self.tiers = tier_builder.TierBuilder(
+            env.get('INSTALLER_TYPE'),
+            env.get('DEPLOY_SCENARIO'),
             pkg_resources.resource_filename('functest', 'ci/testcases.yaml'))
 
     @staticmethod
@@ -207,7 +208,7 @@ class Runner(object):
             field_names=['tiers', 'order', 'CI Loop', 'description',
                          'testcases'])
         for tier in self.tiers.get_tiers():
-            ci_loop = os.environ.get('CI_LOOP', 'daily')
+            ci_loop = env.get('CI_LOOP')
             if (tier.get_tests() and
                     re.search(ci_loop, tier.get_ci_loop()) is not None):
                 tiers_to_run.append(tier)
@@ -247,7 +248,7 @@ class Runner(object):
                     LOGGER.error("Unknown test case or tier '%s', or not "
                                  "supported by the given scenario '%s'.",
                                  kwargs['test'],
-                                 os.environ.get('DEPLOY_SCENARIO', ""))
+                                 env.get('DEPLOY_SCENARIO'))
                     LOGGER.debug("Available tiers are:\n\n%s",
                                  self.tiers)
                     return Result.EX_ERROR
@@ -270,7 +271,7 @@ class Runner(object):
             field_names=['env var', 'value'])
         for env_var in ['INSTALLER_TYPE', 'DEPLOY_SCENARIO', 'BUILD_TAG',
                         'CI_LOOP']:
-            msg.add_row([env_var, os.environ.get(env_var, "")])
+            msg.add_row([env_var, env.get(env_var)])
         LOGGER.info("Deployment description:\n\n%s\n", msg)
         msg = prettytable.PrettyTable(
             header_style='upper', padding_width=5,
diff --git a/functest/cli/commands/cli_env.py b/functest/cli/commands/cli_env.py
index f93ef612c..18c8895ae 100644
--- a/functest/cli/commands/cli_env.py
+++ b/functest/cli/commands/cli_env.py
@@ -8,21 +8,21 @@
 
 # pylint: disable=missing-docstring
 
-import os
-
 import click
 import prettytable
 import six
 
+from functest.utils import env
+
 
 class Env(object):  # pylint: disable=too-few-public-methods
 
     @staticmethod
     def show():
-        install_type = os.environ.get('INSTALLER_TYPE', 'Unknown')
-        scenario = os.environ.get('DEPLOY_SCENARIO', 'Unknown')
-        node = os.environ.get('NODE_NAME', 'Unknown')
-        build_tag = os.environ.get('BUILD_TAG', None)
+        install_type = env.get('INSTALLER_TYPE')
+        scenario = env.get('DEPLOY_SCENARIO')
+        node = env.get('NODE_NAME')
+        build_tag = env.get('BUILD_TAG')
         if build_tag:
             build_tag = build_tag.lstrip(
                 "jenkins-").lstrip("functest").lstrip("-")
diff --git a/functest/cli/commands/cli_tier.py b/functest/cli/commands/cli_tier.py
index 933d8cd63..3694c1ae7 100644
--- a/functest/cli/commands/cli_tier.py
+++ b/functest/cli/commands/cli_tier.py
@@ -8,21 +8,21 @@
 
 # pylint: disable=missing-docstring
 
-import os
 import pkg_resources
 
 import click
 
 from functest.ci import tier_builder
 from functest.utils import functest_utils
+from functest.utils import env
 
 
 class Tier(object):
 
     def __init__(self):
         self.tiers = tier_builder.TierBuilder(
-            os.environ['INSTALLER_TYPE'],
-            os.environ['DEPLOY_SCENARIO'],
+            env.get('INSTALLER_TYPE'),
+            env.get('DEPLOY_SCENARIO'),
             pkg_resources.resource_filename('functest', 'ci/testcases.yaml'))
 
     def list(self):
diff --git a/functest/core/testcase.py b/functest/core/testcase.py
index f0c6c9e9f..e8bb1409d 100644
--- a/functest/core/testcase.py
+++ b/functest/core/testcase.py
@@ -17,6 +17,7 @@ import re
 import requests
 
 from functest.utils import decorators
+from functest.utils import env
 
 
 import prettytable
@@ -180,14 +181,14 @@ class TestCase(object):
             assert self.case_name
             assert self.start_time
             assert self.stop_time
-            url = os.environ['TEST_DB_URL']
+            url = env.get('TEST_DB_URL')
             data = {"project_name": self.project_name,
                     "case_name": self.case_name,
                     "details": self.details}
-            data["installer"] = os.environ['INSTALLER_TYPE']
-            data["scenario"] = os.environ['DEPLOY_SCENARIO']
-            data["pod_name"] = os.environ['NODE_NAME']
-            data["build_tag"] = os.environ['BUILD_TAG']
+            data["installer"] = env.get('INSTALLER_TYPE')
+            data["scenario"] = env.get('DEPLOY_SCENARIO')
+            data["pod_name"] = env.get('NODE_NAME')
+            data["build_tag"] = env.get('BUILD_TAG')
             data["criteria"] = 'PASS' if self.is_successful(
                 ) == TestCase.EX_OK else 'FAIL'
             data["start_date"] = datetime.fromtimestamp(
@@ -197,7 +198,7 @@ class TestCase(object):
             try:
                 data["version"] = re.search(
                     TestCase._job_name_rule,
-                    os.environ['BUILD_TAG']).group(2)
+                    env.get('BUILD_TAG')).group(2)
             except Exception:  # pylint: disable=broad-except
                 data["version"] = "unknown"
             req = requests.post(
@@ -210,9 +211,6 @@ class TestCase(object):
             self.__logger.exception(
                 "Please run test before publishing the results")
             return TestCase.EX_PUSH_TO_DB_ERROR
-        except KeyError as exc:
-            self.__logger.error("Please set env var: " + str(exc))
-            return TestCase.EX_PUSH_TO_DB_ERROR
         except requests.exceptions.HTTPError:
             self.__logger.exception("The HTTP request raises issues")
             return TestCase.EX_PUSH_TO_DB_ERROR
diff --git a/functest/energy/energy.py b/functest/energy/energy.py
index c7da8f046..d5f6871d0 100644
--- a/functest/energy/energy.py
+++ b/functest/energy/energy.py
@@ -12,13 +12,14 @@
 
 import json
 import logging
-import os
 import traceback
 
 from functools import wraps
 import requests
 from six.moves import urllib
 
+from functest.utils import env
+
 
 def finish_session(current_scenario):
     """Finish a recording session."""
@@ -93,14 +94,15 @@ class EnergyRecorder(object):
         # Singleton pattern for energy_recorder_api static member
         # Load only if not previouly done
         if EnergyRecorder.energy_recorder_api is None:
-            assert os.environ['NODE_NAME']
-            assert os.environ["ENERGY_RECORDER_API_URL"]
-            environment = os.environ['NODE_NAME']
-            energy_recorder_uri = os.environ["ENERGY_RECORDER_API_URL"]
+            assert env.get('NODE_NAME')
+            assert env.get('ENERGY_RECORDER_API_URL')
+            environment = env.get('NODE_NAME')
+            energy_recorder_uri = env.get(
+                'ENERGY_RECORDER_API_URL')
 
             # Creds
-            creds_usr = os.environ.get("ENERGY_RECORDER_API_USER", "")
-            creds_pass = os.environ.get("ENERGY_RECORDER_API_PASSWORD", "")
+            creds_usr = env.get("ENERGY_RECORDER_API_USER")
+            creds_pass = env.get("ENERGY_RECORDER_API_PASSWORD")
 
             uri_comp = "/recorders/environment/"
             uri_comp += urllib.parse.quote_plus(environment)
diff --git a/functest/opnfv_tests/openstack/rally/rally.py b/functest/opnfv_tests/openstack/rally/rally.py
index 2632fd398..add0f2437 100644
--- a/functest/opnfv_tests/openstack/rally/rally.py
+++ b/functest/opnfv_tests/openstack/rally/rally.py
@@ -29,6 +29,7 @@ from functest.energy import energy
 from functest.opnfv_tests.openstack.snaps import snaps_utils
 from functest.opnfv_tests.openstack.tempest import conf_utils
 from functest.utils.constants import CONST
+from functest.utils import env
 
 from snaps.config.flavor import FlavorConfig
 from snaps.config.image import ImageConfig
@@ -218,8 +219,8 @@ class RallyBase(testcase.TestCase):
             with open(RallyBase.BLACKLIST_FILE, 'r') as black_list_file:
                 black_list_yaml = yaml.safe_load(black_list_file)
 
-            installer_type = os.getenv('INSTALLER_TYPE', None)
-            deploy_scenario = os.getenv('DEPLOY_SCENARIO', None)
+            installer_type = env.get('INSTALLER_TYPE')
+            deploy_scenario = env.get('DEPLOY_SCENARIO')
             if (bool(installer_type) and bool(deploy_scenario) and
                     'scenario' in black_list_yaml.keys()):
                 for item in black_list_yaml['scenario']:
diff --git a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py b/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
index 9d31f426c..216d9acf6 100644
--- a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
+++ b/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
@@ -15,6 +15,7 @@ import logging
 from functest.core import unit
 from functest.opnfv_tests.openstack.snaps import snaps_utils
 from functest.utils.constants import CONST
+from functest.utils import env
 
 from snaps.openstack import create_flavor
 
@@ -44,7 +45,7 @@ class SnapsTestRunner(unit.Suite):
             CONST.__getattribute__('snaps_use_floating_ips') == 'True')
         self.use_keystone = (
             CONST.__getattribute__('snaps_use_keystone') == 'True')
-        scenario = CONST.__getattribute__('DEPLOY_SCENARIO')
+        scenario = env.get('DEPLOY_SCENARIO')
 
         self.flavor_metadata = None
         if 'ovs' in scenario or 'fdio' in scenario:
diff --git a/functest/opnfv_tests/openstack/snaps/snaps_utils.py b/functest/opnfv_tests/openstack/snaps/snaps_utils.py
index 6bc50ad60..59bd063c1 100644
--- a/functest/opnfv_tests/openstack/snaps/snaps_utils.py
+++ b/functest/opnfv_tests/openstack/snaps/snaps_utils.py
@@ -10,6 +10,7 @@
 """Some common utils wrapping snaps functions """
 
 from functest.utils.constants import CONST
+from functest.utils import env
 
 from snaps.openstack.tests import openstack_tests
 from snaps.openstack.utils import neutron_utils, nova_utils
@@ -24,8 +25,8 @@ def get_ext_net_name(os_creds):
     """
     neutron = neutron_utils.neutron_client(os_creds)
     ext_nets = neutron_utils.get_external_networks(neutron)
-    if hasattr(CONST, 'EXTERNAL_NETWORK'):
-        extnet_config = CONST.__getattribute__('EXTERNAL_NETWORK')
+    if env.get('EXTERNAL_NETWORK'):
+        extnet_config = env.get('EXTERNAL_NETWORK')
         for ext_net in ext_nets:
             if ext_net.name == extnet_config:
                 return extnet_config
diff --git a/functest/opnfv_tests/openstack/tempest/conf_utils.py b/functest/opnfv_tests/openstack/tempest/conf_utils.py
index f128784c2..09471fa52 100644
--- a/functest/opnfv_tests/openstack/tempest/conf_utils.py
+++ b/functest/opnfv_tests/openstack/tempest/conf_utils.py
@@ -14,13 +14,14 @@ import ConfigParser
 import logging
 import fileinput
 import os
-import pkg_resources
 import shutil
 import subprocess
 
+import pkg_resources
 import yaml
 
 from functest.utils.constants import CONST
+from functest.utils import env
 import functest.utils.functest_utils as ft_utils
 
 
@@ -51,7 +52,7 @@ TEST_ACCOUNTS_FILE = pkg_resources.resource_filename(
     'functest',
     'opnfv_tests/openstack/tempest/custom_tests/test_accounts.yaml')
 
-CI_INSTALLER_TYPE = CONST.__getattribute__('INSTALLER_TYPE')
+CI_INSTALLER_TYPE = env.get('INSTALLER_TYPE')
 
 """ logging configuration """
 LOGGER = logging.getLogger(__name__)
@@ -60,7 +61,7 @@ LOGGER = logging.getLogger(__name__)
 def create_rally_deployment():
     """Create new rally deployment"""
     # set the architecture to default
-    pod_arch = os.getenv("POD_ARCH", None)
+    pod_arch = env.get("POD_ARCH")
     arch_filter = ['aarch64']
 
     if pod_arch and pod_arch in arch_filter:
@@ -294,10 +295,9 @@ def configure_tempest_update_params(tempest_conf_file, network_name=None,
         config.set('compute', 'min_compute_nodes', compute_cnt)
         config.set('compute-feature-enabled', 'live_migration', True)
 
-    config.set('identity', 'region',
-               CONST.__getattribute__('OS_REGION_NAME'))
-    identity_api_version = os.getenv(
-        "OS_IDENTITY_API_VERSION", os.getenv("IDENTITY_API_VERSION"))
+    config.set('identity', 'region', os.environ.get('OS_REGION_NAME'))
+    identity_api_version = os.environ.get(
+        "OS_IDENTITY_API_VERSION", os.environ.get("IDENTITY_API_VERSION"))
     if identity_api_version == '3':
         auth_version = 'v3'
         config.set('identity-feature-enabled', 'api_v2', False)
@@ -310,11 +310,11 @@ def configure_tempest_update_params(tempest_conf_file, network_name=None,
     config.set('object-storage', 'operator_role',
                CONST.__getattribute__('tempest_object_storage_operator_role'))
 
-    if CONST.__getattribute__('OS_ENDPOINT_TYPE') is not None:
+    if os.environ.get('OS_ENDPOINT_TYPE') is not None:
         config.set('identity', 'v3_endpoint_type',
-                   CONST.__getattribute__('OS_ENDPOINT_TYPE'))
+                   os.environ.get('OS_ENDPOINT_TYPE'))
 
-    if CONST.__getattribute__('OS_ENDPOINT_TYPE') is not None:
+    if os.environ.get('OS_ENDPOINT_TYPE') is not None:
         sections = config.sections()
         services_list = ['compute',
                          'volume',
@@ -327,7 +327,7 @@ def configure_tempest_update_params(tempest_conf_file, network_name=None,
             if service not in sections:
                 config.add_section(service)
             config.set(service, 'endpoint_type',
-                       CONST.__getattribute__('OS_ENDPOINT_TYPE'))
+                       os.environ.get('OS_ENDPOINT_TYPE'))
 
     LOGGER.debug('Add/Update required params defined in tempest_conf.yaml '
                  'into tempest.conf file')
diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py
index 56705fc0f..c19c8d9d2 100644
--- a/functest/opnfv_tests/openstack/tempest/tempest.py
+++ b/functest/opnfv_tests/openstack/tempest/tempest.py
@@ -26,6 +26,7 @@ from functest.core import testcase
 from functest.opnfv_tests.openstack.snaps import snaps_utils
 from functest.opnfv_tests.openstack.tempest import conf_utils
 from functest.utils.constants import CONST
+from functest.utils import env
 import functest.utils.functest_utils as ft_utils
 
 from snaps.config.flavor import FlavorConfig
@@ -128,8 +129,8 @@ class TempestCommon(testcase.TestCase):
         result_file = open(conf_utils.TEMPEST_LIST, 'w')
         black_tests = []
         try:
-            installer_type = CONST.__getattribute__('INSTALLER_TYPE')
-            deploy_scenario = CONST.__getattribute__('DEPLOY_SCENARIO')
+            installer_type = env.get('INSTALLER_TYPE')
+            deploy_scenario = env.get('DEPLOY_SCENARIO')
             if bool(installer_type) * bool(deploy_scenario):
                 # if INSTALLER_TYPE and DEPLOY_SCENARIO are set we read the
                 # file
@@ -405,7 +406,7 @@ class TempestResourcesManager(object):
 
     def _create_flavor(self, name):
         """Create flavor for tests."""
-        scenario = CONST.__getattribute__('DEPLOY_SCENARIO')
+        scenario = env.get('DEPLOY_SCENARIO')
         flavor_metadata = None
         if 'ovs' in scenario or 'fdio' in scenario:
             flavor_metadata = create_flavor.MEM_PAGE_SIZE_LARGE
@@ -463,7 +464,7 @@ class TempestResourcesManager(object):
 
         if use_custom_flavors:
             LOGGER.info("Creating 2nd flavor for Tempest suite")
-            scenario = CONST.__getattribute__('DEPLOY_SCENARIO')
+            scenario = env.get('DEPLOY_SCENARIO')
             if 'ovs' in scenario or 'fdio' in scenario:
                 CONST.__setattr__('openstack_flavor_ram', 1024)
             name = CONST.__getattribute__(
diff --git a/functest/opnfv_tests/openstack/vping/vping_base.py b/functest/opnfv_tests/openstack/vping/vping_base.py
index 7170101f5..fae5db2d4 100644
--- a/functest/opnfv_tests/openstack/vping/vping_base.py
+++ b/functest/opnfv_tests/openstack/vping/vping_base.py
@@ -18,6 +18,7 @@ import uuid
 from functest.core import testcase
 from functest.opnfv_tests.openstack.snaps import snaps_utils
 from functest.utils.constants import CONST
+from functest.utils import env
 
 from snaps.config.flavor import FlavorConfig
 from snaps.config.network import NetworkConfig, SubnetConfig
@@ -135,7 +136,7 @@ class VPingBase(testcase.TestCase):
 
         self.logger.info(
             "Creating flavor with name: '%s'", self.flavor_name)
-        scenario = getattr(CONST, 'DEPLOY_SCENARIO')
+        scenario = env.get('DEPLOY_SCENARIO')
         flavor_metadata = None
         flavor_ram = 512
         if 'ovs' in scenario or 'fdio' in scenario:
diff --git a/functest/opnfv_tests/sdn/odl/odl.py b/functest/opnfv_tests/sdn/odl/odl.py
index 4c33c4957..705f39dab 100644
--- a/functest/opnfv_tests/sdn/odl/odl.py
+++ b/functest/opnfv_tests/sdn/odl/odl.py
@@ -31,6 +31,7 @@ from snaps.openstack.utils import keystone_utils
 from functest.core import robotframework
 from functest.opnfv_tests.openstack.snaps import snaps_utils
 from functest.utils import constants
+from functest.utils import env
 
 __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
 
@@ -165,9 +166,7 @@ class ODLTests(robotframework.RobotFramework):
             kwargs['odlrestconfport'] = '8181'
             kwargs['odlusername'] = 'admin'
             kwargs['odlpassword'] = 'admin'
-            installer_type = None
-            if 'INSTALLER_TYPE' in os.environ:
-                installer_type = os.environ['INSTALLER_TYPE']
+            installer_type = env.get('INSTALLER_TYPE')
             kwargs['osusername'] = os.environ['OS_USERNAME']
             kwargs['osuserdomainname'] = os.environ.get(
                 'OS_USER_DOMAIN_NAME', 'Default')
@@ -180,17 +179,17 @@ class ODLTests(robotframework.RobotFramework):
                 kwargs['odlwebport'] = '8181'
                 kwargs['odlrestconfport'] = '8282'
             elif installer_type == 'apex' or installer_type == 'netvirt':
-                kwargs['odlip'] = os.environ['SDN_CONTROLLER_IP']
+                kwargs['odlip'] = env.get('SDN_CONTROLLER_IP')
                 kwargs['odlwebport'] = '8081'
                 kwargs['odlrestconfport'] = '8081'
             elif installer_type == 'compass':
                 kwargs['odlrestconfport'] = '8080'
             elif installer_type == 'daisy':
-                kwargs['odlip'] = os.environ['SDN_CONTROLLER_IP']
+                kwargs['odlip'] = env.get('SDN_CONTROLLER_IP')
                 kwargs['odlwebport'] = '8181'
                 kwargs['odlrestconfport'] = '8087'
             else:
-                kwargs['odlip'] = os.environ['SDN_CONTROLLER_IP']
+                kwargs['odlip'] = env.get('SDN_CONTROLLER_IP')
         except KeyError as ex:
             self.__logger.error("Cannot run ODL testcases. "
                                 "Please check env var: "
diff --git a/functest/tests/unit/openstack/tempest/test_tempest.py b/functest/tests/unit/openstack/tempest/test_tempest.py
index 5d543ffcc..060a8a010 100644
--- a/functest/tests/unit/openstack/tempest/test_tempest.py
+++ b/functest/tests/unit/openstack/tempest/test_tempest.py
@@ -8,6 +8,7 @@
 # pylint: disable=missing-docstring
 
 import logging
+import os
 import unittest
 
 import mock
@@ -15,7 +16,6 @@ import mock
 from functest.core import testcase
 from functest.opnfv_tests.openstack.tempest import tempest
 from functest.opnfv_tests.openstack.tempest import conf_utils
-from functest.utils.constants import CONST
 
 from snaps.openstack.os_credentials import OSCreds
 
@@ -115,8 +115,8 @@ class OSTempestTesting(unittest.TestCase):
             mock.patch.object(self.tempestcommon, 'read_file',
                               return_value=['test1', 'test2']):
             conf_utils.TEMPEST_BLACKLIST = Exception
-            CONST.__setattr__('INSTALLER_TYPE', 'installer_type')
-            CONST.__setattr__('DEPLOY_SCENARIO', 'deploy_scenario')
+            os.environ['INSTALLER_TYPE'] = 'installer_type'
+            os.environ['DEPLOY_SCENARIO'] = 'deploy_scenario'
             self.tempestcommon.apply_tempest_blacklist()
             obj = mock_open()
             obj.write.assert_any_call('test1\n')
@@ -131,8 +131,8 @@ class OSTempestTesting(unittest.TestCase):
                               return_value=['test1', 'test2']), \
             mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
                        'yaml.safe_load', return_value=item_dict):
-            CONST.__setattr__('INSTALLER_TYPE', 'installer_type')
-            CONST.__setattr__('DEPLOY_SCENARIO', 'deploy_scenario')
+            os.environ['INSTALLER_TYPE'] = 'installer_type'
+            os.environ['DEPLOY_SCENARIO'] = 'deploy_scenario'
             self.tempestcommon.apply_tempest_blacklist()
             obj = mock_open()
             obj.write.assert_any_call('test1\n')
diff --git a/functest/tests/unit/utils/test_env.py b/functest/tests/unit/utils/test_env.py
new file mode 100644
index 000000000..064ff9880
--- /dev/null
+++ b/functest/tests/unit/utils/test_env.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2018 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import os
+import unittest
+
+from six.moves import reload_module
+
+from functest.utils import env
+from functest.utils import constants
+
+
+class EnvTesting(unittest.TestCase):
+    # pylint: disable=missing-docstring
+
+    def setUp(self):
+        os.environ['FOO'] = 'foo'
+        os.environ['BUILD_TAG'] = 'master'
+        os.environ['CI_LOOP'] = 'weekly'
+
+    def test_get_unset_unknown_env(self):
+        del os.environ['FOO']
+        self.assertEqual(env.get('FOO'), None)
+        # Backward compatibilty (waiting for SDNVPN and SFC)
+        reload_module(env)
+        with self.assertRaises(AttributeError):
+            getattr(env.ENV, 'FOO')
+        reload_module(constants)
+        with self.assertRaises(AttributeError):
+            getattr(constants.CONST, 'FOO')
+
+    def test_get_unknown_env(self):
+        self.assertEqual(env.get('FOO'), 'foo')
+        reload_module(env)
+        # Backward compatibilty (waiting for SDNVPN and SFC)
+        with self.assertRaises(AttributeError):
+            getattr(env.ENV, 'FOO')
+        reload_module(constants)
+        with self.assertRaises(AttributeError):
+            getattr(constants.CONST, 'FOO')
+
+    def test_get_unset_env(self):
+        del os.environ['CI_LOOP']
+        self.assertEqual(
+            env.get('CI_LOOP'), env.INPUTS['CI_LOOP'])
+        # Backward compatibilty (waiting for SDNVPN and SFC)
+        reload_module(env)
+        self.assertEqual(
+            getattr(env.ENV, 'CI_LOOP'), env.INPUTS['CI_LOOP'])
+        reload_module(constants)
+        self.assertEqual(
+            getattr(constants.CONST, 'CI_LOOP'),
+            env.INPUTS['CI_LOOP'])
+
+    def test_get_env(self):
+        self.assertEqual(
+            env.get('CI_LOOP'), 'weekly')
+        # Backward compatibilty (waiting for SDNVPN and SFC)
+        reload_module(env)
+        self.assertEqual(getattr(env.ENV, 'CI_LOOP'), 'weekly')
+        reload_module(constants)
+        self.assertEqual(getattr(constants.CONST, 'CI_LOOP'), 'weekly')
+
+    def test_get_unset_env2(self):
+        del os.environ['BUILD_TAG']
+        self.assertEqual(
+            env.get('BUILD_TAG'), env.INPUTS['BUILD_TAG'])
+        # Backward compatibilty (waiting for SDNVPN and SFC)
+        reload_module(env)
+        self.assertEqual(
+            getattr(env.ENV, 'BUILD_TAG'), env.INPUTS['BUILD_TAG'])
+        reload_module(constants)
+        self.assertEqual(
+            getattr(constants.CONST, 'BUILD_TAG'), env.INPUTS['BUILD_TAG'])
+
+    def test_get_env2(self):
+        self.assertEqual(env.get('BUILD_TAG'), 'master')
+        # Backward compatibilty (waiting for SDNVPN and SFC)
+        reload_module(env)
+        self.assertEqual(getattr(env.ENV, 'BUILD_TAG'), 'master')
+        reload_module(env)
+        self.assertEqual(getattr(constants.CONST, 'BUILD_TAG'), 'master')
+
+
+if __name__ == "__main__":
+    logging.disable(logging.CRITICAL)
+    unittest.main(verbosity=2)
diff --git a/functest/tests/unit/utils/test_functest_utils.py b/functest/tests/unit/utils/test_functest_utils.py
index dd34c90dc..9f8733bba 100644
--- a/functest/tests/unit/utils/test_functest_utils.py
+++ b/functest/tests/unit/utils/test_functest_utils.py
@@ -128,7 +128,7 @@ class FunctestUtilsTesting(unittest.TestCase):
             self.assertEqual(functest_utils.get_resolvconf_ns(),
                              self.test_ip[1:])
 
-    def _get_environ(self, var):
+    def _get_environ(self, var, *args):  # pylint: disable=unused-argument
         if var == 'INSTALLER_TYPE':
             return self.installer
         elif var == 'DEPLOY_SCENARIO':
diff --git a/functest/utils/config.py b/functest/utils/config.py
index c569856b1..61d8401c5 100644
--- a/functest/utils/config.py
+++ b/functest/utils/config.py
@@ -2,12 +2,13 @@
 
 # pylint: disable=missing-docstring
 
-import os
 import pkg_resources
 import yaml
 
 import six
 
+from functest.utils import env
+
 
 class Config(object):
     def __init__(self):
@@ -37,7 +38,7 @@ class Config(object):
             patch_file = yaml.safe_load(yfile)
 
         for key in patch_file:
-            if key in os.environ.get('DEPLOY_SCENARIO', ""):
+            if key in env.get('DEPLOY_SCENARIO'):
                 self.functest_yaml = dict(Config._merge_dicts(
                     self.functest_yaml, patch_file[key]))
 
@@ -64,7 +65,7 @@ class Config(object):
 CONF = Config()
 CONF.patch_file(pkg_resources.resource_filename(
     'functest', 'ci/config_patch.yaml'))
-if os.getenv("POD_ARCH", None) and os.getenv("POD_ARCH", None) in ['aarch64']:
+if env.get("POD_ARCH") in ['aarch64']:
     CONF.patch_file(pkg_resources.resource_filename(
         'functest', 'ci/config_aarch64_patch.yaml'))
 CONF.fill()
diff --git a/functest/utils/constants.py b/functest/utils/constants.py
index c19e0fc52..d8a1d54d1 100644
--- a/functest/utils/constants.py
+++ b/functest/utils/constants.py
@@ -2,6 +2,7 @@
 
 # pylint: disable=missing-docstring
 
+import pkg_resources
 import six
 
 from functest.utils import config
@@ -10,6 +11,9 @@ from functest.utils import env
 
 class Constants(object):  # pylint: disable=too-few-public-methods
 
+    CONFIG_FUNCTEST_YAML = pkg_resources.resource_filename(
+        'functest', 'ci/config_functest.yaml')
+
     def __init__(self):
         for attr_n, attr_v in six.iteritems(config.CONF.__dict__):
             setattr(self, attr_n, attr_v)
diff --git a/functest/utils/env.py b/functest/utils/env.py
index b626473a9..0c0515ba1 100644
--- a/functest/utils/env.py
+++ b/functest/utils/env.py
@@ -1,45 +1,46 @@
 #!/usr/bin/env python
 
+# Copyright (c) 2018 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
 # pylint: disable=missing-docstring
 
 import os
-import re
 
-import pkg_resources
 import six
 
+INPUTS = {
+    'EXTERNAL_NETWORK': None,
+    'CI_LOOP': 'daily',
+    'DEPLOY_SCENARIO': 'os-nosdn-nofeature-noha',
+    'INSTALLER_TYPE': None,
+    'SDN_CONTROLLER_IP': None,
+    'BUILD_TAG': None,
+    'NODE_NAME': None,
+    'POD_ARCH': None,
+    'TEST_DB_URL': 'http://testresults.opnfv.org/test/api/v1/results',
+    'ENERGY_RECORDER_API_URL': 'http://energy.opnfv.fr/resources',
+    'ENERGY_RECORDER_API_USER': '',
+    'ENERGY_RECORDER_API_PASSWORD': ''
+}
 
-class Environment(object):  # pylint: disable=too-few-public-methods
 
-    default_envs = {
-        'NODE_NAME': 'unknown_pod',
-        'DEPLOY_SCENARIO': 'os-nosdn-nofeature-noha',
-        'DEPLOY_TYPE': 'virt',
-        'INSTALLER_TYPE': None,
-        'BUILD_TAG': None,
-        'OS_ENDPOINT_TYPE': None,
-        'OS_AUTH_URL': None,
-        'CONFIG_FUNCTEST_YAML': pkg_resources.resource_filename(
-            'functest', 'ci/config_functest.yaml'),
-        'OS_INSECURE': '',
-        'OS_REGION_NAME': 'RegionOne'
-    }
+def get(env_var):
+    if env_var not in INPUTS.keys():
+        return os.environ.get(env_var, None)
+    return os.environ.get(env_var, INPUTS[env_var])
 
-    def __init__(self):
-        for key, value in six.iteritems(os.environ):
-            setattr(self, key, value)
-        for key, value in six.iteritems(self.default_envs):
-            if key not in os.environ:
-                setattr(self, key, value)
-        if 'CI_LOOP' not in os.environ:
-            self._set_ci_loop()
-
-    def _set_ci_loop(self):
-        if (getattr(self, "BUILD_TAG") and
-                re.search("daily", getattr(self, "BUILD_TAG"))):
-            setattr(self, "CI_LOOP", "daily")
-        else:
-            setattr(self, "CI_LOOP", "weekly")
 
+class Environment(object):  # pylint: disable=too-few-public-methods
+
+    # Backward compatibilty (waiting for SDNVPN and SFC)
+    def __init__(self):
+        for key, _ in six.iteritems(INPUTS):
+            setattr(self, key, get(key))
 
+# Backward compatibilty (waiting for SDNVPN and SFC)
 ENV = Environment()
diff --git a/functest/utils/functest_utils.py b/functest/utils/functest_utils.py
index e84a2b426..b31b392d7 100644
--- a/functest/utils/functest_utils.py
+++ b/functest/utils/functest_utils.py
@@ -11,7 +11,6 @@
 
 from __future__ import print_function
 import logging
-import os
 import re
 import shutil
 import subprocess
@@ -22,6 +21,7 @@ from six.moves import urllib
 import yaml
 
 from functest.utils import constants
+from functest.utils import env
 
 LOGGER = logging.getLogger(__name__)
 
@@ -90,8 +90,8 @@ def get_ci_envvars():
     Get the CI env variables
     """
     ci_env_var = {
-        "installer": os.environ.get('INSTALLER_TYPE'),
-        "scenario": os.environ.get('DEPLOY_SCENARIO')}
+        "installer": env.get('INSTALLER_TYPE'),
+        "scenario": env.get('DEPLOY_SCENARIO')}
     return ci_env_var
 
 
diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py
index b779997c9..98da48b8c 100644
--- a/functest/utils/openstack_utils.py
+++ b/functest/utils/openstack_utils.py
@@ -22,7 +22,7 @@ from novaclient import client as novaclient
 from keystoneclient import client as keystoneclient
 from neutronclient.neutron import client as neutronclient
 
-from functest.utils.constants import CONST
+from functest.utils import env
 import functest.utils.functest_utils as ft_utils
 
 logger = logging.getLogger(__name__)
@@ -659,8 +659,8 @@ def get_private_net(neutron_client):
 
 
 def get_external_net(neutron_client):
-    if (hasattr(CONST, 'EXTERNAL_NETWORK')):
-        return CONST.__getattribute__('EXTERNAL_NETWORK')
+    if (env.get('EXTERNAL_NETWORK')):
+        return env.get('EXTERNAL_NETWORK')
     for network in neutron_client.list_networks()['networks']:
         if network['router:external']:
             return network['name']
@@ -668,9 +668,9 @@ def get_external_net(neutron_client):
 
 
 def get_external_net_id(neutron_client):
-    if (hasattr(CONST, 'EXTERNAL_NETWORK')):
+    if (env.get('EXTERNAL_NETWORK')):
         networks = neutron_client.list_networks(
-            name=CONST.__getattribute__('EXTERNAL_NETWORK'))
+            name=env.get('EXTERNAL_NETWORK'))
         net_id = networks['networks'][0]['id']
         return net_id
     for network in neutron_client.list_networks()['networks']: