Make hostvars more dynamic again to improve performance with large inventories
Fixes #12477
This commit is contained in:
parent
82b33c381f
commit
12df9f2e31
3 changed files with 45 additions and 15 deletions
|
@ -66,6 +66,7 @@ class Group:
|
||||||
self.__init__()
|
self.__init__()
|
||||||
self.name = data.get('name')
|
self.name = data.get('name')
|
||||||
self.vars = data.get('vars', dict())
|
self.vars = data.get('vars', dict())
|
||||||
|
self.depth = data.get('depth', 0)
|
||||||
|
|
||||||
parent_groups = data.get('parent_groups', [])
|
parent_groups = data.get('parent_groups', [])
|
||||||
for parent_data in parent_groups:
|
for parent_data in parent_groups:
|
||||||
|
|
|
@ -43,7 +43,8 @@ from ansible.utils.vars import combine_vars
|
||||||
from ansible.vars.hostvars import HostVars
|
from ansible.vars.hostvars import HostVars
|
||||||
from ansible.vars.unsafe_proxy import UnsafeProxy
|
from ansible.vars.unsafe_proxy import UnsafeProxy
|
||||||
|
|
||||||
CACHED_VARS = dict()
|
VARIABLE_CACHE = dict()
|
||||||
|
HOSTVARS_CACHE = dict()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from __main__ import display
|
from __main__ import display
|
||||||
|
@ -85,6 +86,28 @@ class VariableManager:
|
||||||
self._inventory = None
|
self._inventory = None
|
||||||
self._omit_token = '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest()
|
self._omit_token = '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest()
|
||||||
|
|
||||||
|
def __getstate__(self):
|
||||||
|
data = dict(
|
||||||
|
fact_cache = self._fact_cache.copy(),
|
||||||
|
np_fact_cache = self._nonpersistent_fact_cache.copy(),
|
||||||
|
vars_cache = self._vars_cache.copy(),
|
||||||
|
extra_vars = self._extra_vars.copy(),
|
||||||
|
host_vars_files = self._host_vars_files.copy(),
|
||||||
|
group_vars_files = self._group_vars_files.copy(),
|
||||||
|
omit_token = self._omit_token,
|
||||||
|
)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def __setstate__(self, data):
|
||||||
|
self._fact_cache = data.get('fact_cache', defaultdict(dict))
|
||||||
|
self._nonpersistent_fact_cache = data.get('np_fact_cache', defaultdict(dict))
|
||||||
|
self._vars_cache = data.get('vars_cache', defaultdict(dict))
|
||||||
|
self._extra_vars = data.get('extra_vars', dict())
|
||||||
|
self._host_vars_files = data.get('host_vars_files', defaultdict(dict))
|
||||||
|
self._group_vars_files = data.get('group_vars_files', defaultdict(dict))
|
||||||
|
self._omit_token = data.get('omit_token', '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest())
|
||||||
|
self._inventory = None
|
||||||
|
|
||||||
def _get_cache_entry(self, play=None, host=None, task=None):
|
def _get_cache_entry(self, play=None, host=None, task=None):
|
||||||
play_id = "NONE"
|
play_id = "NONE"
|
||||||
if play:
|
if play:
|
||||||
|
@ -157,9 +180,9 @@ class VariableManager:
|
||||||
|
|
||||||
debug("in VariableManager get_vars()")
|
debug("in VariableManager get_vars()")
|
||||||
cache_entry = self._get_cache_entry(play=play, host=host, task=task)
|
cache_entry = self._get_cache_entry(play=play, host=host, task=task)
|
||||||
if cache_entry in CACHED_VARS and use_cache:
|
if cache_entry in VARIABLE_CACHE and use_cache:
|
||||||
debug("vars are cached, returning them now")
|
debug("vars are cached, returning them now")
|
||||||
return CACHED_VARS[cache_entry]
|
return VARIABLE_CACHE[cache_entry]
|
||||||
|
|
||||||
all_vars = defaultdict(dict)
|
all_vars = defaultdict(dict)
|
||||||
|
|
||||||
|
@ -289,7 +312,12 @@ class VariableManager:
|
||||||
all_vars['groups'][group_name] = [h.name for h in group.get_hosts()]
|
all_vars['groups'][group_name] = [h.name for h in group.get_hosts()]
|
||||||
|
|
||||||
if include_hostvars:
|
if include_hostvars:
|
||||||
hostvars = HostVars(vars_manager=self, play=play, inventory=self._inventory, loader=loader)
|
hostvars_cache_entry = self._get_cache_entry(play=play)
|
||||||
|
if hostvars_cache_entry in HOSTVARS_CACHE:
|
||||||
|
hostvars = HOSTVARS_CACHE[hostvars_cache_entry]
|
||||||
|
else:
|
||||||
|
hostvars = HostVars(play=play, inventory=self._inventory, loader=loader, variable_manager=self)
|
||||||
|
HOSTVARS_CACHE[hostvars_cache_entry] = hostvars
|
||||||
all_vars['hostvars'] = hostvars
|
all_vars['hostvars'] = hostvars
|
||||||
|
|
||||||
if task:
|
if task:
|
||||||
|
@ -355,7 +383,7 @@ class VariableManager:
|
||||||
if 'hostvars' in all_vars and host:
|
if 'hostvars' in all_vars and host:
|
||||||
all_vars['vars'] = all_vars['hostvars'][host.get_name()]
|
all_vars['vars'] = all_vars['hostvars'][host.get_name()]
|
||||||
|
|
||||||
#CACHED_VARS[cache_entry] = all_vars
|
#VARIABLE_CACHE[cache_entry] = all_vars
|
||||||
|
|
||||||
debug("done with get_vars()")
|
debug("done with get_vars()")
|
||||||
return all_vars
|
return all_vars
|
||||||
|
|
|
@ -34,9 +34,11 @@ __all__ = ['HostVars']
|
||||||
class HostVars(collections.Mapping):
|
class HostVars(collections.Mapping):
|
||||||
''' A special view of vars_cache that adds values from the inventory when needed. '''
|
''' A special view of vars_cache that adds values from the inventory when needed. '''
|
||||||
|
|
||||||
def __init__(self, vars_manager, play, inventory, loader):
|
def __init__(self, play, inventory, variable_manager, loader):
|
||||||
self._lookup = {}
|
self._lookup = dict()
|
||||||
self._loader = loader
|
self._loader = loader
|
||||||
|
self._play = play
|
||||||
|
self._variable_manager = variable_manager
|
||||||
|
|
||||||
hosts = inventory.get_hosts(ignore_limits_and_restrictions=True)
|
hosts = inventory.get_hosts(ignore_limits_and_restrictions=True)
|
||||||
|
|
||||||
|
@ -49,9 +51,6 @@ class HostVars(collections.Mapping):
|
||||||
has_localhost = True
|
has_localhost = True
|
||||||
break
|
break
|
||||||
|
|
||||||
# we don't use the method in inventory to create the implicit host,
|
|
||||||
# because it also adds it to the 'ungrouped' group, and we want to
|
|
||||||
# avoid any side-effects
|
|
||||||
if not has_localhost:
|
if not has_localhost:
|
||||||
new_host = Host(name='localhost')
|
new_host = Host(name='localhost')
|
||||||
new_host.set_variable("ansible_python_interpreter", sys.executable)
|
new_host.set_variable("ansible_python_interpreter", sys.executable)
|
||||||
|
@ -60,14 +59,15 @@ class HostVars(collections.Mapping):
|
||||||
hosts.append(new_host)
|
hosts.append(new_host)
|
||||||
|
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
self._lookup[host.name] = vars_manager.get_vars(loader=loader, play=play, host=host, include_hostvars=False)
|
self._lookup[host.name] = host
|
||||||
|
|
||||||
def __getitem__(self, host_name):
|
def __getitem__(self, host_name):
|
||||||
|
|
||||||
if host_name not in self._lookup:
|
if host_name not in self._lookup:
|
||||||
return j2undefined
|
return j2undefined
|
||||||
|
|
||||||
data = self._lookup.get(host_name)
|
host = self._lookup.get(host_name)
|
||||||
|
data = self._variable_manager.get_vars(loader=self._loader, host=host, play=self._play, include_hostvars=False)
|
||||||
templar = Templar(variables=data, loader=self._loader)
|
templar = Templar(variables=data, loader=self._loader)
|
||||||
return templar.template(data, fail_on_undefined=False)
|
return templar.template(data, fail_on_undefined=False)
|
||||||
|
|
||||||
|
@ -84,9 +84,10 @@ class HostVars(collections.Mapping):
|
||||||
raise NotImplementedError('HostVars does not support len. hosts entries are discovered dynamically as needed')
|
raise NotImplementedError('HostVars does not support len. hosts entries are discovered dynamically as needed')
|
||||||
|
|
||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
data = self._lookup.copy()
|
return dict(loader=self._loader, lookup=self._lookup, play=self._play, var_manager=self._variable_manager)
|
||||||
return dict(loader=self._loader, data=data)
|
|
||||||
|
|
||||||
def __setstate__(self, data):
|
def __setstate__(self, data):
|
||||||
self._lookup = data.get('data')
|
self._play = data.get('play')
|
||||||
self._loader = data.get('loader')
|
self._loader = data.get('loader')
|
||||||
|
self._lookup = data.get('lookup')
|
||||||
|
self._variable_manager = data.get('var_manager')
|
||||||
|
|
Loading…
Reference in a new issue