Exemple #1
0
class Arch(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, unique=True, nullable=False)
    description = db.Column(db.String)
    subarchs = db.relationship("Subarch", back_populates="arch", passive_deletes=True)

    def __init__(self, name, description=None):
        self.name = name
        self.description = description

    def check_permission(self, user, min_priv_level='any'):
        if user.admin:
            return True
        elif min_priv_level == 'admin':
            return False

        return False

    @property
    def machines(self):
        return Machine.query.filter((Machine.arch_id == self.id)).all()

    @staticmethod
    def can_create(user):
        return True if user.admin else False
Exemple #2
0
class Subarch(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    description = db.Column(db.String)
    arch_id = db.Column(db.Integer,
                        db.ForeignKey("arch.id", ondelete="CASCADE"),
                        nullable=False)
    arch = db.relationship("Arch",
                           foreign_keys=[arch_id],
                           passive_deletes=True)
    bootloader_id = db.Column(db.Integer, db.ForeignKey("image.id"))
    bootloader = db.relationship("Image",
                                 foreign_keys=[bootloader_id],
                                 passive_deletes=True)

    def __init__(self, name, arch_id, description=None, bootloader_id=None):
        self.name = name
        self.description = description
        self.arch_id = arch_id
        self.bootloader_id = bootloader_id

    def check_permission(self, user, min_priv_level='any'):
        if user.admin:
            return True
        elif min_priv_level == 'admin':
            return False

        return False

    @staticmethod
    def can_create(user):
        return True if user.admin else False
Exemple #3
0
class Token(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    user = db.relationship("User", passive_deletes=True)
    token = db.Column(db.String, unique=True, nullable=False)
    desc = db.Column(db.String)

    def __init__(self, user_id, token, desc):
        if not token:
            token = b64encode(urandom(32)).decode('utf-8')
        self.user_id = user_id
        self.token = token
        self.desc = desc

    def __repr__(self):
        return ''

    def serialize(self):
        """Return object data in serialized format"""
        return {
            'id': self.id,
            'user_id': self.user_id,
            'token': self.token,
            'desc': self.desc,
        }

    def check_permission(self, user, min_priv_level='any'):
        if user.admin:
            return True
        elif min_priv_level == 'admin':
            return False

        if user.id == self.user_id:
            return True
        elif min_priv_level == 'owner':
            return False

        return False

    @staticmethod
    def by_user(user):
        return db.session.query(Token).filter_by(user_id=user.id).all()

    @staticmethod
    def by_token(token):
        return Token.query.filter_by(token=token).first()

    @staticmethod
    def can_create(user):
        return True
Exemple #4
0
class Interface(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    mac = db.Column(MACADDR, unique=True, nullable=False)
    identifier = db.Column(db.String, nullable=True)
    dhcpv4 = db.Column(db.Boolean)
    static_ipv4 = db.Column(INET, nullable=True)
    reserved_ipv4 = db.Column(INET, nullable=True)
    machine_id = db.Column(db.Integer, db.ForeignKey("machine.id", ondelete="CASCADE"))
    machine = db.relationship("Machine", passive_deletes=True)
    network_id = db.Column(db.Integer, db.ForeignKey("network.id", ondelete="SET NULL"), nullable=True)
    network = db.relationship("Network", passive_deletes=True)
    __table_args__ = (UniqueConstraint('static_ipv4', 'network_id'),
                      UniqueConstraint('reserved_ipv4', 'network_id'),)

    def __init__(self, *, mac, machine_id, network_id=None, dhcpv4=True, identifier=None,
                 static_ipv4=None, reserved_ipv4=None):
        self.mac = mac
        self.identifier = identifier
        self.dhcpv4 = dhcpv4
        self.static_ipv4 = static_ipv4
        self.reserved_ipv4 = reserved_ipv4
        self.machine_id = machine_id
        self.network_id = network_id

    @property
    def lease(self):
        return Lease.query.filter_by(mac=self.mac).first()

    @property
    def config_type_v4(self):
        if self.network and self.static_ipv4:
            return 'static'
        elif self.network and self.reserved_ipv4:
            return 'dynamic-reserved'
        else:
            return 'dynamic'

    @property
    def configured_ipv4(self):
        if self.config_type_v4 == 'static':
            return self.static_ipv4
        elif self.config_type_v4 == 'dynamic-reserved':
            return self.reserved_ipv4
        else:
            return None

    @staticmethod
    def by_mac(mac):
        try:
            interface = Interface.query.filter_by(mac=mac).one()
            return interface
        except NoResultFound:
            return None

    @staticmethod
    def update_discovery(connection, interface):
        query = DiscoveredMAC.__table__.delete().where((DiscoveredMAC.mac == interface.mac))
        connection.execute(query)
Exemple #5
0
class Lease(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    mac = db.Column(MACADDR, unique=True, nullable=False)
    ipv4 = db.Column(INET)
    last_seen = db.Column(db.DateTime, nullable=False)

    def __init__(self, *, mac, ipv4):
        self.mac = mac
        self.ipv4 = ipv4
        self.last_seen = datetime.utcnow()

    @staticmethod
    def by_mac(mac):
        try:
            lease = Lease.query.filter_by(mac=mac).one()
            return lease
        except NoResultFound:
            return None
Exemple #6
0
class MachineUsers(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    machine_id = db.Column(db.Integer, db.ForeignKey("machine.id", ondelete="CASCADE"))
    machine = db.relationship("Machine", passive_deletes=True)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    user = db.relationship("User", passive_deletes=True)
    permissions = db.Column(db.Integer)
    start_date = db.Column(db.DateTime, nullable=False)
    reason = db.Column(db.Text, nullable=False)
    __table_args__ = (UniqueConstraint('machine_id', 'user_id'),)

    def __init__(self, machine_id, user_id, permissions, reason):
        self.start_date = datetime.now()
        self.machine_id = machine_id
        self.user_id = user_id
        self.permissions = permissions
        self.reason = reason if reason is not None else ""

    def __repr__(self):
        return "<machine_id: %d, user_id: %d, permissions: %d, " \
               "start_date: %s, reason: %s>" % (self.machine_id,
                                                self.user_id,
                                                self.permissions,
                                                self.start_date,
                                                self.reason)

    def serialize(self):
        return {
            'machine_id': self.machine_id,
            'user_id': self.user_id,
            'permissions': self.permissions,
            'start_date': self.start_date.strftime("%Y-%m-%d"),
            'reason': self.reason
        }
Exemple #7
0
class DiscoveredMAC(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    mac = db.Column(MACADDR, unique=True, nullable=False)
    info = db.Column(JSONB)
    last_seen = db.Column(db.DateTime, nullable=False)

    def __init__(self, *, mac, info):
        self.mac = mac
        self.info = info
        self.last_seen = datetime.utcnow()

    @staticmethod
    def by_mac(mac):
        try:
            d = DiscoveredMAC.query.filter_by(mac=mac).one()
            return d
        except NoResultFound:
            return None

    @staticmethod
    def can_list(user):
        return True if user.admin else False
Exemple #8
0
class ConsoleToken(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    token = db.Column(db.String, unique=True, nullable=False)
    created_at = db.Column(db.DateTime, nullable=False)
    command_response = db.Column(db.Text)

    def __init__(self, command_response):
        self.command_response = command_response
        self.token = ConsoleToken.gen_token()
        print("Token: %s " % self.token)
        self.created_at = datetime.utcnow()

    @staticmethod
    def cleanup():
        db.session.query(ConsoleToken).filter(
            ConsoleToken.created_at <= (datetime.utcnow() -
                                        timedelta(minutes=5))).delete()
        db.session.commit()

    @staticmethod
    def gen_token():
        return binascii.hexlify(urandom(24)).decode('utf-8')
Exemple #9
0
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String, unique=True, nullable=False)
    email = db.Column(db.String, nullable=False)
    ldap = db.Column(db.Boolean)
    ssh_key = db.Column(db.Text)
    password = db.Column(db.String)
    admin = db.Column(db.Boolean)

    def __init__(self, username, email, ldap, ssh_key, password, admin):
        self.username = username
        self.email = email
        self.ldap = ldap
        self.ssh_key = ssh_key
        self.password = password
        self.admin = admin

    def __repr__(self):
        return "<username: %s, email: %s, ldap: %b, ssh_key: %s, " \
               "password: %s, admin: %b>" % (self.username,
                                             self.email,
                                             self.ldap,
                                             self.ssh_key,
                                             self.password,
                                             self.admin)

    def serialize(self):
        """Return object data in serialized format"""
        return {
            'username': self.name,
            'email': self.email,
            'ldap': self.ldap,
            'ssh_key': self.ssh_key,
            'password': self.password,
            'admin': self.admin
        }

    def check_permission(self, user, min_priv_level='any'):
        if user.admin:
            return True
        elif min_priv_level == 'admin':
            return False

        return False

    @staticmethod
    def can_create(user):
        return True if user.admin else False

    @staticmethod
    def by_username(username):
        return User.query.filter_by(username=username).first()
Exemple #10
0
class BMC(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    ip = db.Column(db.String, unique=True, nullable=False)
    name = db.Column(db.String, unique=True, nullable=False)
    username = db.Column(db.String)
    password = db.Column(db.String)
    privilege_level = db.Column(db.String)
    bmc_type = db.Column(db.String)
    machines = db.relationship("Machine",
                               back_populates="bmc",
                               passive_deletes=True)

    def __init__(self, ip, name, username, password, privilege_level,
                 bmc_type):
        self.ip = ip
        self.name = name
        self.username = username
        self.password = password
        self.privilege_level = privilege_level
        self.bmc_type = bmc_type

    @property
    def serialize(self):
        """Return object data in serialized format"""
        return {
            'ip': self.ip,
            'name': self.name,
            'username': self.username,
            'password': self.password,
            'privilege_level': self.privilege_level,
            'bmc_type': self.bmc_type
        }

    @property
    def type_inst(self):
        return resolve_bmc_type(self.bmc_type)

    def check_permission(self, user, min_priv_level='any'):
        if user.admin:
            return True
        elif min_priv_level == 'admin':
            return False

        return False

    @staticmethod
    def can_create(user):
        return True if user.admin else False

    @staticmethod
    def list_types():
        return [t.name for t in list_bmc_types()]
Exemple #11
0
class ConsoleToken(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    token = db.Column(db.String, unique=True, nullable=False)
    created_at = db.Column(db.DateTime, nullable=False)
    command_response = db.Column(db.Text)
    machine_id = db.Column(db.Integer,
                           db.ForeignKey("machine.id", ondelete="CASCADE"))
    machine = db.relationship("Machine", passive_deletes=True)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id",
                                                  ondelete="CASCADE"))
    user = db.relationship("User", passive_deletes=True)

    def __init__(self, *, command_response, machine_id, user_id):
        self.command_response = command_response
        self.token = ConsoleToken.gen_token()
        print("Token: %s " % self.token)
        self.created_at = datetime.utcnow()
        self.machine_id = machine_id
        self.user_id = user_id

    @staticmethod
    def cleanup():
        db.session.query(ConsoleToken).filter(
            ConsoleToken.created_at <= (datetime.utcnow() -
                                        timedelta(minutes=5))).delete()
        db.session.commit()

    @staticmethod
    def gen_token():
        return binascii.hexlify(urandom(24)).decode('utf-8')

    @staticmethod
    def create_token_for_machine(machine, user):
        if not machine.bmc:
            raise ValueError('no BMC configured')

        (cmd, args) = machine.sol_command

        command_response = {
            'command': cmd,
            'args': args,
        }

        sol_token = ConsoleToken(command_response=json.dumps(command_response),
                                 machine_id=machine.id,
                                 user_id=user.id)
        db.session.add(sol_token)
        db.session.commit()
        db.session.refresh(sol_token)

        return sol_token
Exemple #12
0
class AuditLog(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    machine_name = db.Column(db.String, nullable=False)
    user_name = db.Column(db.String, nullable=False)
    permissions = db.Column(db.Integer)
    start_date = db.Column(db.DateTime, nullable=False)
    end_date = db.Column(db.DateTime, nullable=False)

    def __repr__(self):
        return "<machine_name: %s, user_name: %s, permissions: %d, " \
               "start_date: %s, end_date: %s>" % (self.machine_name,
                                                  self.user_name,
                                                  self.permissions,
                                                  self.start_date,
                                                  self.end_date)

    def serialize(self):
        return {
            'machine_name': self.machine_name,
            'user_name': self.user_name,
            'permissions': self.permissions,
            'start_date': self.start_date,
            'end_date': self.end_date
        }
Exemple #13
0
class Network(db.Model):
    __tablename__ = 'network'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, unique=True, nullable=False)
    subnet = db.Column(CIDR, unique=True, nullable=False)
    reserved_net = db.Column(CIDR, unique=True, nullable=True)
    static_net = db.Column(CIDR, unique=True, nullable=True)
    interfaces = db.relationship("Interface", back_populates="network", passive_deletes=True)

    def __init__(self, *, name, subnet, reserved_net=None, static_net=None):
        self.name = name
        self.subnet = subnet
        self.reserved_net = reserved_net
        self.static_net = static_net

    @property
    def machines(self):
        return Machine.query.join(Machine.interfaces).filter(Interface.network_id == self.id).all()

    @property
    def prefix(self):
        return IPNetwork(self.subnet).prefixlen

    @property
    def netmask(self):
        return str(IPNetwork(self.subnet).netmask)

    def check_permission(self, user, min_priv_level='any'):
        if user.admin:
            return True
        elif min_priv_level == 'admin':
            return False

        return False

    def available_ipv4s(self, limit=25):
        def _gen(ip_set):
            for ip_net in ip_set.iter_cidrs():
                for ip in ip_net.iter_hosts():
                    if ip.words[-1] not in [0, 255, 0xffff]:
                        yield ip

        interfaces = Interface.query.filter_by(network_id=self.id).all()

        static_ips = IPSet([self.static_net]) if self.static_net else IPSet()
        reserved_ips = IPSet([self.reserved_net]) if self.reserved_net else IPSet()

        for interface in interfaces:
            if interface.static_ipv4:
                static_ips.remove(interface.static_ipv4)
            if interface.reserved_ipv4:
                reserved_ips.remove(interface.reserved_ipv4)

        return (list(itertools.islice(_gen(static_ips), limit)),
                list(itertools.islice(_gen(reserved_ips), limit)))

    def ip_in_use(self, ip, *, exclude_intf=None):
        query = Interface.query.filter((Interface.network_id == self.id) &
                                       ((Interface.reserved_ipv4 == ip) |
                                       (Interface.static_ipv4 == ip)))
        if exclude_intf:
            query = query.filter((Interface.id != exclude_intf.id))

        return query.count() != 0

    @staticmethod
    def subnet_conflicts(subnet, *, exclude_network=None):
        query = Network.query.filter(
            text('network(:range) << subnet OR network(:range) >>= subnet')).\
            params(range=subnet)

        if exclude_network:
            query = query.filter((Network.id != exclude_network.id))

        return query.count() != 0

    @staticmethod
    def static_net_changed(connection, network):
        query = Interface.__table__.update().where((Interface.network_id == network.id))
        if network.static_net:
            query = query.where(text('not static_ipv4 << network(:range)'))
        query = query.values(static_ipv4=None)

        connection.execute(query, range=network.static_net)

    @staticmethod
    def reserved_net_changed(connection, network):
        query = Interface.__table__.update().where((Interface.network_id == network.id))
        if network.reserved_net:
            query = query.where(text('not reserved_ipv4 << network(:range)'))
        query = query.values(reserved_ipv4=None)

        connection.execute(query, range=network.reserved_net)

    @staticmethod
    def can_create(user):
        return True if user.admin else False
Exemple #14
0
class Preseed(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    filename = db.Column(db.String, unique=True, nullable=False)
    description = db.Column(db.String)
    file_type = db.Column(db.String, nullable=False)
    file_content = db.Column(db.Text)
    date = db.Column(db.DateTime, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    user = db.relationship("User", passive_deletes=True)
    machines = db.relationship("Machine", back_populates="preseed", passive_deletes=True)
    known_good = db.Column(db.Boolean, nullable=False)
    public = db.Column(db.Boolean, nullable=False)

    def __init__(self, filename, description, file_type, file_content, user_id, known_good, public):
        self.date = datetime.now()
        self.filename = filename
        self.description = description
        self.file_type = file_type
        self.file_content = file_content
        self.user_id = user_id
        self.known_good = known_good
        self.public = public

    def __repr__(self):
        return "<filename: %s, file_type: %s, user_id: %d, known_good: %s>" % (self.filename,
                                                                               self.file_type,
                                                                               self.user_id,
                                                                               self.known_good)

    def preseed_url(self, machine, config):
        return "%s/preseed/%s" % (config['CONTROLLER_ACCESS_URI'], machine.id)

    def kernel_opts(self, machine, config):
        if self.file_type == "preseed":
            options = "auto=true priority=critical url=%s interface=auto" % (self.preseed_url(machine, config))

            if config['PRESEED_DNS']:
                options += " netcfg/get_nameservers=%s" % (config['PRESEED_DNS'])

        elif self.file_type == "kickstart":
            options = "ks=%s kssendmac" % self.preseed_url(machine, config)

            if config['PRESEED_DNS']:
                options += " dns=%s" % (config['PRESEED_DNS'])

        elif self.file_type == "autoyast":
            options = "autoyast=%s" % self.preseed_url(machine, config)

            if config['PRESEED_DNS']:
                options += " nameserver=%s" % (config['PRESEED_DNS'])

        return options

    def serialize(self):
        return {
            'filename': self.filename,
            'file_content': self.file_content,
            'type': self.type,
            'date': self.date.strftime("%Y-%m-%d %H:%M"),
            'user_id': self.user_id,
            'known_good': self.known_good,
            'public': self.public
        }

    def check_permission(self, user, min_priv_level='any'):
        if user.admin:
            return True
        elif min_priv_level == 'admin':
            return False

        if user.id == self.user_id:
            return True
        elif min_priv_level == 'owner':
            return False

        return self.public

    @staticmethod
    def can_create(user):
        return True

    @staticmethod
    def all():
        return db.session.query(Preseed).all()

    @staticmethod
    def all_visible(user):
        if(user.admin):
            return db.session.query(Preseed).all()
        else:
            return db.session.query(Preseed).filter((Preseed.public == true()) | (Preseed.user_id == user.id)).all()

    @staticmethod
    def list_types():
        return ['preseed', 'kickstart', 'autoyast']
Exemple #15
0
class Image(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    filename = db.Column(db.String, unique=True, nullable=False)
    description = db.Column(db.String)
    file_type = db.Column(db.String, nullable=False)
    arch_id = db.Column(db.Integer, db.ForeignKey("arch.id"), nullable=False)
    arch = db.relationship("Arch", foreign_keys=[arch_id], passive_deletes=True)
    date = db.Column(db.DateTime, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    user = db.relationship("User", passive_deletes=True)
    known_good = db.Column(db.Boolean, nullable=False)
    public = db.Column(db.Boolean, nullable=False)

    def __init__(self, filename, description, file_type, user_id, known_good, public, arch_id=None):
        self.date = datetime.now()
        self.filename = filename
        self.description = description
        self.file_type = file_type
        self.user_id = user_id
        self.known_good = known_good
        self.public = public
        self.arch_id = arch_id

    def __repr__(self):
        return '<filename: %s, user_id: %d, known_good: %s>' % (self.filename, self.user_id, self.known_good)

    def serialize(self):
        return {
            'filename': self.filename,
            'description': self.description,
            'file_type': self.file_type,
            'date': self.date.strftime("%Y-%m-%d %H:%M"),
            'arch_id': self.arch_id,
            'user_id': self.user_id,
            'known_good': self.known_good,
            'public': self.public
        }

    @property
    def machines(self):
        return Machine.query.filter((Machine.kernel_id == self.id) | (Machine.initrd_id == self.id)).all()

    def check_permission(self, user, min_priv_level='any'):
        if user.admin:
            return True
        elif min_priv_level == 'admin':
            return False

        if user.id == self.user_id:
            return True
        elif min_priv_level == 'owner':
            return False

        return self.public

    @staticmethod
    def can_create(user):
        return True

    @staticmethod
    def all():
        return db.session.query(Image).all()

    @staticmethod
    def all_visible(user):
        if(user.admin):
            return db.session.query(Image).all()
        else:
            return db.session.query(Image).filter((Image.public == true()) | (Image.user_id == user.id)).all()

    @staticmethod
    def list_types():
        return ['Initrd', 'Kernel', 'bootloader']
Exemple #16
0
class MachineEvent(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    machine_id = db.Column(db.Integer, db.ForeignKey("machine.id", ondelete="CASCADE"))
    machine = db.relationship("Machine", passive_deletes=True)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id", ondelete="SET NULL"), nullable=True)
    user = db.relationship("User", passive_deletes=True)
    username = db.Column(db.String, nullable=True)
    date = db.Column(db.DateTime, nullable=False)
    event_type = db.Column(db.Integer, nullable=False)
    info = db.Column(JSONB)

    def __init__(self, *, event_type, info, machine_id, user):
        self.date = datetime.now()
        self.event_type = event_type
        self.info = info
        self.machine_id = machine_id
        self.user_id = user.id if user else None
        self.username = user.username if user else None

    @staticmethod
    def by_machine_id(machine_id, limit=0):
        q = MachineEvent.query.filter_by(machine_id=machine_id).order_by(MachineEvent.date.desc())
        if limit and limit > 0:
            q = q.limit(limit)
        return q.all()

    @staticmethod
    def cleanup():
        db.session.query(MachineEvent).filter(
            MachineEvent.date <= (datetime.utcnow() - timedelta(days=30))
        ).delete()

    @staticmethod
    def console_accessed(machine_id, user):
        event = MachineEvent(event_type=MachineEventType.CONSOLE_ACCESS,
                             info={},
                             machine_id=machine_id,
                             user=user)
        db.session.add(event)
        db.session.commit()

    @staticmethod
    def power_changed(machine_id, user, power_state):
        event = MachineEvent(event_type=MachineEventType.POWER_CHANGE,
                             info={'power': power_state},
                             machine_id=machine_id,
                             user=user)
        db.session.add(event)
        db.session.commit()

    @staticmethod
    def state_changed(machine_id, user, state, reason):
        event = MachineEvent(event_type=MachineEventType.STATE_CHANGE,
                             info={'state': state, 'reason': reason},
                             machine_id=machine_id,
                             user=user)
        db.session.add(event)
        db.session.commit()

    @staticmethod
    def preseed_accessed(machine_id, user, client_ip):
        event = MachineEvent(event_type=MachineEventType.PRESEED_ACCESS,
                             info={'client_ip': client_ip},
                             machine_id=machine_id,
                             user=user)
        db.session.add(event)
        db.session.commit()

    @staticmethod
    def preseed_error(machine_id, user, client_ip, message, lineno=0):
        event = MachineEvent(event_type=MachineEventType.PRESEED_ERROR,
                             info={'client_ip': client_ip, 'message': message, 'lineno': lineno},
                             machine_id=machine_id,
                             user=user)
        db.session.add(event)
        db.session.commit()

    @staticmethod
    def dhcp_request(machine_id, user, discover):
        event = MachineEvent(event_type=MachineEventType.DHCP_REQ,
                             info={'discover': discover},
                             machine_id=machine_id,
                             user=user)
        db.session.add(event)
        db.session.commit()

    @staticmethod
    def tftp_request(machine_id, user, filename):
        event = MachineEvent(event_type=MachineEventType.TFTP_REQ,
                             info={'filename': filename},
                             machine_id=machine_id,
                             user=user)
        db.session.add(event)
        db.session.commit()
Exemple #17
0
class Machine(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, unique=True, nullable=False)
    pdu = db.Column(db.String)
    pdu_port = db.Column(db.Integer)
    serial = db.Column(db.String)
    serial_port = db.Column(db.Integer)
    kernel_id = db.Column(db.Integer, db.ForeignKey("image.id"))
    kernel = db.relationship("Image", foreign_keys=[kernel_id], passive_deletes=True)
    kernel_opts = db.Column(db.String)
    preseed_id = db.Column(db.Integer, db.ForeignKey("preseed.id"))
    preseed = db.relationship("Preseed", passive_deletes=True)
    initrd_id = db.Column(db.Integer, db.ForeignKey("image.id"))
    initrd = db.relationship("Image", foreign_keys=[initrd_id], passive_deletes=True)
    netboot_enabled = db.Column(db.Boolean)
    arch_id = db.Column(db.Integer, db.ForeignKey("arch.id"), nullable=False)
    arch = db.relationship("Arch", foreign_keys=[arch_id], passive_deletes=True)
    subarch_id = db.Column(db.Integer, db.ForeignKey("subarch.id"), nullable=True)
    subarch = db.relationship("Subarch", foreign_keys=[subarch_id], passive_deletes=True)
    bmc_id = db.Column(db.Integer, db.ForeignKey("BMC.id"))
    bmc = db.relationship("BMC", passive_deletes=True)
    bmc_info = db.Column(db.String)
    state = db.Column(db.String)

    interfaces = db.relationship("Interface", back_populates="machine", passive_deletes=True)
    assignments = db.relationship("MachineUsers", back_populates="machine", passive_deletes=True)

    def __init__(self, name, arch_id, subarch_id=None, pdu=None, pdu_port=None, serial=None,
                 serial_port=None, kernel_id=None, kernel_opts="", preseed_id=None,
                 initrd_id=None, netboot_enabled=False, bmc_id=None, bmc_info=""):
        self.name = name
        self.pdu = pdu
        self.pdu_port = pdu_port
        self.serial = serial
        self.serial_port = serial_port
        self.arch_id = arch_id
        self.subarch_id = subarch_id
        self.kernel_id = kernel_id
        self.kernel_opts = kernel_opts
        self.preseed_id = preseed_id
        self.initrd_id = initrd_id
        self.netboot_enabled = netboot_enabled
        self.bmc_id = bmc_id
        self.bmc_info = bmc_info
        self.state = "unknown"

    @property
    def macs(self):
        return map(lambda i: i.mac, self.interfaces)

    def kernel_opts_all(self, config):
        preseed_opts = self.preseed.kernel_opts(self, config) if self.preseed_id else ""
        return preseed_opts + " " + (self.kernel_opts if self.kernel_opts else "")

    # XXX: get rid of it.
    @property
    def user(self):
        # XXX: support multiple
        machine_user = MachineUsers.query.filter_by(machine_id=self.id).first()
        return machine_user.user if machine_user else None

    @property
    def assignees(self):
        return [mu.user for mu in self.assignments]

    # XXX: get rid of it.
    @property
    def assignment(self):
        # XXX: support multiple
        machine_user = MachineUsers.query.filter_by(machine_id=self.id).first()
        return machine_user if machine_user else None

    @property
    def bootloader(self):
        return self.subarch.bootloader if self.subarch else None

    @property
    def hostname(self):
        return re.sub(r'[^a-zA-Z0-9]', '-', self.name)

    @property
    def power_state(self):
        bmc = self.bmc
        if not bmc:
            return "unknown"

        try:
            # XXX: consider proxying get_power in bmc so that one can do bmc.get_power instead
            return bmc.type_inst.get_power(self)
        except BMCError as e:
            return "Unknown (BMC error)"

    def reboot(self):
        bmc = self.bmc
        # XXX: raise exception if not bmc
        if self.power_state == "on":
            bmc.type_inst.set_power(self, "reset")
        else:
            bmc.type_inst.set_power(self, "on")

    def pxe_reboot(self):
        bmc = self.bmc
        # XXX: raise exception if not bmc
        bmc.type_inst.set_bootdev(self, "pxe")
        if self.power_state == "on":
            bmc.type_inst.set_power(self, "reset")
        else:
            bmc.type_inst.set_power(self, "on")

    def disk_reboot(self):
        bmc = self.bmc
        # XXX: raise exception if not bmc
        bmc.type_inst.set_bootdev(self, "disk")
        if self.power_state == "on":
            bmc.type_inst.set_power(self, "reset")
        else:
            bmc.type_inst.set_power(self, "on")

    def bios_reboot(self):
        bmc = self.bmc
        # XXX: raise exception if not bmc
        bmc.type_inst.set_bootdev(self, "bios")
        if self.power_state == "on":
            bmc.type_inst.set_power(self, "reset")
        else:
            bmc.type_inst.set_power(self, "on")

    def set_power(self, power_state):
        if power_state == 'pxe_reboot':
            self.pxe_reboot()
        elif power_state == 'disk_reboot':
            self.disk_reboot()
        elif power_state == 'bios_reboot':
            self.bios_reboot()
        else:
            power_state = 'reset' if power_state == 'reboot' else power_state
            bmc = self.bmc
            # XXX: raise exception if not bmc
            bmc.type_inst.set_power(self, power_state)

    def deactivate_sol(self):
        bmc = self.bmc
        # XXX: raise exception if not bmc
        if self.power_state == "on":
            bmc.type_inst.deactivate_sol(self)

    @property
    def sol_command(self):
        bmc = self.bmc
        return bmc.type_inst.get_sol_command(self)

    def check_permission(self, user, min_priv_level='any'):
        # XXX: min_priv_level is something like 'any', 'assignee', 'admin'
        if user.admin:
            return True
        elif min_priv_level == 'admin':
            return False

        if user in self.assignees:
            return True
        elif min_priv_level == 'assignee':
            return False

        return True

    @staticmethod
    def can_create(user):
        return True if user.admin else False

    @staticmethod
    def by_mac(mac):
        try:
            interface = Interface.query.filter_by(mac=mac).one()
            return Machine.query.get(interface.machine_id)
        except NoResultFound:
            return None

    @staticmethod
    def query_by_criteria(query_str, *, no_assignees=False):
        intf_subq = (db.session.query(Interface.machine_id,
                                      func.count(Interface.machine_id).label("interface_count"))
                     .group_by(Interface.machine_id)).subquery("interface")

        mu_subq = (db.session.query(MachineUsers.machine_id,
                                    func.count(MachineUsers.machine_id).label("assignee_count"))
                   .group_by(MachineUsers.machine_id)).subquery("assignee")

        sym_table = {
            'name': Machine.name,
            'assignee_count': func.coalesce(mu_subq.c.assignee_count, 0),
            'interface_count': func.coalesce(intf_subq.c.interface_count, 0),
            'bmc_type': func.coalesce(BMC.bmc_type, ''),
            'arch': func.coalesce(Arch.name, ''),
            'nil': None,
        }

        # Build base query, filtering out machines that have assignees already
        q = db.session.query(Machine) \
            .outerjoin(BMC, BMC.id == Machine.bmc_id) \
            .outerjoin(Arch, Arch.id == Machine.arch_id) \
            .outerjoin(intf_subq, Machine.id == intf_subq.c.machine_id) \
            .outerjoin(mu_subq, Machine.id == mu_subq.c.machine_id)

        if no_assignees:
            q = q.filter(func.coalesce(mu_subq.c.assignee_count, 0) == 0)

        # Parse the query string and further filter expression based on it
        f = build_filter(query_str, sym_table)
        if f is not None:
            q = q.filter(f)

        return q
Exemple #18
0
class Machine(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, unique=True, nullable=False)
    pdu = db.Column(db.String)
    pdu_port = db.Column(db.Integer)
    serial = db.Column(db.String)
    serial_port = db.Column(db.Integer)
    kernel_id = db.Column(db.Integer, db.ForeignKey("image.id"))
    kernel = db.relationship("Image",
                             foreign_keys=[kernel_id],
                             passive_deletes=True)
    kernel_opts = db.Column(db.String)
    preseed_id = db.Column(db.Integer, db.ForeignKey("preseed.id"))
    preseed = db.relationship("Preseed", passive_deletes=True)
    initrd_id = db.Column(db.Integer, db.ForeignKey("image.id"))
    initrd = db.relationship("Image",
                             foreign_keys=[initrd_id],
                             passive_deletes=True)
    netboot_enabled = db.Column(db.Boolean)
    # arch needed?
    bmc_id = db.Column(db.Integer, db.ForeignKey("BMC.id"))
    bmc = db.relationship("BMC", passive_deletes=True)
    bmc_info = db.Column(db.String)

    interfaces = db.relationship("Interface",
                                 back_populates="machine",
                                 passive_deletes=True)
    assignments = db.relationship("MachineUsers",
                                  back_populates="machine",
                                  passive_deletes=True)

    def __init__(self,
                 name,
                 pdu=None,
                 pdu_port=None,
                 serial=None,
                 serial_port=None,
                 kernel_id=None,
                 kernel_opts="",
                 preseed_id=None,
                 initrd_id=None,
                 netboot_enabled=False,
                 bmc_id=None,
                 bmc_info=""):
        self.name = name
        self.pdu = pdu
        self.pdu_port = pdu_port
        self.serial = serial
        self.serial_port = serial_port
        self.kernel_id = kernel_id
        self.kernel_opts = kernel_opts
        self.preseed_id = preseed_id
        self.initrd_id = initrd_id
        self.netboot_enabled = netboot_enabled
        self.bmc_id = bmc_id
        self.bmc_info = bmc_info

    def __repr__(self):
        return "<name: %s, macs: %s, kernel: %d, kernel_opts: %s," \
               "initrd: %d, netboot_enabled: %b, bmc_id %s>" % (self.name,
                                                                ",".join(self.macs),
                                                                self.kernel_id,
                                                                self.kernel_opts,
                                                                self.initrd_id,
                                                                self.netboot_enabled,
                                                                self.bmc_id)

    @property
    def macs(self):
        return map(lambda i: i.mac, self.interfaces)

    def kernel_opts_all(self, config):
        preseed_opts = self.preseed.kernel_opts(
            self, config) if self.preseed_id else ""
        return preseed_opts + " " + (self.kernel_opts
                                     if self.kernel_opts else "")

    # XXX: get rid of it.
    @property
    def user(self):
        # XXX: support multiple
        machine_user = MachineUsers.query.filter_by(machine_id=self.id).first()
        return machine_user.user if machine_user else None

    @property
    def assignees(self):
        return [mu.user for mu in self.assignments]

    # XXX: get rid of it.
    @property
    def assignment(self):
        # XXX: support multiple
        machine_user = MachineUsers.query.filter_by(machine_id=self.id).first()
        return machine_user if machine_user else None

    @property
    def hostname(self):
        return re.sub(r'[^a-zA-Z0-9]', '-', self.name)

    @property
    def power_state(self):
        bmc = self.bmc
        if not bmc:
            return "unknown"

        try:
            # XXX: consider proxying get_power in bmc so that one can do bmc.get_power instead
            return bmc.type_inst.get_power(self)
        except BMCError as e:
            return "Unknown (BMC error)"

    def reboot(self):
        bmc = self.bmc
        # XXX: raise exception if not bmc
        if self.power_state == "on":
            bmc.type_inst.set_power(self, "reset")
        else:
            bmc.type_inst.set_power(self, "on")

    def pxe_reboot(self):
        bmc = self.bmc
        # XXX: raise exception if not bmc
        bmc.type_inst.set_bootdev(self, "pxe")
        if self.power_state == "on":
            bmc.type_inst.set_power(self, "reset")
        else:
            bmc.type_inst.set_power(self, "on")

    def set_power(self, power_state):
        power_state = 'reset' if power_state == 'reboot' else power_state
        bmc = self.bmc
        # XXX: raise exception if not bmc
        bmc.type_inst.set_power(self, power_state)

    def deactivate_sol(self):
        bmc = self.bmc
        # XXX: raise exception if not bmc
        if self.power_state == "on":
            bmc.type_inst.deactivate_sol(self)

    @property
    def sol_command(self):
        bmc = self.bmc
        return bmc.type_inst.get_sol_command(self)

    def check_permission(self, user, min_priv_level='any'):
        # XXX: min_priv_level is something like 'any', 'assignee', 'admin'
        if user.admin:
            return True
        elif min_priv_level == 'admin':
            return False

        if user in self.assignees:
            return True
        elif min_priv_level == 'assignee':
            return False

        return True

    @staticmethod
    def can_create(user):
        return True if user.admin else False

    @staticmethod
    def by_mac(mac):
        try:
            interface = Interface.query.filter_by(mac=mac).one()
            return Machine.query.get(interface.machine_id)
        except NoResultFound:
            return None