v 1.0.11
- added IGridEngine abstraction that allows to switch between dry-run mode and normal mode - added more commandes to the test work related to [https://bugzilla.ipr.univ-rennes.fr/show_bug.cgi?id=3093]
This commit is contained in:
parent
a7d92a3f99
commit
f5dce0bf10
|
|
@ -1,4 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
import subprocess
|
import subprocess
|
||||||
import argparse
|
import argparse
|
||||||
|
|
@ -11,15 +12,37 @@ RequesterId = str # identifies the queue enable/disable requester eg auto.croco
|
||||||
QueueMachineId = str # identifies the queue machine eg main.q@alambix42.ipr.univ-rennes.fr
|
QueueMachineId = str # identifies the queue machine eg main.q@alambix42.ipr.univ-rennes.fr
|
||||||
|
|
||||||
|
|
||||||
def run_qmod(args):
|
class IGridEngine(ABC):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def disable_queue(self, queue_name: QueueMachineId):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def enable_queue(self, queue_name: QueueMachineId):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Sge(IGridEngine):
|
||||||
|
dry_run: bool
|
||||||
|
|
||||||
|
def __init__(self, dry_run: bool = False):
|
||||||
|
self.dry_run = dry_run
|
||||||
|
|
||||||
|
def run_qmod(self, args):
|
||||||
"""runs qmod with the given arguments."""
|
"""runs qmod with the given arguments."""
|
||||||
cmd = ["qmod"] + args
|
cmd = ["qmod"] + args
|
||||||
dry_run = True # set to True to print the command instead of executing it
|
if self.dry_run:
|
||||||
if dry_run:
|
|
||||||
print(f"Dry run: {' '.join(cmd)}")
|
print(f"Dry run: {' '.join(cmd)}")
|
||||||
else:
|
else:
|
||||||
subprocess.run(cmd, check=True)
|
subprocess.run(cmd, check=True)
|
||||||
|
|
||||||
|
def disable_queue(self, queue_name: QueueMachineId):
|
||||||
|
self.run_qmod(["-d", queue_name])
|
||||||
|
|
||||||
|
def enable_queue(self, queue_name: QueueMachineId):
|
||||||
|
self.run_qmod(["-e", queue_name])
|
||||||
|
|
||||||
|
|
||||||
def init_db(db_backend: ISqlDatabaseBackend):
|
def init_db(db_backend: ISqlDatabaseBackend):
|
||||||
if not db_backend.table_exists('log'):
|
if not db_backend.table_exists('log'):
|
||||||
|
|
@ -69,8 +92,12 @@ class DisableReason:
|
||||||
|
|
||||||
|
|
||||||
class QueueManager:
|
class QueueManager:
|
||||||
def __init__(self, db_backend: ISqlDatabaseBackend):
|
db_backend: ISqlDatabaseBackend
|
||||||
|
grid_engine: IGridEngine
|
||||||
|
|
||||||
|
def __init__(self, db_backend: ISqlDatabaseBackend, grid_engine: IGridEngine = Sge()):
|
||||||
self.db_backend = db_backend
|
self.db_backend = db_backend
|
||||||
|
self.grid_engine = grid_engine
|
||||||
|
|
||||||
def log_modification(self, queue_name: str, action: str, requester_id: RequesterId, reason: str) -> LogId:
|
def log_modification(self, queue_name: str, action: str, requester_id: RequesterId, reason: str) -> LogId:
|
||||||
assert action in ["disable", "enable"], "Action must be either 'disable' or 'enable'"
|
assert action in ["disable", "enable"], "Action must be either 'disable' or 'enable'"
|
||||||
|
|
@ -96,7 +123,7 @@ class QueueManager:
|
||||||
|
|
||||||
if len(disable_reasons) == 0:
|
if len(disable_reasons) == 0:
|
||||||
# queue is currently active, we can disable it
|
# queue is currently active, we can disable it
|
||||||
run_qmod(["-d", queue_name])
|
self.grid_engine.disable_queue(queue_name)
|
||||||
|
|
||||||
disable_log_id = self.log_modification(queue_name, "disable", requester_id, reason)
|
disable_log_id = self.log_modification(queue_name, "disable", requester_id, reason)
|
||||||
self.db_backend.query(f"INSERT INTO state (disable_reason_id, queue_name) VALUES ({disable_log_id}, '{queue_name}');")
|
self.db_backend.query(f"INSERT INTO state (disable_reason_id, queue_name) VALUES ({disable_log_id}, '{queue_name}');")
|
||||||
|
|
@ -111,7 +138,7 @@ class QueueManager:
|
||||||
|
|
||||||
assert dr_to_remove is not None, f"Requester {requester_id} has not requested deactivation of queue {queue_name}. Cannot request activation without a prior deactivation."
|
assert dr_to_remove is not None, f"Requester {requester_id} has not requested deactivation of queue {queue_name}. Cannot request activation without a prior deactivation."
|
||||||
|
|
||||||
run_qmod(["-e", queue_name])
|
self.grid_engine.enable_queue(queue_name)
|
||||||
enable_log_id = self.log_modification(queue_name, "enable", requester_id, reason) # noqa: F841
|
enable_log_id = self.log_modification(queue_name, "enable", requester_id, reason) # noqa: F841
|
||||||
self.db_backend.query(f"DELETE FROM state WHERE disable_reason_id = {dr_to_remove.log_id} AND queue_name = '{queue_name}';")
|
self.db_backend.query(f"DELETE FROM state WHERE disable_reason_id = {dr_to_remove.log_id} AND queue_name = '{queue_name}';")
|
||||||
|
|
||||||
|
|
@ -126,7 +153,7 @@ def main():
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
db_backend = create_db_backend()
|
db_backend = create_db_backend()
|
||||||
qmod = QueueManager(db_backend)
|
qmod = QueueManager(db_backend, Sge(dry_run=False)) # set dry_run to False to actually run qmod commands
|
||||||
|
|
||||||
queue = args.queue
|
queue = args.queue
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
__version__ = '1.0.10'
|
__version__ = '1.0.11'
|
||||||
|
|
||||||
|
|
||||||
class Version(object):
|
class Version(object):
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import unittest
|
||||||
import logging
|
import logging
|
||||||
# from cocluto import ClusterController
|
# from cocluto import ClusterController
|
||||||
from cocluto.SimpaDbUtil import SqliteDb
|
from cocluto.SimpaDbUtil import SqliteDb
|
||||||
from cocluto.quman import QueueManager, init_db
|
from cocluto.quman import QueueManager, init_db, Sge
|
||||||
|
|
||||||
|
|
||||||
class QumanTestCase(unittest.TestCase):
|
class QumanTestCase(unittest.TestCase):
|
||||||
|
|
@ -20,9 +20,13 @@ class QumanTestCase(unittest.TestCase):
|
||||||
db_path.unlink()
|
db_path.unlink()
|
||||||
db_backend = SqliteDb(db_path)
|
db_backend = SqliteDb(db_path)
|
||||||
init_db(db_backend)
|
init_db(db_backend)
|
||||||
quman = QueueManager(db_backend)
|
quman = QueueManager(db_backend, Sge(dry_run=True)) # set dry_run to True to not actually run qmod commands
|
||||||
|
quman.request_queue_deactivation('main.q@alambix42', 'sysadmin.graffy', 'disabled to move the alambix42 to another rack')
|
||||||
|
with self.assertRaises(AssertionError):
|
||||||
|
# attempting to disable the same queue again with the same disable tag should raise an assertion error (the tag is used to uniquely identify the disables on the machine)
|
||||||
quman.request_queue_deactivation('main.q@alambix42', 'sysadmin.graffy', 'because I want to test quman')
|
quman.request_queue_deactivation('main.q@alambix42', 'sysadmin.graffy', 'because I want to test quman')
|
||||||
quman.request_queue_activation('main.q@alambix42', 'sysadmin.graffy', 'because I want to test quman')
|
quman.request_queue_deactivation('main.q@alambix42', 'croconaus.maco-update', 'disabled to update maco')
|
||||||
|
quman.request_queue_activation('main.q@alambix42', 'sysadmin.graffy', 'alambix42 has been moved to a new rack')
|
||||||
# self.assertIsInstance(job_state, JobsState)
|
# self.assertIsInstance(job_state, JobsState)
|
||||||
db_backend.dump(Path('./quman_test/quman_dump.sql'))
|
db_backend.dump(Path('./quman_test/quman_dump.sql'))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue