1
|
|
|
"""Data structures that combine all program data.""" |
2
|
|
|
|
3
|
1 |
|
import logging |
4
|
|
|
|
5
|
1 |
|
import yorm |
6
|
|
|
import crayons |
7
|
1 |
|
|
8
|
1 |
|
from .config import ProgramConfig |
9
|
|
|
from .status import ProgramStatus |
10
|
|
|
|
11
|
1 |
|
|
12
|
|
|
log = logging.getLogger(__name__) |
13
|
|
|
|
14
|
1 |
|
|
15
|
1 |
|
@yorm.attr(config=ProgramConfig) |
16
|
|
|
@yorm.attr(status=ProgramStatus) |
17
|
|
|
class Data: |
18
|
|
|
"""Primary wrapper for all settings.""" |
19
|
1 |
|
|
20
|
1 |
|
def __init__(self): |
21
|
1 |
|
self.config = ProgramConfig() |
22
|
1 |
|
self.status = ProgramStatus() |
23
|
|
|
self._last_counter = self.status.counter |
24
|
1 |
|
|
25
|
1 |
|
def __repr__(self): |
26
|
|
|
return "settings" |
27
|
1 |
|
|
28
|
|
|
@property |
29
|
1 |
|
def modified(self): |
30
|
1 |
|
changed = self.status.counter != self._last_counter |
31
|
1 |
|
self._last_counter = self.status.counter |
32
|
|
|
return changed |
33
|
1 |
|
|
34
|
|
|
@staticmethod |
35
|
|
|
def prune_status(config, status): |
36
|
1 |
|
"""Remove undefined applications and computers.""" |
37
|
1 |
|
log.info("Cleaning up applications and computers...") |
38
|
1 |
|
for appstatus in status.applications.copy(): |
39
|
|
|
if not config.applications.find(appstatus.application): |
40
|
|
|
status.applications.remove(appstatus) |
41
|
|
|
log.info("Removed application: %s", appstatus) |
42
|
1 |
|
else: |
43
|
1 |
|
for computerstate in appstatus.computers.copy(): |
44
|
|
|
if not config.computers.find(computerstate.computer): |
45
|
|
|
appstatus.computers.remove(computerstate) |
46
|
|
|
log.info("Removed computer: %s", computerstate) |
47
|
1 |
|
|
48
|
|
|
@staticmethod |
49
|
|
|
def queue_all_applications(config, status, computer): |
50
|
|
|
"""Queue applications for launch.""" |
51
|
|
|
log.info("Queuing applications for launch...") |
52
|
|
|
for application in config.applications: |
53
|
|
|
if application.auto_queue: |
54
|
|
|
log.debug("Queuing %s on %s...", application, computer) |
55
|
|
|
status.queue(application, computer) |
56
|
1 |
|
|
57
|
|
|
@staticmethod |
58
|
|
|
def launch_queued_applications(config, status, computer, manager): |
59
|
1 |
|
"""Launch applications that have been queued.""" |
60
|
1 |
|
log.info("Launching queued applications...") |
61
|
1 |
|
for app_status in status.applications: |
62
|
|
|
if app_status.next: |
63
|
|
|
application = config.applications.get(app_status.application) |
64
|
|
|
print(crayons.yellow( |
65
|
|
|
f"{application} is queued for {app_status.next}")) |
66
|
|
|
if app_status.next == computer: |
67
|
|
|
latest = status.get_latest(application) |
68
|
|
|
if latest in (computer, None) or application.no_wait: |
69
|
|
|
if not manager.is_running(application): |
70
|
|
|
manager.start(application) |
71
|
|
|
app_status.next = None |
72
|
|
|
else: |
73
|
|
|
print(crayons.yellow( |
74
|
|
|
f"{application} is still running on {latest}")) |
75
|
1 |
|
elif manager.is_running(application): |
76
|
|
|
manager.stop(application) |
77
|
|
|
|
78
|
|
|
@staticmethod |
79
|
|
|
def close_all_applications(config, manager): |
80
|
|
|
"""Close all applications running on this computer.""" |
81
|
|
|
log.info("Closing all applications on this computer...") |
82
|
1 |
|
for application in config.applications: |
83
|
|
|
manager.stop(application) |
84
|
|
|
|
85
|
1 |
|
@staticmethod |
86
|
1 |
|
def update_status(config, status, computer, manager): |
87
|
1 |
|
"""Update each application's status.""" |
88
|
1 |
|
log.info("Recording application status...") |
89
|
1 |
|
for application in config.applications: |
90
|
1 |
|
latest = status.get_latest(application) |
91
|
|
|
if manager.is_running(application): |
92
|
1 |
|
if computer != latest: |
93
|
1 |
|
if status.is_running(application, computer): |
94
|
1 |
|
# case 1: application just launched remotely |
95
|
1 |
|
manager.stop(application) |
96
|
|
|
status.stop(application, computer) |
97
|
|
|
print(crayons.green( |
98
|
1 |
|
f"{application} is now running on {latest}")) |
99
|
1 |
|
print(crayons.red( |
100
|
|
|
f"{application} is now stopped on {computer}")) |
101
|
|
|
else: |
102
|
1 |
|
# case 2: application just launched locally |
103
|
|
|
status.start(application, computer) |
104
|
1 |
|
print(crayons.green( |
105
|
|
|
f"{application} is now running on {computer}")) |
106
|
1 |
|
else: |
107
|
1 |
|
# case 3: application already running locally |
108
|
|
|
print(crayons.magenta( |
109
|
|
|
f"{application} is running on {computer}")) |
110
|
1 |
|
else: |
111
|
|
|
if status.is_running(application, computer): |
112
|
|
|
# case 4: application just closed locally |
113
|
1 |
|
status.stop(application, computer) |
114
|
|
|
print(crayons.red( |
115
|
|
|
f"{application} is now stopped on {computer}")) |
116
|
|
|
elif latest: |
117
|
|
|
# case 5: application already closed locally |
118
|
1 |
|
print(crayons.blue( |
119
|
|
|
f"{application} is running on {latest}")) |
120
|
|
|
else: |
121
|
|
|
# case 6: application is not running |
122
|
|
|
print(crayons.white( |
123
|
|
|
f"{application} is not running")) |
124
|
|
|
|