3 # Sample invocation: PYTHONPATH=build/lib/ kdo quentin/root python3.8 ~/Documents/MIT/SIPB/XVM/invirt-deactivate --uri postgresql://postgres:@localhost:1235/invirt --remote xvm-remote.mit.edu --force 2>&1 | tee shutdown-20201020.log
7 from invirt import database
8 from invirt.database import record, models
11 from sqlalchemy import func
12 from sqlalchemy import *
13 from sqlalchemy import orm
14 from sqlalchemy.orm import create_session, relation
15 from subprocess import check_call, check_output
18 lockers_table = Table(
19 'lockers', models.meta,
20 Column('name', String, nullable=False, primary_key=True),
21 Column('type', Enum("AFS", "ERR", name='locker_type')),
22 Column('message', String),
25 class Locker(record.Record):
26 _identity_field = 'name'
28 models.mapper(Locker, lockers_table)
31 for i in sorted(l, key=lambda i: str(i)):
32 if not hasattr(i, '__iter__') or isinstance(i, (str, bytes)):
34 print("\t".join(str(x) for x in i))
37 parser = argparse.ArgumentParser(description='Set memory, disk, and VM quotas')
39 parser.add_argument('-u', '--uri', type=str, dest='uri',
40 help='Database URI (e.g. postgresql://postgres:@localhost:1234/invirt)')
41 parser.add_argument('-r', '--remote-host', type=str, dest='remote',
42 default='xvm-remote-dev.mit.edu',
44 parser.add_argument('-f', '--force', action='store_true', dest='force',
47 args = parser.parse_args()
49 database.connect(args.uri)
50 database.session.begin()
52 lockers_table.create(checkfirst=True)
54 owners = database.session.query(database.Machine.owner).distinct()
56 l = Locker.query.get(o)
60 fs = hesiod.FilsysLookup(o).filsys
62 l.message=fs[0].get('message')
63 except FileNotFoundError:
67 print("Error looking up", o)
69 database.session.commit()
71 database.session.begin()
72 machines_no_access = database.session.query(database.Machine).filter(~database.Machine.acl.any()).all()
74 machines_no_locker = database.session.query(database.Machine).join(Locker, database.Machine.owner == Locker.name).filter(Locker.type == None).all()
75 machines_err_locker = database.session.query(database.Machine, Locker.message).join(Locker, database.Machine.owner == Locker.name).filter(Locker.type == 'ERR').all()
77 print("Machines with no admin users:\n")
78 print_list(machines_no_access)
79 print("\nMachines with missing locker:\n")
80 print_list(machines_no_locker)
81 print("\nMachines with ERR locker:\n")
82 print_list(machines_err_locker)
84 listvms = yaml.safe_load(check_output(
85 ['remctl', args.remote, 'web', 'listvms'],
88 machines_running = set(listvms)
89 machines_broken_locker = set(machines_no_locker) | set(m for (m,msg) in machines_err_locker)
90 machines_deactivate = set(machines_no_access) & machines_broken_locker
91 print("\nMachines with no admin users AND broken locker:\n")
92 print_list(machines_deactivate)
93 machines_to_shut_down = database.Machine.query.filter(database.Machine.name.in_(machines_running & set(m.name for m in machines_deactivate))).all()
94 print("\nMachines to shutdown%s:\n" % (" (WILL SHUTDOWN)" if args.force else ""))
95 print_list(machines_to_shut_down)
97 if input("Are you sure (yes/NO)?") != "yes":
101 for m in machines_to_shut_down:
104 database.session.commit()
107 for m in machines_to_shut_down:
108 c = ['remctl', args.remote, 'control', m.name, 'shutdown']
114 print("Waiting 30 seconds for VMs to exit")
116 for m in machines_to_shut_down:
117 c = ['remctl', args.remote, 'control', m.name, 'destroy']
124 if __name__ == '__main__':