From 161f62d083aaf9d867120bbda8d754150479f50b Mon Sep 17 00:00:00 2001 From: grossmj Date: Fri, 5 May 2023 22:40:58 +0800 Subject: [PATCH 1/2] Install empty Qemu disks on first start --- gns3server/controller/__init__.py | 36 +++++++++++++++++++++++++++++- gns3server/disks/empty100G.qcow2 | Bin 0 -> 198208 bytes gns3server/disks/empty10G.qcow2 | Bin 0 -> 196768 bytes gns3server/disks/empty150G.qcow2 | Bin 0 -> 199008 bytes gns3server/disks/empty1T.qcow2 | Bin 0 -> 212992 bytes gns3server/disks/empty200G.qcow2 | Bin 0 -> 199808 bytes gns3server/disks/empty20G.qcow2 | Bin 0 -> 196928 bytes gns3server/disks/empty250G.qcow2 | Bin 0 -> 200608 bytes gns3server/disks/empty30G.qcow2 | Bin 0 -> 197088 bytes gns3server/disks/empty40G.qcow2 | Bin 0 -> 197248 bytes gns3server/disks/empty500G.qcow2 | Bin 0 -> 204608 bytes gns3server/disks/empty50G.qcow2 | Bin 0 -> 197408 bytes gns3server/disks/empty8G.qcow2 | Bin 0 -> 196736 bytes gns3server/utils/images.py | 36 +++++++++++++++--------------- 14 files changed, 53 insertions(+), 19 deletions(-) create mode 100644 gns3server/disks/empty100G.qcow2 create mode 100644 gns3server/disks/empty10G.qcow2 create mode 100644 gns3server/disks/empty150G.qcow2 create mode 100644 gns3server/disks/empty1T.qcow2 create mode 100644 gns3server/disks/empty200G.qcow2 create mode 100644 gns3server/disks/empty20G.qcow2 create mode 100644 gns3server/disks/empty250G.qcow2 create mode 100644 gns3server/disks/empty30G.qcow2 create mode 100644 gns3server/disks/empty40G.qcow2 create mode 100644 gns3server/disks/empty500G.qcow2 create mode 100644 gns3server/disks/empty50G.qcow2 create mode 100755 gns3server/disks/empty8G.qcow2 diff --git a/gns3server/controller/__init__.py b/gns3server/controller/__init__.py index 84e02ce9..8590ef33 100644 --- a/gns3server/controller/__init__.py +++ b/gns3server/controller/__init__.py @@ -30,6 +30,7 @@ except ImportError: from ..config import Config from ..utils import parse_version +from ..utils.images import default_images_directory from .project import Project from .template import Template @@ -72,6 +73,7 @@ class Controller: log.info("Controller is starting") self._install_base_configs() + self._install_builtin_disks() server_config = Config.instance().get_section_config("Server") Config.instance().listen_for_config_changes(self._update_config) host = server_config.get("host", "localhost") @@ -281,7 +283,7 @@ class Controller: def _install_base_configs(self): """ - At startup we copy base file to the user location to allow + At startup we copy base configs to the user location to allow them to customize it """ @@ -302,6 +304,29 @@ class Controller: except OSError as e: log.error(f"Could not install base config files to {dst_path}: {e}") + def _install_builtin_disks(self): + """ + At startup we copy built-in Qemu disks to the user location to allow + them to use with appliances + """ + + dst_path = self.disks_path() + log.info(f"Installing built-in disks in '{dst_path}'") + try: + if hasattr(sys, "frozen") and sys.platform.startswith("win"): + resource_path = os.path.normpath(os.path.join(os.path.dirname(sys.executable), "disks")) + for filename in os.listdir(resource_path): + if not os.path.exists(os.path.join(dst_path, filename)): + shutil.copy(os.path.join(resource_path, filename), os.path.join(dst_path, filename)) + else: + for entry in importlib_resources.files('gns3server.disks').iterdir(): + full_path = os.path.join(dst_path, entry.name) + if entry.is_file() and not os.path.exists(full_path): + log.debug(f"Installing disk file {entry.name} to {full_path}") + shutil.copy(str(entry), os.path.join(dst_path, entry.name)) + except OSError as e: + log.error(f"Could not install disk files to {dst_path}: {e}") + def images_path(self): """ Get the image storage directory @@ -322,6 +347,15 @@ class Controller: os.makedirs(configs_path, exist_ok=True) return configs_path + def disks_path(self, emulator_type="qemu"): + """ + Get the disks storage directory + """ + + disks_path = default_images_directory(emulator_type) + os.makedirs(disks_path, exist_ok=True) + return disks_path + async def add_compute(self, compute_id=None, name=None, force=False, connect=True, **kwargs): """ Add a server to the dictionary of computes controlled by this controller diff --git a/gns3server/disks/empty100G.qcow2 b/gns3server/disks/empty100G.qcow2 new file mode 100644 index 0000000000000000000000000000000000000000..94ed3e44235dff509c61e8dd957aedd42b219f18 GIT binary patch literal 198208 zcmeIuF;2rU6aY{s?EzTXd9Re74%Od8~A|OBn{4W!3#!_7`G(troGa`YO(wMH)R|GFvUXoYw1R)y96)jaP>-{oKE;Qyp)w zVru)`r1i)FMOaj?o0!vlwt8y&vC`cxWf)|ZRrhP**O_IJtLONm=aIjWB0zuu0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!Csrf$~ILm;eC+1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7&PSjK`}=%4 z)+qr31PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly gK!5-N0t5&UAV7cs0RjXF5FkK+009C72>e5V4?RUN@&Et; literal 0 HcmV?d00001 diff --git a/gns3server/disks/empty150G.qcow2 b/gns3server/disks/empty150G.qcow2 new file mode 100644 index 0000000000000000000000000000000000000000..da50806077060ba0bf49a0dd0639500415a0f044 GIT binary patch literal 199008 zcmeIuF;2rU6aY{s?EyG~7d9pifrP}u#2gw|L~4^LO$BA@v5{B^Ev;Z^U}5S@6vzJm z$IgHEH@EL0gvs!Hzb=Nw<@OlKu6ENyRkmC0$79XO$#lrHhwRhj?IDD08$wxi{U$zE z{UJ5}&Sp*5t=s;uU*zefPhDLsVp;S>oL7r9dcb7XEZZ)vR#j8Se$$RuhcNxzzb;c5 z@2+F2`>sl>kpr@@C|)Q?uKTgl-7a|;WR^wyYvI?KdDa!r@kh@iefi?--h}M&zEqF0n3lVAbDD)+S-ONm8 zvhU{d>MevYAD;1b9zrpCKilsQRr}PqU{w2KyBH$fA$mW5y&ZbLgizJF-^IJSKcuGD zV%g^W(Di@)VwRrzl$&xLtFkZSs$Qqb0rO?M>2lg`>$ZvguA8n7Ve!$wsZtfMFJfx? zT&L~CfFi8R=UvQcwQL`neya4d%Pb5so3i`0@N4F*$mL`FcIJt{ks?5V009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7e?5rNr}xG(_%1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72%L^U5%%}#oY+YT z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N x0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAn-2*-T{#5Fl7J$ literal 0 HcmV?d00001 diff --git a/gns3server/disks/empty200G.qcow2 b/gns3server/disks/empty200G.qcow2 new file mode 100644 index 0000000000000000000000000000000000000000..ee7ce51773208538ecb656dd432d666415497d1c GIT binary patch literal 199808 zcmeIuF;2rU6aY}C?EyG~&(K34A+azqhsG6=+9XPipiCTr<07#TTB^d(z{b#*D31OA zkDdQ+F0bB02-D&Deq9WU`7uzu?&gQ8Vz=6l$D&iS*^uZC$@}TsZ3x9n2vyzZZM>`V zAvOLk7H!`@bosAeOwvs1;(V7h46U7t3ax@}_KcH`9{%s%&Ts#L}6 zc}z|2>$Dj;pa`q-c^mt*T(l2O9xL7LG6{psy6k=}{5o?|^yOpx(eudPND&}FfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkL{guvuPT$lg>0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1kOjG2>bhd zI@T!x0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U vAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7e?KMH&R$$c>& literal 0 HcmV?d00001 diff --git a/gns3server/disks/empty20G.qcow2 b/gns3server/disks/empty20G.qcow2 new file mode 100644 index 0000000000000000000000000000000000000000..968f8fcf72fac5737f5f5109c4eeb14752ff031b GIT binary patch literal 196928 zcmeIuu};G<5CBl8Ejyo(k(rM`LSkWJ4vi}!wMpc>hNGybwN@ZwZVCzd1$G*GR zxp#ka`w>Ez4$tv*IV>)Y0$02Fp{m%e_Ty2}iRo;J_lMlm^!*`(;w^-_NqJj7Hu;bm ze;4yErA?pz`o$!^7a;%-epvI)vHR{%sxW^6t8f zZB9*Gj~q~hW%ar(Q(VluO`FF`ce_l&AhW9aUkks_oD`{gE`Rhq@;6ch2oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5I7+)IT05oK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB=E>5h%j`KA(O~%LiRAsx>emvHkoJ@yIcgQ|Y-tI%lwjq>t>NoMB z?hmQ)cQ$KNT6g_lzsRfSzDiB8h-J|iab7Q~(E}#4cG;zBwW`}D_M2|JI)v%x{!Lkx z@%A!SO`qy&HF7`}7RAdZrfNQG*G)fGy4xiWgUqt%el7euGtW}-6o2$Q@;6ch2oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5I7-_pNI<+AV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!Cvc2xMV@ zpHIg+B|v}x0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+z`qpu00s0i A4*&oF literal 0 HcmV?d00001 diff --git a/gns3server/disks/empty30G.qcow2 b/gns3server/disks/empty30G.qcow2 new file mode 100644 index 0000000000000000000000000000000000000000..414611bbd3e9110d09242dad9eff4cdeecb1b692 GIT binary patch literal 197088 zcmeIuu};G<5CBl8t;EVF_#2p+k&sxJm_y@=NF|BfR8XdVHWCY=r78>!?0t#i*moB@ z_wH|QKSBu8;rV%84vUNJF><||9;%AnYCj%pPR(XRqB|s?rtc3S6x$H0I`^CSSoeq2 z_`8_5Ij_6^zh6w!YoBscE@M^pWn9$DG_nA2k3uA6?WbhpbS3^LDU_h;evnUf-yFY#B;BYz`BfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+0D%(%lM``a0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBl~AAut5@AK(c zrvwNPAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs h0RjXF5FkK+009C72oNAZfB*pk1PBlyK;Y~IJ^{r7F&_W` literal 0 HcmV?d00001 diff --git a/gns3server/disks/empty40G.qcow2 b/gns3server/disks/empty40G.qcow2 new file mode 100644 index 0000000000000000000000000000000000000000..74d53888f4b17c7c8045977013f43b1d88e290ac GIT binary patch literal 197248 zcmeIuF;2rU6aY}C?Zm_pat028gv0<7b7))RzkV@^FFB^RT9$Q{t8&pS~sINj&*r; zUdA>JO!~g&Q literal 0 HcmV?d00001 diff --git a/gns3server/disks/empty50G.qcow2 b/gns3server/disks/empty50G.qcow2 new file mode 100644 index 0000000000000000000000000000000000000000..143669510bb66ca66a5f65f7338e51b0bd0f9f2f GIT binary patch literal 197408 zcmeIuF;2rU6aY}C?a06pdDzq>#WsYh&iy7n)cqkf z{x0Ti&QD$c*DogNrBAsjm$54QGA`<68a-e-Z&zJT>vi2WvEOv#)gjD2_iw6H#oMcx znm*TQJ#s)1mgVav=Cqi%Pfb5oy4z(E2ANga{aW~S=A_8wbNtcs$lpj2AV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK;VSHEz4A1FxHB8Erz;6DXRqSVnasN3wOo!F}nDI1ue+Z#?3t`@*yp4}dJ}!;F zi&>Y_rq6%fQPwZHPHnY}^D0+y(JbrH0+U&{>QlX5H(eX^wja+9VY)lNo!9etcOC0C zr>0(y6ez;7dfmoUFJ|4Q&10$iQ_3*Ntg8Ok#IKrVk*eqTqvw&ou|$9X0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5;&GXmwAxG(_%1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72waXp5f1m|bgWYX z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N d0t5&UAV7cs0RjXF5FkK+009C72oU&(0-w|bFm3<< literal 0 HcmV?d00001 diff --git a/gns3server/utils/images.py b/gns3server/utils/images.py index 93420069..2c5ed130 100644 --- a/gns3server/utils/images.py +++ b/gns3server/utils/images.py @@ -26,11 +26,11 @@ import logging log = logging.getLogger(__name__) -def list_images(type): +def list_images(emulator_type): """ - Scan directories for available image for a type + Scan directories for available image for a given emulator type - :param type: emulator type (dynamips, qemu, iou) + :param emulator_type: emulator type (dynamips, qemu, iou) """ files = set() images = [] @@ -38,10 +38,10 @@ def list_images(type): server_config = Config.instance().get_section_config("Server") general_images_directory = os.path.expanduser(server_config.get("images_path", "~/GNS3/images")) - # Subfolder of the general_images_directory specific to this VM type - default_directory = default_images_directory(type) + # Subfolder of the general_images_directory specific to this emulator type + default_directory = default_images_directory(emulator_type) - for directory in images_directories(type): + for directory in images_directories(emulator_type): # We limit recursion to path outside the default images directory # the reason is in the default directory manage file organization and @@ -57,9 +57,9 @@ def list_images(type): if filename not in files: if filename.endswith(".md5sum") or filename.startswith("."): continue - elif ((filename.endswith(".image") or filename.endswith(".bin")) and type == "dynamips") \ - or ((filename.endswith(".bin") or filename.startswith("i86bi")) and type == "iou") \ - or (not filename.endswith(".bin") and not filename.endswith(".image") and type == "qemu"): + elif ((filename.endswith(".image") or filename.endswith(".bin")) and emulator_type == "dynamips") \ + or ((filename.endswith(".bin") or filename.startswith("i86bi")) and emulator_type == "iou") \ + or (not filename.endswith(".bin") and not filename.endswith(".image") and emulator_type == "qemu"): files.add(filename) # It the image is located in the standard directory the path is relative @@ -69,7 +69,7 @@ def list_images(type): path = os.path.relpath(os.path.join(root, filename), default_directory) try: - if type in ["dynamips", "iou"]: + if emulator_type in ["dynamips", "iou"]: with open(os.path.join(root, filename), "rb") as f: # read the first 7 bytes of the file. elf_header_start = f.read(7) @@ -102,34 +102,34 @@ def _os_walk(directory, recurse=True, **kwargs): yield directory, [], files -def default_images_directory(type): +def default_images_directory(emulator_type): """ :returns: Return the default directory for a node type """ server_config = Config.instance().get_section_config("Server") img_dir = os.path.expanduser(server_config.get("images_path", "~/GNS3/images")) - if type == "qemu": + if emulator_type == "qemu": return os.path.join(img_dir, "QEMU") - elif type == "iou": + elif emulator_type == "iou": return os.path.join(img_dir, "IOU") - elif type == "dynamips": + elif emulator_type == "dynamips": return os.path.join(img_dir, "IOS") else: - raise NotImplementedError("%s node type is not supported", type) + raise NotImplementedError("%s node type is not supported", emulator_type) -def images_directories(type): +def images_directories(emulator_type): """ Return all directories where we will look for images by priority - :param type: Type of emulator + :param emulator_type: Type of emulator """ server_config = Config.instance().get_section_config("Server") paths = [] img_dir = os.path.expanduser(server_config.get("images_path", "~/GNS3/images")) - type_img_directory = default_images_directory(type) + type_img_directory = default_images_directory(emulator_type) try: os.makedirs(type_img_directory, exist_ok=True) paths.append(type_img_directory) From f3f79215252d2f20495ec04e6feae37a1676e65d Mon Sep 17 00:00:00 2001 From: grossmj Date: Sun, 7 May 2023 21:57:44 +0800 Subject: [PATCH 2/2] Add generic function to install resource files --- gns3server/controller/__init__.py | 42 +++++++++++----------- gns3server/controller/appliance_manager.py | 12 ++----- tests/controller/test_controller.py | 25 +++++++++++++ 3 files changed, 47 insertions(+), 32 deletions(-) diff --git a/gns3server/controller/__init__.py b/gns3server/controller/__init__.py index 8590ef33..33552c6a 100644 --- a/gns3server/controller/__init__.py +++ b/gns3server/controller/__init__.py @@ -281,6 +281,24 @@ class Controller: except OSError as e: log.error(str(e)) + @staticmethod + def install_resource_files(dst_path, resource_name): + """ + Install files from resources to user's file system + """ + + if hasattr(sys, "frozen") and sys.platform.startswith("win"): + resource_path = os.path.normpath(os.path.join(os.path.dirname(sys.executable), resource_name)) + for filename in os.listdir(resource_path): + if not os.path.exists(os.path.join(dst_path, filename)): + shutil.copy(os.path.join(resource_path, filename), os.path.join(dst_path, filename)) + else: + for entry in importlib_resources.files(f'gns3server.{resource_name}').iterdir(): + full_path = os.path.join(dst_path, entry.name) + if entry.is_file() and not os.path.exists(full_path): + log.debug(f'Installing {resource_name} resource file "{entry.name}" to "{full_path}"') + shutil.copy(str(entry), os.path.join(dst_path, entry.name)) + def _install_base_configs(self): """ At startup we copy base configs to the user location to allow @@ -290,17 +308,7 @@ class Controller: dst_path = self.configs_path() log.info(f"Installing base configs in '{dst_path}'") try: - if hasattr(sys, "frozen") and sys.platform.startswith("win"): - resource_path = os.path.normpath(os.path.join(os.path.dirname(sys.executable), "configs")) - for filename in os.listdir(resource_path): - if not os.path.exists(os.path.join(dst_path, filename)): - shutil.copy(os.path.join(resource_path, filename), os.path.join(dst_path, filename)) - else: - for entry in importlib_resources.files('gns3server.configs').iterdir(): - full_path = os.path.join(dst_path, entry.name) - if entry.is_file() and not os.path.exists(full_path): - log.debug(f"Installing base config file {entry.name} to {full_path}") - shutil.copy(str(entry), os.path.join(dst_path, entry.name)) + Controller.install_resource_files(dst_path, "configs") except OSError as e: log.error(f"Could not install base config files to {dst_path}: {e}") @@ -313,17 +321,7 @@ class Controller: dst_path = self.disks_path() log.info(f"Installing built-in disks in '{dst_path}'") try: - if hasattr(sys, "frozen") and sys.platform.startswith("win"): - resource_path = os.path.normpath(os.path.join(os.path.dirname(sys.executable), "disks")) - for filename in os.listdir(resource_path): - if not os.path.exists(os.path.join(dst_path, filename)): - shutil.copy(os.path.join(resource_path, filename), os.path.join(dst_path, filename)) - else: - for entry in importlib_resources.files('gns3server.disks').iterdir(): - full_path = os.path.join(dst_path, entry.name) - if entry.is_file() and not os.path.exists(full_path): - log.debug(f"Installing disk file {entry.name} to {full_path}") - shutil.copy(str(entry), os.path.join(dst_path, entry.name)) + Controller.install_resource_files(dst_path, "disks") except OSError as e: log.error(f"Could not install disk files to {dst_path}: {e}") diff --git a/gns3server/controller/appliance_manager.py b/gns3server/controller/appliance_manager.py index 15c4da70..679926f1 100644 --- a/gns3server/controller/appliance_manager.py +++ b/gns3server/controller/appliance_manager.py @@ -100,17 +100,9 @@ class ApplianceManager: dst_path = self._builtin_appliances_path(delete_first=True) log.info(f"Installing built-in appliances in '{dst_path}'") + from . import Controller try: - if hasattr(sys, "frozen") and sys.platform.startswith("win"): - resource_path = os.path.normpath(os.path.join(os.path.dirname(sys.executable), "appliances")) - for filename in os.listdir(resource_path): - shutil.copy(os.path.join(resource_path, filename), os.path.join(dst_path, filename)) - else: - for entry in importlib_resources.files('gns3server.appliances').iterdir(): - full_path = os.path.join(dst_path, entry.name) - if entry.is_file(): - log.debug(f"Installing built-in appliance file {entry.name} to {full_path}") - shutil.copy(str(entry), os.path.join(dst_path, entry.name)) + Controller.instance().install_resource_files(dst_path, "appliances") except OSError as e: log.error(f"Could not install built-in appliance files to {dst_path}: {e}") diff --git a/tests/controller/test_controller.py b/tests/controller/test_controller.py index 198556a1..86e49109 100644 --- a/tests/controller/test_controller.py +++ b/tests/controller/test_controller.py @@ -395,6 +395,31 @@ async def test_install_base_configs(controller, config, tmpdir): assert f.read() == 'test' +@pytest.mark.parametrize( + "builtin_disk", + [ + "empty8G.qcow2", + "empty10G.qcow2", + "empty20G.qcow2", + "empty30G.qcow2", + "empty40G.qcow2", + "empty50G.qcow2", + "empty100G.qcow2", + "empty150G.qcow2", + "empty200G.qcow2", + "empty250G.qcow2", + "empty500G.qcow2", + "empty1T.qcow2" + ] +) +async def test_install_builtin_disks(controller, config, tmpdir, builtin_disk): + + config.set_section_config("Server", {"images_path": str(tmpdir)}) + controller._install_builtin_disks() + # we only install Qemu empty disks at this time + assert os.path.exists(str(tmpdir / "QEMU" / builtin_disk)) + + def test_appliances(controller, tmpdir): my_appliance = {