import mac.py from cinv
This commit is contained in:
		
					parent
					
						
							
								b017df4879
							
						
					
				
			
			
				commit
				
					
						64ab011299
					
				
			
		
					 1 changed files with 171 additions and 0 deletions
				
			
		
							
								
								
									
										171
									
								
								uncloud/hack/hackcloud/mac-gen.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								uncloud/hack/hackcloud/mac-gen.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,171 @@
 | 
			
		|||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
# 2012 Nico Schottelius (nico-cinv at schottelius.org)
 | 
			
		||||
#
 | 
			
		||||
# This file is part of cinv.
 | 
			
		||||
#
 | 
			
		||||
# cinv is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# cinv is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with cinv. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
import logging
 | 
			
		||||
import os.path
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
import cinv
 | 
			
		||||
from cinv import fsproperty
 | 
			
		||||
 | 
			
		||||
log = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
class Error(cinv.Error):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Mac(object):
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.base_dir = self.get_base_dir()
 | 
			
		||||
 | 
			
		||||
    _prefix = fsproperty.FileStringProperty(lambda obj: os.path.join(obj.base_dir, "prefix"))
 | 
			
		||||
    free    = fsproperty.FileListProperty(lambda obj: os.path.join(obj.base_dir, "free"))
 | 
			
		||||
    last    = fsproperty.FileStringProperty(lambda obj: os.path.join(obj.base_dir, "last"))
 | 
			
		||||
 | 
			
		||||
    def _init_base_dir(self):
 | 
			
		||||
        try:
 | 
			
		||||
            os.makedirs(self.base_dir, exist_ok=True)
 | 
			
		||||
        except OSError as e:
 | 
			
		||||
            raise Error(e)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def validate_mac(mac):
 | 
			
		||||
        if not re.match(r'([0-9A-F]{2}[-:]){5}[0-9A-F]{2}$', mac, re.I):
 | 
			
		||||
            raise Error("Not a valid mac address: %s" % mac)
 | 
			
		||||
 | 
			
		||||
    def free_append(self, mac):
 | 
			
		||||
        if mac in self.free:
 | 
			
		||||
            raise Error("Mac already in free database: %s" % mac)
 | 
			
		||||
 | 
			
		||||
        self._init_base_dir()
 | 
			
		||||
        self.free.append(mac)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_base_dir():
 | 
			
		||||
        return cinv.get_base_dir("db/mac")
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def exists(cls):
 | 
			
		||||
        return os.path.exists(cls.get_base_dir())
 | 
			
		||||
 | 
			
		||||
    def get_next(self):
 | 
			
		||||
        self._init_base_dir()
 | 
			
		||||
 | 
			
		||||
        if self.free:
 | 
			
		||||
            return self.free.pop()
 | 
			
		||||
 | 
			
		||||
        if not self.prefix:
 | 
			
		||||
            raise Error("Cannot generate address without prefix - use prefix-set")
 | 
			
		||||
 | 
			
		||||
        if self.last:
 | 
			
		||||
            suffix = re.search(r'([0-9A-F]{2}[-:]){2}[0-9A-F]{2}$', self.last, re.I)
 | 
			
		||||
            last_number_hex = "0x%s" % suffix.group().replace(":", "")
 | 
			
		||||
            last_number = int(last_number_hex, 16)
 | 
			
		||||
 | 
			
		||||
            if last_number == int('0xffffff', 16):
 | 
			
		||||
                raise Error("Exhausted all possible mac addresses - try to free some")
 | 
			
		||||
 | 
			
		||||
            next_number = last_number + 1
 | 
			
		||||
        else:
 | 
			
		||||
            next_number = 0
 | 
			
		||||
 | 
			
		||||
        next_number_hex = "%0.6x" % next_number
 | 
			
		||||
        next_suffix = "%s:%s:%s" % (next_number_hex[0:2], next_number_hex[2:4], next_number_hex[4:6])
 | 
			
		||||
 | 
			
		||||
        next_mac = "%s:%s" % (self.prefix, next_suffix)
 | 
			
		||||
 | 
			
		||||
        self.last = next_mac
 | 
			
		||||
 | 
			
		||||
        return next_mac
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def prefix(self):
 | 
			
		||||
        return self._prefix
 | 
			
		||||
 | 
			
		||||
    @prefix.setter
 | 
			
		||||
    def prefix(self, prefix):
 | 
			
		||||
        if not re.match(r'([0-9A-F]{2}[-:]){2}[0-9A-F]{2}$', prefix, re.I):
 | 
			
		||||
            raise Error("Wrong mac address format - use 00:11:22")
 | 
			
		||||
 | 
			
		||||
        self._init_base_dir()
 | 
			
		||||
        self._prefix = prefix
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def commandline_generate(cls, args):
 | 
			
		||||
        mac = Mac()
 | 
			
		||||
        print(mac.get_next())
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def commandline_free_add(cls, args):
 | 
			
		||||
        mac = Mac()
 | 
			
		||||
        mac.validate_mac(args.address)
 | 
			
		||||
        mac.free_append(args.address)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def commandline_free_list(cls, args):
 | 
			
		||||
        mac = Mac()
 | 
			
		||||
        for mac in mac.free:
 | 
			
		||||
            print(mac)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def commandline_prefix_set(cls, args):
 | 
			
		||||
        mac = Mac()
 | 
			
		||||
        mac.prefix = args.prefix
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def commandline_prefix_get(cls, args):
 | 
			
		||||
        mac = cls()
 | 
			
		||||
        print(mac.prefix)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def commandline_add(cls, args):
 | 
			
		||||
        host = cls(fqdn=args.fqdn)
 | 
			
		||||
        host.host_type = args.type
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def commandline_args(cls, parent_parser, parents):
 | 
			
		||||
        """Add us to the parent parser and add all parents to our parsers"""
 | 
			
		||||
 | 
			
		||||
        parser = {}
 | 
			
		||||
        parser['sub'] = parent_parser.add_subparsers(title="Mac Commands")
 | 
			
		||||
 | 
			
		||||
        parser['free-add'] = parser['sub'].add_parser('free-add', parents=parents)
 | 
			
		||||
        parser['free-add'].add_argument('address', help='Address to add to free database')
 | 
			
		||||
        parser['free-add'].set_defaults(func=cls.commandline_free_add)
 | 
			
		||||
 | 
			
		||||
        parser['free-list'] = parser['sub'].add_parser('free-list', parents=parents,
 | 
			
		||||
            help="List free mac addresses")
 | 
			
		||||
        parser['free-list'].set_defaults(func=cls.commandline_free_list)
 | 
			
		||||
 | 
			
		||||
        parser['generate'] = parser['sub'].add_parser('generate', parents=parents)
 | 
			
		||||
        parser['generate'].set_defaults(func=cls.commandline_generate)
 | 
			
		||||
 | 
			
		||||
        parser['prefix-get'] = parser['sub'].add_parser('prefix-get', parents=parents)
 | 
			
		||||
        parser['prefix-get'].set_defaults(func=cls.commandline_prefix_get)
 | 
			
		||||
 | 
			
		||||
        parser['prefix-set'] = parser['sub'].add_parser('prefix-set', parents=parents)
 | 
			
		||||
        parser['prefix-set'].add_argument('prefix', help="3 Byte address prefix (f.i. '00:16:3e')")
 | 
			
		||||
        parser['prefix-set'].set_defaults(func=cls.commandline_prefix_set)
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue