kapsikkum-unmanic – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #!/usr/bin/env python3 |
2 | # -*- coding: utf-8 -*- |
||
3 | |||
4 | """ |
||
5 | unmanic.worker_group.py |
||
6 | |||
7 | Written by: Josh.5 <jsunnex@gmail.com> |
||
8 | Date: 18 Apr 2022, (4:08 PM) |
||
9 | |||
10 | Copyright: |
||
11 | Copyright (C) Josh Sunnex - All Rights Reserved |
||
12 | |||
13 | Permission is hereby granted, free of charge, to any person obtaining a copy |
||
14 | of this software and associated documentation files (the "Software"), to deal |
||
15 | in the Software without restriction, including without limitation the rights |
||
16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||
17 | copies of the Software, and to permit persons to whom the Software is |
||
18 | furnished to do so, subject to the following conditions: |
||
19 | |||
20 | The above copyright notice and this permission notice shall be included in all |
||
21 | copies or substantial portions of the Software. |
||
22 | |||
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||
24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
||
26 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
||
27 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
||
28 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE |
||
29 | OR OTHER DEALINGS IN THE SOFTWARE. |
||
30 | |||
31 | """ |
||
32 | import random |
||
33 | |||
34 | from unmanic import config |
||
35 | from unmanic.libs.unmodels import Tags |
||
36 | from unmanic.libs.unmodels.workergroups import WorkerGroups |
||
37 | from unmanic.libs.unmodels.workerschedules import WorkerSchedules |
||
38 | |||
39 | |||
40 | def generate_random_worker_group_name(): |
||
41 | names = ['Altoa', 'Anje', 'Anji', 'Azibo', 'Azra', 'Bajin', 'Baliaja', 'Benni', 'Bie', 'Ditid', 'Ecia', 'Ejie', 'Ekon', |
||
42 | 'Equinus', 'Erasto', 'Fefeya', 'Gamjee', 'Gilta', 'Girisha', 'Haijen', 'Hakalai', 'Halasuwa', 'Hamedi', 'Hokajin', |
||
43 | 'Hokima', 'Hyptu', 'Ithra', 'Jaryaya', 'Javinda', 'Javyn', 'Jijel', 'Jinjin', 'Jiranty', 'Jumoke', 'Kaijin', |
||
44 | 'Kanjin', 'Khuwei', 'Kina', 'Lakjin', 'Makas', 'Malak', 'Meimei', 'Melkree', 'Napokue', 'Nelina', 'Nepita', |
||
45 | 'Nuenvan', 'Prerrahar', 'Pujati', 'Rakash', 'Reji', 'Renji', 'Rhazin', 'Ronjaty', 'Rujabu', 'Saonji', 'Shadrala', |
||
46 | 'Shengis', 'Suja', 'Suli', 'Suliya', 'Talisa', 'Tanjin', 'Tayo', 'Tazingo', 'Tedar', 'Teshi', 'Tirezi', |
||
47 | 'Trezzahn', 'Trolgar', 'Ttarmek', 'Ugoki', 'Valja', 'Vekuzz', 'Venjo', 'Venmara', 'Vinji', 'Voyambi', 'Vujii', |
||
48 | 'Vuzashi', 'Wanjin', 'Yaci', 'Yamike', 'Yavo', 'Yera', 'Yeree', 'Yetu', 'Yishi', 'Yuhai', 'Zaejin', 'Zalma', |
||
49 | 'Zea', 'Zelaji', 'Zelea', 'Ziataaman', 'Ziataima', 'Ziatakraa', 'Zola', 'Zoljin', 'Zoti', 'Zujia', 'Zulabar', |
||
50 | 'Zulja', 'Zuljah', 'Zulkis', 'Zulraja', 'Zulrajas', 'Zulwatha', 'Zulyafi', 'Zunabar', 'Zyra', ] |
||
51 | return random.choice(names) |
||
52 | |||
53 | |||
54 | class WorkerGroup(object): |
||
55 | """ |
||
56 | WorkerGroup |
||
57 | |||
58 | Contains all data pertaining to a worker group |
||
59 | |||
60 | """ |
||
61 | |||
62 | def __init__(self, group_id: int): |
||
63 | # Ensure worker group ID is not 0 |
||
64 | if group_id < 1: |
||
65 | raise Exception("Worker group ID cannot be less than 1") |
||
66 | self.model = WorkerGroups.get_or_none(id=group_id) |
||
67 | if not self.model: |
||
68 | raise Exception("Unable to fetch Worker group with ID {}".format(group_id)) |
||
69 | |||
70 | @staticmethod |
||
71 | def random_name(): |
||
72 | return generate_random_worker_group_name() |
||
73 | |||
74 | @staticmethod |
||
75 | def get_all_worker_groups(): |
||
76 | """ |
||
77 | Return a list of all worker groups |
||
78 | |||
79 | :return: |
||
80 | """ |
||
81 | # Fetch all worker groups from DB |
||
82 | configured_worker_groups = WorkerGroups.select() |
||
83 | |||
84 | if not configured_worker_groups: |
||
85 | default_worker_group = { |
||
86 | 'id': 1, |
||
87 | 'locked': False, |
||
88 | 'name': generate_random_worker_group_name(), |
||
89 | 'number_of_workers': 0, |
||
90 | 'tags': [], |
||
91 | 'worker_event_schedules': [], |
||
92 | } |
||
93 | |||
94 | # Migrate default worker data from |
||
95 | settings = config.Config() |
||
96 | if settings.number_of_workers is not None: |
||
97 | default_worker_group['number_of_workers'] = settings.number_of_workers |
||
98 | if settings.worker_event_schedules is not None: |
||
99 | default_worker_group['worker_event_schedules'] = settings.worker_event_schedules |
||
100 | |||
101 | # Disable the legacy settings |
||
102 | settings.set_config_item('number_of_workers', None, save_settings=True) |
||
103 | settings.set_config_item('worker_event_schedules', None, save_settings=True) |
||
104 | |||
105 | WorkerGroup.create(default_worker_group) |
||
106 | return [default_worker_group] |
||
107 | |||
108 | # Loop over results |
||
109 | worker_groups = [] |
||
110 | for group in configured_worker_groups: |
||
111 | group_config = { |
||
112 | 'id': group.id, |
||
113 | 'locked': group.locked, |
||
114 | 'name': group.name, |
||
115 | 'number_of_workers': group.number_of_workers, |
||
116 | 'worker_event_schedules': [], |
||
117 | 'tags': [], |
||
118 | } |
||
119 | # Append tags |
||
120 | for tag in group.tags.order_by(Tags.name): |
||
121 | group_config['tags'].append(tag.name) |
||
122 | # Append worker_event_schedules |
||
123 | for event_schedule in group.worker_schedules: |
||
124 | group_config['worker_event_schedules'].append({ |
||
125 | 'repetition': event_schedule.repetition, |
||
126 | 'schedule_task': event_schedule.schedule_task, |
||
127 | 'schedule_time': event_schedule.schedule_time, |
||
128 | 'schedule_worker_count': event_schedule.schedule_worker_count, |
||
129 | }) |
||
130 | |||
131 | worker_groups.append(group_config) |
||
132 | |||
133 | # Return the list of worker groups |
||
134 | return worker_groups |
||
135 | |||
136 | @staticmethod |
||
137 | def create(data: dict): |
||
138 | """ |
||
139 | Create a new library |
||
140 | |||
141 | :param data: |
||
142 | :return: |
||
143 | """ |
||
144 | # Ensure the name is not blank |
||
145 | if not data.get('name'): |
||
146 | data['name'] = generate_random_worker_group_name() |
||
147 | |||
148 | worker_group_data = { |
||
149 | 'locked': data.get('locked'), |
||
150 | 'name': data.get('name'), |
||
151 | 'number_of_workers': data.get('number_of_workers'), |
||
152 | } |
||
153 | worker_group_id = WorkerGroups.create(**worker_group_data) |
||
154 | |||
155 | # Fetch worker group |
||
156 | worker_group = WorkerGroup(int(worker_group_id.id)) |
||
157 | |||
158 | # Set lists |
||
159 | worker_group.set_tags(data.get('tags', [])) |
||
160 | worker_group.set_worker_event_schedules(data.get('worker_event_schedules', [])) |
||
161 | |||
162 | @staticmethod |
||
163 | def create_schedules(worker_group_id: int, worker_event_schedules: list): |
||
164 | for worker_event_schedule in worker_event_schedules: |
||
165 | worker_event_schedule_data = { |
||
166 | 'worker_group_id': worker_group_id, |
||
167 | 'repetition': worker_event_schedule.get('repetition'), |
||
168 | 'schedule_task': worker_event_schedule.get('schedule_task'), |
||
169 | 'schedule_time': worker_event_schedule.get('schedule_time'), |
||
170 | 'schedule_worker_count': worker_event_schedule.get('schedule_worker_count'), |
||
171 | } |
||
172 | WorkerSchedules.create(**worker_event_schedule_data) |
||
173 | |||
174 | def __remove_schedules(self): |
||
175 | """ |
||
176 | Remove all schedules |
||
177 | |||
178 | :return: |
||
179 | """ |
||
180 | query = WorkerSchedules.delete() |
||
181 | query = query.where(WorkerSchedules.worker_group_id == self.model.id) |
||
182 | return query.execute() |
||
183 | |||
184 | def get_id(self): |
||
185 | return self.model.id |
||
186 | |||
187 | def get_name(self): |
||
188 | return self.model.name |
||
189 | |||
190 | def set_name(self, value): |
||
191 | self.model.name = value |
||
192 | |||
193 | def get_locked(self): |
||
194 | return self.model.locked |
||
195 | |||
196 | def set_locked(self, value): |
||
197 | self.model.locked = value |
||
198 | |||
199 | def get_number_of_workers(self): |
||
200 | return self.model.number_of_workers |
||
201 | |||
202 | def set_number_of_workers(self, value): |
||
203 | self.model.number_of_workers = value |
||
204 | |||
205 | def get_tags(self): |
||
206 | return_value = [] |
||
207 | for tag in self.model.tags.order_by(Tags.name): |
||
208 | return_value.append(tag.name) |
||
209 | return return_value |
||
210 | |||
211 | def set_tags(self, value): |
||
212 | # Create any missing tags |
||
213 | for tag_name in value: |
||
214 | # Do not update any current tags with on_conflict_replace() as this will also change their IDs |
||
215 | # Instead, just ignore them |
||
216 | Tags.insert(name=tag_name).on_conflict_ignore().execute() |
||
217 | # Create a SELECT query for all tags with the listed names |
||
218 | tags_select_query = Tags.select().where(Tags.name.in_(value)) |
||
219 | # Clear out the current linking table of tags linked to this library |
||
220 | # Add new links for each tag that was fetched matching the provided names |
||
221 | self.model.tags.add(tags_select_query, clear_existing=True) |
||
222 | |||
223 | def get_worker_event_schedules(self): |
||
224 | return_value = [] |
||
225 | for event_schedule in self.model.worker_schedules: |
||
226 | return_value.append({ |
||
227 | 'repetition': event_schedule.repetition, |
||
228 | 'schedule_task': event_schedule.schedule_task, |
||
229 | 'schedule_time': event_schedule.schedule_time, |
||
230 | 'schedule_worker_count': event_schedule.schedule_worker_count, |
||
231 | }) |
||
232 | return return_value |
||
233 | |||
234 | def set_worker_event_schedules(self, value): |
||
235 | # Remove all schedules |
||
236 | self.__remove_schedules() |
||
237 | # Save the event schedules |
||
238 | if value: |
||
239 | WorkerGroup.create_schedules(self.model.id, value) |
||
240 | |||
241 | def save(self): |
||
242 | """ |
||
243 | Save the data for this library |
||
244 | |||
245 | :return: |
||
246 | """ |
||
247 | # Ensure a name is actually set |
||
248 | if not self.get_name(): |
||
249 | self.set_name(generate_random_worker_group_name()) |
||
250 | |||
251 | # Save changes made to model |
||
252 | self.model.save() |
||
253 | |||
254 | def delete(self): |
||
255 | """ |
||
256 | Delete the current library |
||
257 | |||
258 | :return: |
||
259 | """ |
||
260 | # Ensure we are not trying to delete a locked library |
||
261 | if self.get_locked(): |
||
262 | raise Exception("Unable to remove a locked library") |
||
263 | |||
264 | # Remove all schedules |
||
265 | self.__remove_schedules() |
||
266 | |||
267 | # Remove the library entry |
||
268 | return self.model.delete_instance(recursive=True) |