Skip to content

Commit 8611382

Browse files
committed
Implement transactions
1 parent 37a75fd commit 8611382

File tree

11 files changed

+995
-37
lines changed

11 files changed

+995
-37
lines changed

cobbler/actions/sync.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ def rsync_gen(self):
296296

297297
self.templar.render(template_data, metadata, "/etc/rsyncd.conf")
298298

299-
def add_single_distro(self, name):
299+
def add_single_distro(self, name, rebuild_menu: bool = True):
300300
"""
301301
Sync adding a single distro.
302302
@@ -331,9 +331,10 @@ def add_single_distro(self, name):
331331
kids = self.api.find_items("profile", {"distro": name}, return_list=True)
332332
for k in kids:
333333
self.add_single_profile(k, rebuild_menu=False)
334-
self.tftpgen.make_pxe_menu()
334+
if rebuild_menu:
335+
self.tftpgen.make_pxe_menu()
335336

336-
def add_single_image(self, name):
337+
def add_single_image(self, name, rebuild_menu: bool = True):
337338
"""
338339
Sync adding a single image.
339340
@@ -344,7 +345,8 @@ def add_single_image(self, name):
344345
kids = self.api.find_items("system", {"image": name})
345346
for k in kids:
346347
self.add_single_system(k)
347-
self.tftpgen.make_pxe_menu()
348+
if rebuild_menu:
349+
self.tftpgen.make_pxe_menu()
348350

