1# -*- coding: utf-8 -*-
2# (c) 2020 Ansible Project
3#
4# This file is part of Ansible
5#
6# Ansible is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# Ansible is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
18
19# Make coding more python3-ish
20from __future__ import (absolute_import, division, print_function)
21__metaclass__ = type
22
23import re
24from random import Random, SystemRandom
25
26from ansible.errors import AnsibleFilterError
27from ansible.module_utils.six import string_types
28
29
30def random_mac(value, seed=None):
31    ''' takes string prefix, and return it completed with random bytes
32        to get a complete 6 bytes MAC address '''
33
34    if not isinstance(value, string_types):
35        raise AnsibleFilterError('Invalid value type (%s) for random_mac (%s)' %
36                                 (type(value), value))
37
38    value = value.lower()
39    mac_items = value.split(':')
40
41    if len(mac_items) > 5:
42        raise AnsibleFilterError('Invalid value (%s) for random_mac: 5 colon(:) separated'
43                                 ' items max' % value)
44
45    err = ""
46    for mac in mac_items:
47        if not mac:
48            err += ",empty item"
49            continue
50        if not re.match('[a-f0-9]{2}', mac):
51            err += ",%s not hexa byte" % mac
52    err = err.strip(',')
53
54    if err:
55        raise AnsibleFilterError('Invalid value (%s) for random_mac: %s' % (value, err))
56
57    if seed is None:
58        r = SystemRandom()
59    else:
60        r = Random(seed)
61    # Generate random int between x1000000000 and xFFFFFFFFFF
62    v = r.randint(68719476736, 1099511627775)
63    # Select first n chars to complement input prefix
64    remain = 2 * (6 - len(mac_items))
65    rnd = ('%x' % v)[:remain]
66    return value + re.sub(r'(..)', r':\1', rnd)
67
68
69class FilterModule:
70    ''' Ansible jinja2 filters '''
71    def filters(self):
72        return {
73            'random_mac': random_mac,
74        }
75