Skip to content

Commit 36ee1f9

Browse files
committed
added arbitrary property entry
1 parent 07ce7e0 commit 36ee1f9

File tree

2 files changed

+47
-31
lines changed

2 files changed

+47
-31
lines changed

bale/scheduler.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
@dataclass(kw_only=True)
1212
class Automation:
1313
id: str
14+
name: str
1415
app: str
1516
hosts: List[str]
1617
host: str
@@ -30,6 +31,7 @@ def to_dict(self) -> Dict[str, Any]:
3031
class Zfs_Autobackup(Automation):
3132
app: str = "zfs_autobackup"
3233
execute_mode: str = "local"
34+
prop: str
3335
target_host: str
3436
target_path: str
3537
target_paths: List[str]

bale/tabs/automation.py

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Dict, List, Union
1+
from typing import Any, Callable, Dict, List, Union
22
import asyncio
33
from datetime import datetime
44
import json
@@ -36,20 +36,20 @@ def populate_job_handler(app: str, job_id: str, host: str):
3636
return job_handlers[job_id]
3737

3838

39-
class CommandTemplate(string.Template):
39+
class AutomationTemplate(string.Template):
4040
delimiter = ""
4141

4242

4343
async def automation_job(**kwargs) -> None:
4444
if "data" in kwargs:
4545
jd = json.loads(kwargs["data"])
46-
command = CommandTemplate(jd["command"])
46+
command = AutomationTemplate(jd["command"])
4747
tab = Tab(host=None, spinner=None)
4848
if jd["app"] == "zfs_autobackup":
4949
d = scheduler.Zfs_Autobackup(**jd)
5050
populate_job_handler(app=d.app, job_id=d.id, host=d.host)
5151
if job_handlers[d.id].is_busy is False:
52-
result = await job_handlers[d.id].execute(command.safe_substitute(host=d.host))
52+
result = await job_handlers[d.id].execute(command.safe_substitute(name=d.name, host=d.host))
5353
result.name = d.host
5454
result.status = "success" if result.return_code == 0 else "error"
5555
if d.pipe_success is True and result.status == "success":
@@ -63,7 +63,7 @@ async def automation_job(**kwargs) -> None:
6363
d = scheduler.Automation(**jd)
6464
populate_job_handler(app=d.app, job_id=d.id, host=d.host)
6565
if job_handlers[d.id].is_busy is False:
66-
result = await job_handlers[d.id].execute(command.safe_substitute(host=d.host))
66+
result = await job_handlers[d.id].execute(command.safe_substitute(name=d.name, host=d.host))
6767
result.name = d.host
6868
if d.pipe_success is True and result.status == "success":
6969
tab.pipe_result(result=result)
@@ -76,7 +76,7 @@ async def automation_job(**kwargs) -> None:
7676
d = scheduler.Automation(**jd)
7777
populate_job_handler(app=d.app, job_id=d.id, host=d.host)
7878
if job_handlers[d.id].is_busy is False:
79-
result = await job_handlers[d.id].execute(command.safe_substitute(host=d.host))
79+
result = await job_handlers[d.id].execute(command.safe_substitute(name=d.name, host=d.host))
8080
result.name = d.host
8181
if d.pipe_success is True and result.status == "success":
8282
tab.pipe_result(result=result)
@@ -99,7 +99,7 @@ def __init__(self, spinner, host: Union[str, None] = None) -> None:
9999
self.job_data: Dict[str, str] = {}
100100
self.job_names: List[str] = []
101101
self.default_options: Dict[str, str] = {}
102-
self.build_command: str = ""
102+
self.build_command: Callable
103103
self.target_host: el.DSelect
104104
self.target_paths: List[str] = [""]
105105
self.target_path: el.DSelect
@@ -308,26 +308,17 @@ async def _edit_automation(self) -> None:
308308
await self._create_automation(rows[0]["name"])
309309
self._set_selection()
310310

