rel_path: str,
start: Optional[str] = None,
subvol: Optional[str] = None,
+ group: Optional[str] = None,
retention_policy: str = '{}',
created: Optional[str] = None,
first: Optional[str] = None,
) -> None:
self.fs = fs_name
self.subvol = subvol
+ self.group = group
self.path = path
self.rel_path = rel_path
self.schedule = schedule
cast(str, table_row['rel_path']),
cast(str, table_row['start']),
cast(str, table_row['subvol']),
+ cast(str, table_row['group_name']),
cast(str, table_row['retention']),
cast(str, table_row['created']),
cast(str, table_row['first']),
ORDER BY until;'''
PROTO_GET_SCHEDULES = '''SELECT
- s.path, s.subvol, s.rel_path, sm.active,
+ s.path, s.subvol, s.group_name, s.rel_path, sm.active,
sm.schedule, s.retention, sm.start, sm.first, sm.last,
sm.last_pruned, sm.created, sm.created_count, sm.pruned_count
FROM schedules s
return [cls._from_db_row(row, fs) for row in c.fetchall()]
INSERT_SCHEDULE = '''INSERT INTO
- schedules(path, subvol, retention, rel_path)
- Values(?, ?, ?, ?);'''
+ schedules(path, subvol, group_name, retention, rel_path)
+ Values(?, ?, ?, ?, ?);'''
INSERT_SCHEDULE_META = '''INSERT INTO
schedules_meta(schedule_id, start, created, repeat, schedule,
active)
c = db.execute(self.INSERT_SCHEDULE,
(self.path,
self.subvol,
+ self.group,
json.dumps(self.retention),
self.rel_path,))
sched_id = c.lastrowid
def dump_on_update(self) -> None:
return self.mgr.get_module_option('dump_on_update')
+ def _create_snap_schedule_kv_db(self, db: sqlite3.Connection) -> None:
+ SQL = """
+ CREATE TABLE IF NOT EXISTS SnapScheduleModuleKV (
+ key TEXT PRIMARY KEY,
+ value NOT NULL
+ ) WITHOUT ROWID;
+ INSERT OR IGNORE INTO SnapScheduleModuleKV (key, value) VALUES ('__snap_schedule_db_version', 1);
+ """
+ db.executescript(SQL)
+
+ def _get_snap_schedule_db_version(self, db: sqlite3.Connection) -> int:
+ SQL = """
+ SELECT value
+ FROM SnapScheduleModuleKV
+ WHERE key = '__snap_schedule_db_version';
+ """
+ cur = db.execute(SQL)
+ row = cur.fetchone()
+ assert row is not None
+ return int(row[0])
+
+ # add all upgrades here
+ def _upgrade_snap_schedule_db_schema(self, db: sqlite3.Connection) -> None:
+ # add a column to hold the subvolume group name
+ if self._get_snap_schedule_db_version(db) < 2:
+ SQL = """
+ ALTER TABLE schedules
+ ADD COLUMN group_name TEXT;
+ """
+ db.executescript(SQL)
+
+ # bump up the snap-schedule db version to 2
+ SQL = "UPDATE OR ROLLBACK SnapScheduleModuleKV SET value = ? WHERE key = '__snap_schedule_db_version';"
+ db.execute(SQL, (2,))
+
def get_schedule_db(self, fs: str) -> DBConnectionManager:
dbinfo = None
self.conn_lock.acquire()
except rados.ObjectNotFound:
log.debug(f'No legacy schedule DB found in {fs}')
db.executescript(Schedule.CREATE_TABLES)
+ self._create_snap_schedule_kv_db(db)
+ self._upgrade_snap_schedule_db_schema(db)
self.sqlite_connections[fs] = DBInfo(fs, db)
dbinfo = self.sqlite_connections[fs]
self.conn_lock.release()
def store_snap_schedule(self,
fs: str, path_: str,
args: Tuple[str, str, str, str,
- Optional[str], Optional[str]]) -> None:
+ Optional[str], Optional[str],
+ Optional[str]]) -> None:
sched = Schedule(*args)
log.debug(f'repeat is {sched.repeat}')
if sched.parse_schedule(sched.schedule)[1] == 'm' and not self.allow_minute_snaps: