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