@ -2,6 +2,7 @@
from __future__ import absolute_import , print_function
import os
import time
from lib . cloud import (
CloudProvider ,
@ -12,6 +13,10 @@ from lib.cloud import (
from lib . util import (
find_executable ,
display ,
ApplicationError ,
is_shippable ,
ConfigParser ,
SubprocessError ,
)
from lib . docker_util import (
@ -22,6 +27,14 @@ from lib.docker_util import (
get_docker_container_id ,
)
from lib . core_ci import (
AnsibleCoreCI ,
)
from lib . http import (
HttpClient ,
)
class VcenterProvider ( CloudProvider ) :
""" VMware vcenter/esx plugin. Sets up cloud resources for tests. """
@ -40,50 +53,83 @@ class VcenterProvider(CloudProvider):
self . image = ' quay.io/ansible/vcenter-test-container:1.5.0 '
self . container_name = ' '
# VMWare tests can be run on govcsim or baremetal, either BYO with a static config
# file or hosted in worldstream. Using an env var value of 'worldstream' with appropriate
# CI credentials will deploy a dynamic baremetal environment. The simulator is the default
# if no other config if provided.
self . vmware_test_platform = os . environ . get ( ' VMWARE_TEST_PLATFORM ' , ' ' )
self . aci = None
self . insecure = False
self . endpoint = ' '
self . hostname = ' '
self . port = 443
def filter ( self , targets , exclude ) :
""" Filter out the cloud tests when the necessary config and resources are not available.
: type targets : tuple [ TestTarget ]
: type exclude : list [ str ]
"""
docker = find_executable ( ' docker ' , required = False )
if self . vmware_test_platform is None or ' govcsim ' :
docker = find_executable ( ' docker ' , required = False )
if docker :
return
if docker :
return
skip = ' cloud/ %s / ' % self . platform
skipped = [ target . name for target in targets if skip in target . aliases ]
if skipped :
exclude . append ( skip )
display . warning ( ' Excluding tests marked " %s " which require the " docker " command: %s '
% ( skip . rstrip ( ' / ' ) , ' , ' . join ( skipped ) ) )
else :
if os . path . isfile ( self . config_static_path ) :
return
aci = self . _create_ansible_core_ci ( )
skip = ' cloud/ %s / ' % self . platform
skipped = [ target . name for target in targets if skip in target . aliases ]
if os . path . isfile ( aci . ci_key ) :
return
if skipped :
exclude . append ( skip )
display . warning ( ' Excluding tests marked " %s " which require the " docker " command: %s '
% ( skip . rstrip ( ' / ' ) , ' , ' . join ( skipped ) ) )
if is_shippable ( ) :
return
super ( VcenterProvider , self ) . filter ( targets , exclude )
def setup ( self ) :
""" Setup the cloud resource before delegation and register a cleanup callback. """
super ( VcenterProvider , self ) . setup ( )
self . _set_cloud_config ( ' vmware_test_platform ' , self . vmware_test_platform )
if self . _use_static_config ( ) :
self . _setup_static ( )
elif self . vmware_test_platform == ' worldstream ' :
self . _setup_dynamic_baremetal ( )
else :
self . _setup_dynamic ( )
self . _setup_dynamic _simulator ( )
def get_docker_run_options ( self ) :
""" Get any additional options needed when delegating tests to a docker container.
: rtype : list [ str ]
"""
if self . managed :
if self . managed and self . vmware_test_platform != ' worldstream ' :
return [ ' --link ' , self . DOCKER_SIMULATOR_NAME ]
return [ ]
def cleanup ( self ) :
""" Clean up the cloud resource and any temporary configuration files after tests complete. """
if self . vmware_test_platform == ' worldstream ' :
if self . aci :
self . aci . stop ( )
if self . container_name :
docker_rm ( self . args , self . container_name )
super ( VcenterProvider , self ) . cleanup ( )
def _setup_dynamic ( self ) :
def _setup_dynamic _simulator ( self ) :
""" Create a vcenter simulator using docker. """
container_id = get_docker_container_id ( )
@ -139,8 +185,62 @@ class VcenterProvider(CloudProvider):
ipaddress = results [ 0 ] [ ' NetworkSettings ' ] [ ' IPAddress ' ]
return ipaddress
def _setup_dynamic_baremetal ( self ) :
""" Request Esxi credentials through the Ansible Core CI service. """
display . info ( ' Provisioning %s cloud environment. ' % self . platform ,
verbosity = 1 )
config = self . _read_config_template ( )
aci = self . _create_ansible_core_ci ( )
if not self . args . explain :
response = aci . start ( )
self . aci = aci
config = self . _populate_config_template ( config , response )
self . _write_config ( config )
def _create_ansible_core_ci ( self ) :
"""
: rtype : AnsibleCoreCI
"""
return AnsibleCoreCI ( self . args , ' vmware ' , ' vmware ' ,
persist = False , stage = self . args . remote_stage ,
provider = ' vmware ' )
def _setup_static ( self ) :
raise NotImplementedError ( )
parser = ConfigParser ( )
parser . read ( self . config_static_path )
self . endpoint = parser . get ( ' DEFAULT ' , ' vcenter_hostname ' )
self . port = parser . get ( ' DEFAULT ' , ' vcenter_port ' )
if parser . get ( ' DEFAULT ' , ' vmware_validate_certs ' ) . lower ( ) in ( ' no ' , ' false ' ) :
self . insecure = True
self . _wait_for_service ( )
def _wait_for_service ( self ) :
""" Wait for the VCenter service endpoint to accept connections. """
if self . args . explain :
return
client = HttpClient ( self . args , always = True , insecure = self . insecure )
endpoint = ' https:// %s : %s ' % ( self . endpoint , self . port )
for i in range ( 1 , 30 ) :
display . info ( ' Waiting for VCenter service: %s ' % endpoint , verbosity = 1 )
try :
client . get ( endpoint )
return
except SubprocessError :
pass
time . sleep ( 10 )
raise ApplicationError ( ' Timeout waiting for VCenter service. ' )
class VcenterEnvironment ( CloudEnvironment ) :
@ -149,13 +249,29 @@ class VcenterEnvironment(CloudEnvironment):
"""
: rtype : CloudEnvironmentConfig
"""
env_vars = dict (
VCENTER_HOST = self . _get_cloud_config ( ' vcenter_host ' ) ,
)
vmware_test_platform = self . _get_cloud_config ( ' vmware_test_platform ' )
if vmware_test_platform == ' worldstream ' :
parser = ConfigParser ( )
parser . read ( self . config_path )
# Most of the test cases use ansible_vars, but we plan to refactor these
# to use env_vars, output both for now
env_vars = dict (
( key . upper ( ) , value ) for key , value in parser . items ( ' DEFAULT ' ) )
ansible_vars = dict (
resource_prefix = self . resource_prefix ,
)
ansible_vars . update ( dict ( parser . items ( ' DEFAULT ' ) ) )
ansible_vars = dict (
vcsim = self . _get_cloud_config ( ' vcenter_host ' ) ,
)
else :
env_vars = dict (
VCENTER_HOST = self . _get_cloud_config ( ' vcenter_host ' ) ,
)
ansible_vars = dict (
vcsim = self . _get_cloud_config ( ' vcenter_host ' ) ,
)
return CloudEnvironmentConfig (
env_vars = env_vars ,