311-
async def _add_prop_to_fs(
312-
self,
313-
host: str,
314-
prop: str,
315-
value: str,
316-
module: str = "autobackup",
317-
filesystems: Union[List[str], None] = None,
318-
) -> None:
311+
async def _add_prop_to_fs(self, host: str, prop: str, value: str, filesystems: Union[List[str], None] = None) -> None:
319312
if filesystems is not None:
320-
full_prop = f"{module}:{prop}"
321313
for fs in filesystems:
322-
result = await self._zfs[host].add_filesystem_prop(filesystem=fs, prop=full_prop, value=value)
314+
result = await self._zfs[host].add_filesystem_prop(filesystem=fs, prop=prop, value=value)
323315
self.add_history(result=result)
324316

325-
async def _remove_prop_from_all_fs(self, host: str, prop: str, module: str = "autobackup") -> None:
326-
full_prop = f"{module}:{prop}"
327-
filesystems_with_prop_result = await self._zfs[host].filesystems_with_prop(full_prop)
317+
async def _remove_prop_from_all_fs(self, host: str, prop: str) -> None:
318+
filesystems_with_prop_result = await self._zfs[host].filesystems_with_prop(prop)
328319
filesystems_with_prop = list(filesystems_with_prop_result.data)
329320
for fs in filesystems_with_prop:
330-
result = await self._zfs[host].remove_filesystem_prop(filesystem=fs, prop=full_prop)
321+
result = await self._zfs[host].remove_filesystem_prop(filesystem=fs, prop=prop)
331322
self.add_history(result=result)
332323

333324
async def _create_automation(self, name: str = "") -> None:
@@ -421,15 +412,16 @@ async def target_host_selected() -> None:
421412
self.target_path.update()
422413
self.target_path.value = ""
423414

424-
async def target_path_selected() -> None:
425-
self.build_command()
426-
427415
def build_command() -> None:
416+
try:
417+
prop_suffix = self.prop.value.split(":")[1]
418+
except IndexError:
419+
prop_suffix = ""
428420
base = ""
429421
for key, value in self.picked_options.items():
430422
base = base + f" --{key}{f' {value}' if value != '' else ''}"
431423
target_path = f"{f' {self.target_path.value}' if self.target_path.value != '' else ''}"
432-
base = base + f" {self.auto_name.value.lower()}" + target_path
424+
base = base + f" {prop_suffix}" + target_path
433425
self.command.value = base
434426

435427
def all_fs_to_lists():
@@ -476,6 +468,17 @@ def cull_fs_list(e: events.GenericEventArguments, value: str = "false") -> None:
476468
self.children.update()
477469
self.exclude.update()
478470