349351
def remove_single_distro(self, name):
350352
"""

cobbler/api.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import threading
2727
from configparser import ConfigParser
2828
from pathlib import Path
29-
from typing import Dict, List, Optional, Union
29+
from typing import Dict, List, Optional, Tuple, Union
3030

3131
from schema import SchemaError
3232

@@ -1005,6 +1005,45 @@ def add_menu(self, ref, check_for_duplicate_names=False, save=True):
10051005
self.add_item("menu", ref, check_for_duplicate_names=check_for_duplicate_names, save=save)
10061006

10071007
# ==========================================================================
1008+
def add_remove_items(self, items: List[Tuple[str, "Item", bool, float, str]]):
1009+
"""
1010+
Add or remove multiple items.
1011+
1012+
:param items: The list of items.
1013+
"""
1014+
for what, ref, _, mtime, base_id in items:
1015+
if base_id:
1016+
orig_ref = self.find_items(what, criteria={"uid": base_id}, return_list=False)
1017+
if not orig_ref or isinstance(orig_ref, list) or mtime != orig_ref.mtime:
1018+
raise ValueError("The item has been modified")
1019+
1020+
to_remove = [i for i in items if i[2]]
1021+
to_add = [i for i in items if not i[2]]
1022+
1023+
to_remove.sort(key=lambda x: -x[1].depth)
1024+
to_add.sort(key=lambda x: x[1].depth)
1025+
1026+
for what, ref, _, _, _ in to_add:
1027+
self.log(f"add_item({what})", [ref.name])
1028+
self.get_items(what).add(
1029+
ref, # type: ignore
1030+
check_for_duplicate_names=False,
1031+
save=True,
1032+
with_triggers=True,
1033+
rebuild_menu=False
1034+
)
1035+
1036+
for what, ref, _, _, _ in to_remove:
1037+
self.log(f"remove_item({what})", [ref.name])
1038+
self.get_items(what).remove(
1039+
ref.name,
1040+
recursive=False,
1041+
with_delete=True,
1042+
with_triggers=True,
1043+
rebuild_menu=False
1044+
)
1045+
1046+
self.tftpgen.make_pxe_menu()
10081047

10091048
def find_items(self, what: str = "", criteria: dict = None, name: str = "", return_list: bool = True,
10101049
no_errors: bool = False):

cobbler/cobbler_collections/collection.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def remove(
8484
with_sync: bool = True,
8585
with_triggers: bool = True,
8686
recursive: bool = False,
87+
rebuild_menu: bool = True,
8788
) -> None:
8889
"""
8990
Remove an item from collection. This method must be overridden in any subclass.
@@ -93,6 +94,7 @@ def remove(
9394
:param with_sync: sync to server file system
9495
:param with_triggers: run "on delete" triggers
9596
:param recursive: recursively delete children
97+
:param rebuild_menu: rebuild menu after removing the item
9698
:returns: NotImplementedError
9799
"""
98100
raise NotImplementedError("Please implement this in a child class of this class.")
@@ -338,6 +340,7 @@ def add(
338340
with_sync: bool = True,
339341
quick_pxe_update: bool = False,
340342
check_for_duplicate_names: bool = False,
343+
rebuild_menu: bool = True,
341344
):
342345
"""
343346
Add an object to the collection
@@ -415,7 +418,7 @@ def add(
415418
# we don't need openvz containers to be network bootable
416419
if ref.virt_type == "openvz":
417420
ref.enable_menu = False
418-
self.lite_sync.add_single_profile(ref)
421+
self.lite_sync.add_single_profile(ref, rebuild_menu=rebuild_menu)
419422
self.api.sync_systems(
420423
systems=self.find(
421424
"system",
@@ -425,9 +428,9 @@ def add(
425428
)
426429
)
427430
elif isinstance(ref, distro.Distro):
428-
self.lite_sync.add_single_distro(ref.name)
431+
self.lite_sync.add_single_distro(ref.name, rebuild_menu=rebuild_menu)
429432
elif isinstance(ref, image.Image):
430-
self.lite_sync.add_single_image(ref.name)
433+
self.lite_sync.add_single_image(ref.name, rebuild_menu=rebuild_menu)
431434
elif isinstance(ref, repo.Repo):
432435
pass
433436
elif isinstance(ref, mgmtclass.Mgmtclass):

cobbler/cobbler_collections/distros.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def factory_produce(self, api, item_dict):
4949
return new_distro
5050

5151
def remove(self, name, with_delete: bool = True, with_sync: bool = True, with_triggers: bool = True,
52-
recursive: bool = False):
52+
recursive: bool = False, rebuild_menu: bool = True):
5353
"""
5454
Remove element named 'name' from the collection
5555

cobbler/cobbler_collections/images.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def factory_produce(self, api, item_dict):
4040
return new_image
4141

4242
def remove(self, name, with_delete: bool = True, with_sync: bool = True, with_triggers: bool = True,
43-
recursive: bool = True):
43+
recursive: bool = True, rebuild_menu: bool = True):
4444
"""
4545
Remove element named 'name' from the collection
4646

cobbler/cobbler_collections/profiles.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def factory_produce(self, api, item_dict):
4646
return new_profile
4747

4848
def remove(self, name: str, with_delete: bool = True, with_sync: bool = True, with_triggers: bool = True,
49-
recursive: bool = False):
49+
recursive: bool = False, rebuild_menu: bool = True):
5050
"""
5151
Remove element named 'name' from the collection
5252

cobbler/items/item.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -817,21 +817,27 @@ def parent(self) -> Any:
817817
return self.api.get_items(self.COLLECTION_TYPE).get(self._parent)
818818

819819
@parent.setter
820-
def parent(self, parent: str):
820+
def parent(self, parent: Union["Item", str]):
821821
"""
822822
Set the parent object for this object.
823823
824824
:param parent: The new parent object. This needs to be a descendant in the logical inheritance chain.
825825
"""
826-
if not isinstance(parent, str):
827-
raise TypeError('Property "parent" must be of type str!')
826+
found = None
827+
if isinstance(parent, Item):
828+
found = parent
829+
parent = parent.name
830+
elif not isinstance(parent, str):
831+
raise TypeError('Property "parent" must be of type Item or str!')
832+
828833
if not parent:
829834
self._parent = ""
830835
return
831836
if parent == self.name:
832837
# check must be done in two places as setting parent could be called before/after setting name...
833838
raise CX("self parentage is weird")
834-
found = self.api.get_items(self.COLLECTION_TYPE).get(parent)
839+
if found is None:
840+
found = self.api.get_items(self.COLLECTION_TYPE).get(parent)
835841
if found is None:
836842
raise CX(f'profile "{parent}" not found, inheritance not possible')
837843
self._parent = parent

cobbler/items/profile.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,18 +189,23 @@ def distro(self):
189189
return self.api.distros().find(name=self._distro)
190190

191191
@distro.setter
192-
def distro(self, distro_name: str):
192+
def distro(self, distro_name: Union["Distro", str]):
193193
"""
194194
Sets the distro. This must be the name of an existing Distro object in the Distros collection.
195195
196196
:param distro_name: The name of the distro.
197197
"""
198-
if not isinstance(distro_name, str):
199-
raise TypeError("distro_name needs to be of type str")
198+
distro = None
199+
if isinstance(distro_name, Distro):
200+
distro = distro_name
201+
distro_name = distro.name
202+
elif not isinstance(distro_name, str):
203+
raise TypeError("distro_name needs to be of type Distro or str")
200204
if not distro_name:
201205
self._distro = ""
202206
return
203-
distro = self.api.distros().find(name=distro_name)
207+
if distro is None:
208+
distro = self.api.distros().find(name=distro_name)
204209
if distro is None:
205210
raise ValueError('distribution "%s" not found' % distro_name)
206211
self._distro = distro_name

0 commit comments

Comments
 (0)