diff --git a/.gitignore b/.gitignore index bee8a64..8d35cb3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ __pycache__ +*.pyc diff --git a/README.rst b/README.rst index 0bdd5b3..5c79d3a 100644 --- a/README.rst +++ b/README.rst @@ -10,3 +10,21 @@ Add an image ************ python3.4 gns3repository/main.py --add ~/Downloads/linux-microcore-3.4.1.img + +Search an image +**************** + +python3.4 gns3repository/main.py --search core + +Micro Core Linux: + * 3.4.1 linux-microcore-3.4.1.img: 5f42d71b30bc682e44ccf7340e20ea7ea8967ef5 + * 4.0.2 linux-microcore-4.0.2-clean.img: 0252f2c913519c993b812325bbd553af2d77218a + + +Install a remote image +************************** + +If the image is available from the internet you can download it: + +python3.4 gns3repository/main.py --install 0252f2c913519c993b812325bbd553af2d77218a +Download http://downloads.sourceforge.net/project/gns-3/Qemu%20Appliances/linux-microcore-4.0.2-clean.img to /Users/noplay/GNS3/images/linux-microcore-4.0.2-clean.img diff --git a/gns3repository/config.py b/gns3repository/config.py index ebb301e..b81f802 100644 --- a/gns3repository/config.py +++ b/gns3repository/config.py @@ -41,6 +41,13 @@ class Config: with open(self.path) as f: self._config = json.load(f) + @property + def images_dir(self): + """ + :returns: Localion of the images directory on the server + """ + return self._config["LocalServer"]["images_path"] + def _get_standard_config_file_path(self): if sys.platform.startswith("win"): filename = "gns3_gui.ini" @@ -111,5 +118,5 @@ class Config: Save the configuration file """ with open(self.path, "w+") as f: - json.dump(self._config, f) + json.dump(self._config, f, indent=4) diff --git a/gns3repository/main.py b/gns3repository/main.py index 5e5c9ab..65e82a7 100644 --- a/gns3repository/main.py +++ b/gns3repository/main.py @@ -26,6 +26,10 @@ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) from gns3repository.repository import Repository from gns3repository.config import Config +repository = Repository() +config = Config() + + def yes_no(message): while True: try: @@ -33,27 +37,42 @@ def yes_no(message): except ValueError: pass +def add_image(image): + confs = repository.detect_image(image) + if len(confs) > 0: + print("Found: {} devices configuration".format(len(confs))) + for conf in confs: + if yes_no("Add {}?".format(conf["name"])): + config.add_image(conf) + config.save() + + if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Manage GNS3 repository') - parser.add_argument('--add', dest='add_image', action='store', - help='Add an image to GNS') + parser = argparse.ArgumentParser(description="Manage GNS3 repository") + parser.add_argument("--add", dest="add_image", action="store", + help="Add an image to GNS3") + parser.add_argument("--search", dest="search", action="store", + help="Search an image for GNS3") + parser.add_argument("--install", dest="install", action="store", + help="Download and install an image for GNS3") args = parser.parse_args() print("WARNING WARNING WARNING") print("It's experimental") print("Please close the GUI before using it") - repository = Repository() - config = Config() + print("") if args.add_image: - confs = repository.detect_image(args.add_image) - if len(confs) > 0: - print("Found: {} devices configuration".format(len(confs))) - for conf in confs: - if yes_no("Add {}?".format(conf["name"])): - config.add_image(conf) - config.save() + add_image(args.add_image) + elif args.search: + for res in repository.search_device(args.search): + print("{}: ".format(res["name"])) + for file in res["hda_disk_image"]: + print(" * {} {}: {}".format(file["version"], file["filename"], file["sha1sum"])) + elif args.install: + image = repository.download_image(args.install, config.images_dir) + add_image(image) else: parser.print_help() sys.exit(1) diff --git a/gns3repository/repository.py b/gns3repository/repository.py index 6873aad..f2d320d 100644 --- a/gns3repository/repository.py +++ b/gns3repository/repository.py @@ -20,6 +20,8 @@ import hashlib import json import os +import re +import urllib.request from gns3repository.image import Image @@ -36,16 +38,44 @@ class Repository: configurations = [] #TODO: Manage open error + for config in self._all_configs(): + if self._image_match(image, config): + configurations.append(config) + + return configurations + + + def download_image(self, sha1sum, images_dir): + for config in self._all_configs(): + for file in config.get("hda_disk_image", []): + if file["sha1sum"] == sha1sum: + path = os.path.join(images_dir, file["filename"]) + + print("Download {} to {}".format(file["direct_download_url"], path)) + #TODO: Skip download if file already exist with same sha1 + urllib.request.urlretrieve(file["direct_download_url"], path) + return path + + def search_device(self, query): + results = [] + for config in self._all_configs(): + if re.match(r".*{}.*".format(query), config["name"], flags=re.IGNORECASE): + results.append(config) + return results + + def _all_configs(self): + """ + Iterate on all configs available on devices + """ devices_path = self._get_devices_path() for (dirpath, dirnames, filenames) in os.walk(devices_path): for filename in filenames: file = os.path.join(dirpath, filename) - with open(os.path.join(devices_path, file)) as f: - config = json.load(f) - if self._image_match(image, config): - configurations.append(config) - - return configurations + if file.endswith(".json"): + with open(os.path.join(devices_path, file)) as f: + config = json.load(f) + config["filename"] = file[:-5] + yield config def _image_match(self, image, config): """ diff --git a/test/test_repository.py b/test/test_repository.py index 19e7ce9..3e88f7e 100644 --- a/test/test_repository.py +++ b/test/test_repository.py @@ -37,3 +37,9 @@ def test_detect_image(linux_microcore_img): def test_detect_unknow_image(empty_file): repository = Repository() assert repository.detect_image(empty_file) == [] + + +def test_search_device(): + repository = Repository() + results = repository.search_device("Micro Core Linux") + assert len(results) == 1