Source code for flask_app.models

from .app import app, ldap_obj
from .ldap_utils import server_dn
from flask.ext.sqlalchemy import SQLAlchemy
from sqlalchemy_utils import IPAddressType
import ldap
import ldap.modlist
import json
from ipaddr import IPAddress

db = SQLAlchemy(app)

def gen_modlist(obj_dict, options):
    if options:
        options = json.loads(options)
        for option in options:
            options[option] = [str(o) for o in options[option]]
        obj_dict.update(options)
    return obj_dict

class LDAPModel(db.Model):
    __abstract__ = True

    def dn(self):
        return ''

    def modlist(self):
        return dict()

    def ldap_add(self):
        ldap_obj.add_s(self.dn(), ldap.modlist.addModlist(self.modlist()))

    def ldap_modify(self):
        try:
            objs = ldap_obj.search_s(self.dn(), ldap.SCOPE_BASE)
            if objs[0][1] != dict(self.modlist()):
                ldap_obj.modify_s(self.dn(), ldap.modlist.modifyModlist(objs[0][1], dict(self.modlist())))
        except ldap.NO_SUCH_OBJECT:
            self.ldap_add()

    def ldap_delete(self):
        ldap_obj.delete_s(self.dn())

[docs]class Host(LDAPModel): """ class Host docstring """ id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255)) mac = db.Column(db.String(100), unique=True) group_id = db.Column(db.Integer, db.ForeignKey('group.id')) ip = db.relationship('IP', backref='host', uselist=False) options = db.Column(db.Text) def dn(self): if self.group_id: return 'cn=%s,%s' % (self.name, self.group.dn()) return 'cn=%s,ou=Hosts,%s' % (self.name, server_dn()) def modlist(self): options = self.options if self.ip: options = json.loads(self.options) if self.options else {} if not options.get('dhcpStatements'): options['dhcpStatements'] = [] options['dhcpStatements'] += ['fixed-address %s' % (self.ip.address)] options = json.dumps(options) return gen_modlist(dict(objectClass=['dhcpHost','top'], dhcpHWAddress=['ethernet %s' % str(self.mac)], cn=str(self.name)), options) def config(self): return dict(id = self.id, dn = self.dn(), name = self.name, mac = self.mac, group = self.group_id, options = json.loads(self.options) if self.options else None)
class Group(LDAPModel): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255)) hosts = db.relationship('Host', backref='group', lazy='dynamic') options = db.Column(db.Text) def dn(self): return 'cn=%s,ou=Groups,%s' % (self.name, server_dn()) def modlist(self): return gen_modlist(dict(objectClass=['dhcpGroup', 'top'], cn=str(self.name)), self.options) def config(self): return dict(id = self.id, dn = self.dn(), name = self.name, hosts = [host.id for host in self.hosts.all()], options = json.loads(self.options) if self.options else None) class Subnet(LDAPModel): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255)) netmask = db.Column(db.Integer) options = db.Column(db.Text) ips = db.relationship('IP', backref='subnet', lazy='dynamic') range_id = db.Column(db.Integer, db.ForeignKey('range.id')) pools = db.relationship('Pool', backref='subnet', lazy='dynamic') def dn(self): return 'cn=%s,ou=Subnets,%s' % (self.name, server_dn()) def modlist(self): mod_dict = dict(objectClass=['dhcpSubnet', 'top'], cn=str(self.name), dhcpNetMask=str(self.netmask)) if self.range: mod_dict.update(dict(dhcpRange=[str('range %s %s' % (self.range.min, self.range.max))])) return gen_modlist(mod_dict, self.options) def config(self): return dict(id = self.id, dn = self.dn(), name = self.name, netmask = self.netmask, options = json.loads(self.options) if self.options else None, range = self.range_id, ips = [ip.id for ip in self.ips.all()], pools = [pool.id for pool in self.pools.all()]) class IP(db.Model): id = db.Column(db.Integer, primary_key=True) address = db.Column(IPAddressType) subnet_id = db.Column(db.Integer, db.ForeignKey('subnet.id')) range_id = db.Column(db.Integer, db.ForeignKey('range.id')) host_id = db.Column(db.Integer, db.ForeignKey('host.id')) def ldap_add(self): if self.host: self.host.ldap_modify() def ldap_delete(self): if self.host: host = self.host host.ip = None db.session.add(host) db.session.commit() host.ldap_modify() def config(self): return dict(id = self.id, address = self.address.compressed, subnet = self.subnet_id, range = self.range_id, host = self.host_id) class Range(db.Model): id = db.Column(db.Integer, primary_key=True) type = db.Column(db.String(255)) min = db.Column(IPAddressType) max = db.Column(IPAddressType) subnet = db.relationship('Subnet', backref='range', uselist=False) pool = db.relationship('Pool', backref='range', uselist=False) ips = db.relationship('IP', backref='range') def ldap_add(self): if self.type == 'dynamic' and self.subnet: self.subnet.ldap_modify() def ldap_delete(self): if self.type == 'dynamic' and self.subnet: subnet = self.subnet subnet.ip = None db.session.add(subnet) db.session.commit() subnet.ldap_modify() def free_ips(self, num=1): # return the first IP address in the range, from the top, without conflict top = self.max+1 addresses = [] ips = [ip.address for ip in self.ips] ips.sort(reverse=True) ips = [self.max+1] + ips + [self.min-1] i = 0 j = 0 for ip in ips: while i < num: ip_j = top-j j+=1 if ip_j < self.min: return [] if ip >= ip_j: break addresses.append(ip_j) i+=1 if i == num: break return addresses def contains(self, ip): return ip >= self.min and ip <= self.max def config(self): return dict(id = self.id, type = self.type, min = self.min.compressed, max = self.max.compressed, ips = [ip.id for ip in self.ips], subnet = self.subnet.id if self.subnet else None, pool = self.pool.id if self.pool else None) class Pool(LDAPModel): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255)) subnet_id = db.Column(db.Integer, db.ForeignKey('subnet.id')) range_id = db.Column(db.Integer, db.ForeignKey('range.id')) options = db.Column(db.Text) def dn(self): return 'cn=%s,%s' % (self.name, self.subnet.dn()) def modlist(self): # range is required mod_dict = dict(objectClass=['dhcpPool', 'top'], cn=str(self.name), dhcpRange=[str('range %s %s' % (self.range.min, self.range.max))]) return gen_modlist(mod_dict, self.options) def config(self): return dict(id = self.id, name = self.name, subnet = self.subnet.id, range = self.range.id, options = self.options)