infra/plugins/filters.py
Sergey Bubnov (omg) d89c7ab77e prevent wrong behaviour when more than one dhcp on interfaces
firts we check that the VM has already get some IP address
and if so we just deploy as usual. If VM have no IP address
on any interface we throw all interfaces except first (eth0) to
the `empty vlan` that have no DHCP server enabled. VLAD ID defined
in environment variable. After network configuration inside VM we
restore propper VLAN IDs on all interfaces. This approach should help
in situations when DHCP available on more than one interfaces and those
interfaces configured as dhcp-clients, thus more than one default gw
will be configured with some metrics and all traffic will be routed
to the right one or will be not.
2019-06-27 13:21:48 +04:00

130 lines
3.6 KiB
Python

#!/usr/bin/env python
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase
from ansible.utils.listify import listify_lookup_plugin_terms
import collections
import re
import ipaddress
try:
import jmespath
HAS_LIB = True
except ImportError:
HAS_LIB = False
def dict_merge(dct, merge_dct):
""" Recursive dict merge. Inspired by :meth:``dict.update()``, instead of
updating only top-level keys, dict_merge recurses down into dicts nested
to an arbitrary depth, updating keys. The ``merge_dct`` is merged into
``dct``.
:param dct: dict onto which the merge is executed
:param merge_dct: dct merged into dct
:return: None
"""
for k, v in merge_dct.iteritems():
if (k in dct and isinstance(dct[k], dict)
and isinstance(merge_dct[k], collections.Mapping)):
dict_merge(dct[k], merge_dct[k])
else:
dct[k] = merge_dct[k]
def dict_inject(data, path, obj):
p = path.split('/')
p.remove('')
p.reverse()
c = obj
for n in p:
c = {n: c}
z = data.copy()
dict_merge(z, c)
return z
def to_nics_dict(src):
nics = {}
lo_pat = re.compile("^lo[0-9]{0,2}$")
for n in src:
if not lo_pat.match(n['name']):
addrs = []
if "ip-addresses" in n:
for a in n['ip-addresses']:
if a['ip-address-type'] != "ipv6":
addrs.append(u'%s/%s' % (a['ip-address'], a['prefix']))
nics[n['name']] = {"mac": n['hardware-address'],
"addrs": addrs}
return nics
def to_proxmox_net(src, vlan=None):
out = {}
ks = ['virtio', 'bridge', 'tag']
for k,v in src.items():
if k != 'eth0' and vlan:
v['tag'] = vlan
k = k.replace('eth','net')
[ v.pop(x, None) for x in set(v.keys()).difference(ks) ]
v.pop('ipv4', None) # remove unused key
if 'virtio' not in v.items():
res = "virtio,"
else:
res = ""
res = res + ','.join(map(lambda x:str('='.join(map(str,x))), v.items()))
out[k] = res
return out
def gen_nics_addrs(node, num):
res = node.copy()
for k, v in res['net'].items():
for i, a in enumerate(res['net'][k]['ipv4']):
interface = ipaddress.ip_interface(a)
addr = interface.ip + int(num)
cidr = interface.network.prefixlen
res['net'][k]['ipv4'][i] = '%s/%s' % (addr, cidr)
return res
def list_to_dict(src):
res = {}
for a in src:
k = list(a.keys())[0]
res[k] = a[k]
return res
def get_steps(node, steps_list):
res = []
for idx, ss in enumerate(steps_list):
for a in ss:
if node in a['binds']:
res.append("step%s" % idx)
return res
def filter_dict(src, pred):
p = eval(pred)
return { k: v for k, v in src.iteritems() if p(v)}
def format2(what, fmt):
return fmt % what
def domain2dn(domain):
return ','.join('DC=%s' % s for s in domain.split('.'))
class FilterModule(object):
''' Query filter '''
def filters(self):
return {
'dict_merge': dict_merge,
'dict_inject': dict_inject,
'to_nics_dict': to_nics_dict,
'to_proxmox_net': to_proxmox_net,
'gen_nics_addrs': gen_nics_addrs,
'list_to_dict': list_to_dict,
'get_steps': get_steps,
'filter_dict': filter_dict,
'format2': format2,
'domain2dn': domain2dn
}