471+
def validate_prop(value):
472+
parts = value.split(":")
473+
for part in parts:
474+
if part.find(" ") != -1:
475+
return False
476+
if len(part) < 1:
477+
return False
478+
if len(parts) != 2:
479+
return False
480+
return True
481+
479482
if name == "":
480483
self.default_options = {
481484
"verbose": "",
@@ -496,9 +499,11 @@ def cull_fs_list(e: events.GenericEventArguments, value: str = "false") -> None:
496499
row.tailwind.width("[860px]").justify_content("center")
497500
with ui.column() as col:
498501
col.tailwind.height("full").width("[420px]")
502+
self.prop = el.DInput(label="Property", value="autobackup:{name}", on_change=build_command, validation=validate_prop)
503+
self.app_em.append(self.prop)
499504
self.target_host = el.DSelect(target_host, label="Target Host", on_change=target_host_selected)
500505
self.target_paths = [""]
501-
self.target_path = el.DSelect(self.target_paths, value="", label="Target Path", new_value_mode="add-unique", on_change=target_path_selected)
506+
self.target_path = el.DSelect(self.target_paths, value="", label="Target Path", new_value_mode="add-unique", on_change=build_command)
502507
self.hosts = el.DSelect(source_hosts, label="Source Host(s)", multiple=True, with_input=True)
503508
all_fs_to_lists()
504509
with ui.scroll_area().classes("col"):
@@ -534,6 +539,7 @@ def cull_fs_list(e: events.GenericEventArguments, value: str = "false") -> None:
534539
col.tailwind.height("full").width("[420px]")
535540
options_controls()
536541
if name != "":
542+
self.prop.value = self.job_data.get("prop", "autobackup:{name}")
537543
self.target_host.value = self.job_data.get("target_host", "")
538544
target_path = self.job_data.get("target_path", "")
539545
tries = 0
@@ -758,7 +764,9 @@ def validate_hosts(e):
758764
with el.WRow() as row:
759765
row.tailwind.height("[40px]")
760766
self.as_spinner = el.Spinner()
767+
self.app_em = el.ErrorAggregator()
761768
self.save = el.DButton("SAVE", on_click=lambda: automation_dialog.submit("save"))
769+
self.save.bind_enabled_from(self.app_em, "no_errors")
762770
el.Spinner(master=self.as_spinner)
763771
self.auto_name.value = name
764772
if name != "":
@@ -779,18 +787,21 @@ def validate_hosts(e):
779787
self.scheduler.scheduler.remove_job(job.id)
780788
for host in hosts:
781789
auto_id = f"{auto_name}@{host}"
782-
await self._remove_prop_from_all_fs(host=host, prop=auto_name)
783-
await self._add_prop_to_fs(host=host, prop=auto_name, value="true", filesystems=self.parentchildren.value)
784-
await self._add_prop_to_fs(host=host, prop=auto_name, value="parent", filesystems=self.parent.value)
785-
await self._add_prop_to_fs(host=host, prop=auto_name, value="child", filesystems=self.children.value)
786-
await self._add_prop_to_fs(host=host, prop=auto_name, value="false", filesystems=self.exclude.value)
790+
command = AutomationTemplate(self.prop.value)
791+
prop = command.safe_substitute(name=auto_name, host=host)
792+
await self._remove_prop_from_all_fs(host=host, prop=prop)
793+
await self._add_prop_to_fs(host=host, prop=prop, value="true", filesystems=self.parentchildren.value)
794+
await self._add_prop_to_fs(host=host, prop=prop, value="parent", filesystems=self.parent.value)
795+
await self._add_prop_to_fs(host=host, prop=prop, value="child", filesystems=self.children.value)
796+
await self._add_prop_to_fs(host=host, prop=prop, value="false", filesystems=self.exclude.value)
787797
self.fs["values"] = {}
788798
self.fs["values"]["parentchildren"] = self.parentchildren.value
789799
self.fs["values"]["parent"] = self.parent.value
790800
self.fs["values"]["children"] = self.children.value
791801
self.fs["values"]["exclude"] = self.exclude.value
792802
auto = scheduler.Zfs_Autobackup(
793803
id=auto_id,
804+
name=auto_name,
794805
hosts=hosts,
795806
host=host,
796807
command="python -m zfs_autobackup.ZfsAutobackup" + self.command.value,
@@ -803,6 +814,7 @@ def validate_hosts(e):
803814
filesystems=self.fs,
804815
pipe_success=self.pipe_success.value,
805816
pipe_error=self.pipe_error.value,
817+
prop=self.prop.value,
806818
)
807819
self.scheduler.scheduler.add_job(
808820
automation_job,
@@ -822,6 +834,7 @@ def validate_hosts(e):
822834
auto_id = f"{auto_name}@{host}"
823835
auto = scheduler.Automation(
824836
id=auto_id,
837+
name=auto_name,
825838
app=self.app.value,
826839
hosts=hosts,
827840
host=host,
@@ -844,6 +857,7 @@ def validate_hosts(e):
844857
auto_id = f"{auto_name}@{self.host}"
845858
auto = scheduler.Automation(
846859
id=auto_id,
860+
name=auto_name,
847861
app=self.app.value,
848862
hosts=hosts,
849863
host=self.host,

0 commit comments

Comments
 (0)