class Reservation(db.Model): id = db.Column(db.Integer, primary_key=True) res_date = db.Column(db.DateTime, nullable=False) res_moment = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) is_started = db.Column(db.Boolean(), nullable=False, default=False) owner_id = db.Column(db.Integer, db.ForeignKey('setup.id'), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) def se(self): # se:Student Enviroment Starter start_time = self.res_date duration = Setup.query.filter_by( id=self.owner_id).first().period_of_res token = User.query.filter_by(id=self.user_id).first().password_sha1 setup = Setup.query.filter_by(id=self.owner_id).first() port = self.owner_id + 8800 self.bash_file(token, setup.id, port) duration = int(duration) end_time = start_time + timedelta(minutes=duration) left = end_time - datetime.now() proc = subprocess.Popen([ 'gnome-terminal', '--disable-factory', '--', 'bash', 'setup{}.sh'.format(setup.id) ], preexec_fn=os.setpgrp) o_e_id = Setup.query.filter_by(id=self.owner_id).first().owner_id self.cp_materials(o_e_id, setup.id) print(f'New student enviroment ready for {setup.name}!') time.sleep(int(left.seconds) - 10) print(f'{setup.name} is closing') os.killpg(proc.pid, signal.SIGINT) os.remove(f'setup{setup.id}.sh') print(f'{setup.name} has closed') @staticmethod def bash_file(token, setup_id, port): ip_adress = ip_find() text = [] text.append('#!/bin/bash\n') text.append('\n') text.append('sudo su - setup{} <<EOF\n'.format(setup_id)) text.append('rm -rf *\n') text.append( "jupyter notebook --no-browser --NotebookApp.token='' --NotebookApp.password={0} --ip {1} --port {2} --NotebookApp.terminals_enabled=False\n" .format(token, ip_adress, port)) text.append('EOF\n') with open('setup{}.sh'.format(setup_id), 'w') as f: f.writelines(text) @staticmethod def cp_materials(o_e_id, setup_id): time.sleep(3) #If no delay put, materials delete in the subprocess mtrls = Experiment.query.filter_by(id=o_e_id).first().materials.all() for m in mtrls: os.system(f'sudo cp uploads/{m.name} /home/setup{setup_id}/') return def __repr__(self): return f"Reservation('{self.res_date}','{self.owner_id}','{self.user_id}')"
class ActorDTO(db.Model): __tablename__ = 'actor' actor_id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(50), nullable=False) image = db.Column(db.String(500), nullable=True) description = db.Column(db.String(500), nullable=True) phone = db.Column(db.String(20), nullable=False) email = db.Column(db.String(50), nullable=False) password = db.Column(db.String(20), nullable=False, default='123') role = db.Column(db.String(5), nullable=False, default='actor') is_deleted = db.Column(db.Boolean(), default=False) def serialize(self): return { "actor_id": self.actor_id, "name": self.name, "image": self.image, "description": self.description, "phone": self.phone, "email": self.email, "role": self.role, } def merge(self, newdata): for key, value in newdata.items(): if value: setattr(self, key, value)
class ToolDTO(db.Model): __tablename__ = 'tool' tool_id = db.Column("tool_id", db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(50), nullable=False) image = db.Column(db.String(500), nullable=True) description = db.Column(db.String(500), nullable=True) quantity = db.Column(db.Integer, default=0) status = db.Column(db.String(20), nullable=True) is_deleted = db.Column(db.Boolean(), default=0) def serialize(self): return { "tool_id": self.tool_id, "name": self.name, "image": self.image, "description": self.description, "quantity": self.quantity, "status": self.status, } def merge(self, newdata): for key, value in newdata.items(): if value: setattr(self, key, value)
class Setup(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), nullable=False) period_of_res = db.Column(db.Integer, nullable=False) max_res_for_week = db.Column(db.Integer, nullable=False) #Currently not in use is_virtual = db.Column(db.Boolean(), nullable=False, default=False) product_id = db.Column(db.String(150), nullable=False) product_serial = db.Column(db.String(150), unique=True, nullable=False) owner_id = db.Column(db.Integer, db.ForeignKey('experiment.id'), nullable=False) reservations = db.relationship('Reservation', backref='owner', lazy='dynamic') def setup_user_creator(self): os.system( f'sudo useradd -m -d /home/setup{self.id} -s /bin/bash setup{self.id}' ) os.system(f'sudo chown -R setup{self.id} /home/setup{self.id}') os.system(f'sudo chmod -R 750 /home/setup{self.id}') if self.is_virtual: os.system(f'sudo usermod -a -G dialout setup{self.id}') return self.rule_file(self.product_id, self.product_serial, self.id) os.system(f'sudo cp 99-setup{self.id}.rules /etc/udev/rules.d/') os.system(f'sudo udevadm control --reload-rules && udevadm trigger') os.remove(f'99-setup{self.id}.rules') def setup_user_delete(self): if not self.is_virtual: os.system(f'sudo rm /etc/udev/rules.d/99-setup{self.id}.rules') os.system(f'sudo userdel -r setup{self.id}') @staticmethod def rule_file(product_id, product_serial, setup_id): text = [] text.append( f'SUBSYSTEM=="tty", ATTRS{{idProduct}}=="{product_id}", ATTRS{{serial}}=="{product_serial}", ACTION=="add", RUN+="/bin/setfacl -m u:setup{setup_id}:rw- /dev/$name"' ) with open(f'99-setup{setup_id}.rules', 'w') as f: f.writelines(text) def __repr__(self): return f"Setup('{self.name}','{self.period_of_res}','{self.max_res_for_week}','{self.owner_id}')"
class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(30), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) password = db.Column(db.String(120), nullable=False) password_sha1 = db.Column(db.String(120), nullable=False) is_admin = db.Column(db.Boolean(), nullable=False, default=False) reservations = db.relationship('Reservation', backref='owner_student', lazy='dynamic') classes = db.relationship( 'Course', secondary=subs, backref=db.backref('students_of_class', lazy='dynamic')) #Currently not in use def __repr__(self): return f"User('{self.username}','{self.email}')"
class TribulationDTO(db.Model): __tablename__ = 'tribulation' tribulation_id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(100), nullable=False) description = db.Column(db.String(500), nullable=True) address = db.Column(db.String(200), nullable=True) time_start = db.Column(db.DateTime, default=datetime.utcnow) time_end = db.Column(db.DateTime, default=datetime.utcnow) times = db.Column(db.Integer, default=1) url_file = db.Column(db.String(200), nullable=True) actor = db.relationship(ActorDTO, secondary='character', backref="tribulation") tool = db.relationship(ToolDTO, secondary='tool_for_tribulation', backref="tribulation") is_deleted = db.Column(db.Boolean(), default=0) def serialize(self): actor = [a.serialize() for a in self.actor] tool = [t.serialize() for t in self.tool] time_start = self.time_start.strftime("%Y-%m-%d") time_end = self.time_end.strftime("%Y-%m-%d") return { "tribulation_id": self.tribulation_id, "name": self.name, "description": self.description, "address": self.address, "time_start": time_start, "time_end": time_end, "times": self.times, "url_file": self.url_file, "actor": actor, "tool": tool } def merge(self, newdata): for key, value in newdata.items(): if key != "_sa_instance_state": print('va: ', value) setattr(self, key, value)