gns3 deploy initial repo

This commit is contained in:
2026-05-28 06:56:46 -07:00
commit d1ca7c6692
17 changed files with 4652 additions and 0 deletions
+62
View File
@@ -0,0 +1,62 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
YT90qFF93M3v01BbxP+EIY2/9tiIPbrd
=0YYh
-----END PGP PUBLIC KEY BLOCK-----
+577
View File
@@ -0,0 +1,577 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import configparser
import locale
import os
import re
import subprocess
import sys
import time
import urllib.request
from json import loads as convert
from dialog import Dialog, PythonDialogBug
class Welcome_dialog:
def __init__(self):
try:
locale.setlocale(locale.LC_ALL, "")
except locale.Error:
# Not supported via SSH
pass
self.display = Dialog(dialog="dialog", autowidgetsize=True)
if self.gns3_version() is None:
self.display.set_background_title("GNS3")
else:
self.display.set_background_title("GNS3 {}".format(self.gns3_version()))
def get_ip(self):
"""
Return the active IP
"""
# request 'ip addr' data in JSON format from shell
ip_addr_response = subprocess.run(["ip", "--json", "addr"], capture_output=True)
# process response, decode and use json.loads to convert the string to a dict
ip_addr_data = convert(ip_addr_response.stdout.decode("utf-8"))
# search ip_addr_data for the first ip adress that is not under a virtual bridge or loopback interface
for i in ip_addr_data:
if ("virbr" in i["ifname"]) or ("lo" in i["ifname"]):
continue
try:
if "UP" in i["flags"]:
ip_addr = i["addr_info"][0]["local"]
break
except:
continue
ip_addr = None
return ip_addr
def repair_remote_install(self):
"""
This method is only called by remote-install.sh during setup to ensure it is setting the same IP as shown by Dialog
"""
ip_addr = self.get_ip()
subprocess.run(
[
"sed",
"-i",
f"s/host = 0.0.0.0/host = {ip_addr}/",
"/etc/gns3/gns3_server.conf",
],
capture_output=False,
)
subprocess.run(["service", "gns3", "stop"], capture_output=False)
subprocess.run(["service", "gns3", "start"], capture_output=False)
def get_config(self):
"""
Read the config
"""
config = configparser.RawConfigParser()
path = os.path.expanduser("~/.config/GNS3/gns3_server.conf")
config.read([path], encoding="utf-8")
return config
def write_config(self, config):
"""
Write the config file
"""
with open(os.path.expanduser("~/.config/GNS3/gns3_server.conf"), "w") as f:
config.write(f)
def gns3_major_version(self):
"""
Returns the GNS3 major server version
"""
version = self.gns3_version()
if version:
match = re.search(r"\d+.\d+", version)
return match.group(0)
return ""
def gns3_version(self):
"""
Return the GNS3 server version
"""
try:
return subprocess.check_output(["gns3server", "--version"]).strip().decode()
except (subprocess.CalledProcessError, FileNotFoundError):
return None
def gns3vm_version(self):
"""
Return the GNS3 VM version
"""
try:
with open("/home/gns3/.config/GNS3/gns3vm_version") as f:
return f.read().strip()
except FileNotFoundError:
return "Remote Install"
def mode(self):
if (
self.display.yesno(
"This feature is for testers only. You may break your GNS3 installation. Are you REALLY sure you want to continue?",
yes_label="Exit (Safe option)",
no_label="Continue",
)
== self.display.OK
):
return
code, tag = self.display.menu(
"Select the GNS3 version",
choices=[
("2.1", "Stable release for this GNS3 VM (RECOMMENDED)"),
("2.1dev", "Development version for stable release"),
("2.2", "Latest stable release"),
],
)
self.display.clear()
if code == Dialog.OK:
os.makedirs(os.path.expanduser("~/.config/GNS3"), exist_ok=True)
with open(os.path.expanduser("~/.config/GNS3/gns3_release"), "w+") as f:
f.write(tag)
self.update(force=True)
def get_release(self):
try:
with open(os.path.expanduser("~/.config/GNS3/gns3_release")) as f:
content = f.read()
# Support old VM versions
if content == "stable":
content = "1.5"
elif content == "testing":
content = "1.5"
elif content == "unstable":
content = "1.5dev"
return content
except OSError:
return "1.5"
def update(self, force=False):
if not force:
if (
self.display.yesno(
"It is recommended to ensure all Nodes are shutdown before upgrading. Continue?"
)
!= self.display.OK
):
return
code, option = self.display.menu(
"Select an option",
choices=[
("Upgrade GNS3", "Upgrades only the GNS3 pakage and dependences."),
("Upgrade All", "Upgrades all avaiable packages"),
(
"Dist Upgrade",
"Upgrades all avaiable packages and the Linux Kernel. Requires a reboot.",
),
],
)
if code == Dialog.OK:
if option == "Upgrade GNS3":
ret = os.system(
"sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A2E3EF7B \
&& sudo apt-get update \
&& sudo apt-get install -y --only-upgrade gns3-server"
)
elif option == "Upgrade All":
ret = os.system(
'sudo apt-key adv --refresh-keys --keyserver keyserver.ubuntu.com \
&& sudo apt-get update \
&& sudo apt-get upgrade --yes --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"'
)
elif option == "Dist Upgrade":
ret = os.system(
'sudo apt-key adv --refresh-keys --keyserver keyserver.ubuntu.com \
&& sudo apt-get update \
&& sudo apt-get dist-upgrade --yes --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"'
)
if ret != 0:
print(
"ERROR DURING UPGRADE PROCESS PLEASE TAKE A SCREENSHOT IF YOU NEED SUPPORT"
)
time.sleep(15)
return
if option == "Dist Upgrade":
if self.display.yesno("Reboot now?") == self.display.OK:
os.system("sudo reboot now")
def migrate(self):
"""
Migrate GNS3 VM data.
"""
code, option = self.display.menu(
"Select an option",
choices=[
("Setup", "Configure this VM to send data to another GNS3 VM"),
("Send", "Send images and projects to another GNS3 VM"),
],
)
self.display.clear()
if code == Dialog.OK:
(answer, destination) = self.display.inputbox(
"What is IP address or hostname of the other GNS3 VM?",
init="172.16.1.128",
)
if answer != self.display.OK:
return
if destination == self.get_ip():
self.display.msgbox(
"The destination cannot be the same as this VM IP address ({})".format(
destination
)
)
return
if option == "Send":
# first make sure they are no files belonging to root
os.system("sudo chown -R gns3:gns3 /opt/gns3")
# then rsync the data
command = r"rsync -az --progress -e 'ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /home/gns3/.ssh/gns3-vm-key' /opt/gns3 gns3@{}:/opt".format(
destination
)
ret = os.system('bash -c "{}"'.format(command))
time.sleep(10)
if ret != 0:
self.display.msgbox(
"Could not send data to the other GNS3 VM located at {}".format(
destination
)
)
else:
self.display.msgbox(
"Images and projects have been successfully sent to the other GNS3 VM located at {}".format(
destination
)
)
elif option == "Setup":
script = """
if [ ! -f ~/.ssh/gns3-vm-key ]
then
ssh-keygen -f ~/.ssh/gns3-vm-key -N '' -C gns3@{}
fi
ssh-copy-id -i ~/.ssh/gns3-vm-key gns3@{}
""".format(self.get_ip(), destination)
ret = os.system('bash -c "{}"'.format(script))
time.sleep(10)
if ret != 0:
self.display.msgbox("Error while setting up the migrate feature")
else:
self.display.msgbox(
"Configuration successful, you can now send data to the GNS3 VM located at {} without password".format(
destination
)
)
def shrink_disk(self):
ret = os.system("lspci | grep -i vmware")
if ret != 0:
self.display.msgbox(
"Shrinking the disk is only supported when running inside VMware"
)
return
if (
self.display.yesno(
"Would you like to shrink the VM disk? The VM will reboot at the end of the process. Continue?"
)
!= self.display.OK
):
return
os.system("sudo service gns3 stop")
os.system("sudo service docker stop")
os.system("sudo vmware-toolbox-cmd disk shrink /opt")
os.system("sudo vmware-toolbox-cmd disk shrink /")
self.display.msgbox("The GNS3 VM will reboot")
os.execvp("sudo", ["/usr/bin/sudo", "reboot"])
def vm_information(self):
"""
Show IP, SSH settings....
"""
content = "Welcome to GNS3 appliance\n\n"
version = self.gns3_version()
if version is None:
content += "GNS3 is not installed please install it with sudo pip3 install gns3-server. Or download a preinstalled VM.\n\n"
else:
content = "GNS3 version: {gns3_version}\nVM version: {gns3vm_version}\nKVM support available: {kvm}\n\n".format(
gns3vm_version=self.gns3vm_version(),
gns3_version=version,
kvm=self.kvm_support(),
)
ip = self.get_ip()
if ip:
content += f"""
IP: {ip}
Web UI: http://{ip}:3080
To log in using SSH:
ssh gns3@{ip}
Password: gns3
Images and projects are located in /opt/gns3
""".strip()
else:
content += "eth0 is not configured. Please manually configure it via the Networking menu."
content += "\n\nRelease channel: " + self.get_release()
try:
self.display.msgbox(content)
# If it's an scp command or any bugs
except:
os.execvp("bash", ["/bin/bash"])
def check_internet_connectivity(self):
self.display.pause("Please wait...\n\n")
try:
response = urllib.request.urlopen("http://pypi.python.org/", timeout=5)
except urllib.request.URLError as err:
self.display.infobox(
"Can't connect to Internet (pypi.python.org): {}".format(str(err))
)
time.sleep(15)
return
self.display.infobox("Connection to Internet: OK")
time.sleep(2)
def keyboard_configuration():
"""
Allow user to change the keyboard layout
"""
os.system("/usr/bin/sudo dpkg-reconfigure keyboard-configuration")
def set_security(self):
config = self.get_config()
if self.display.yesno("Enable server authentication?") == self.display.OK:
if not config.has_section("Server"):
config.add_section("Server")
config.set("Server", "auth", True)
(answer, text) = self.display.inputbox("Login?")
if answer != self.display.OK:
return
config.set("Server", "user", text)
(answer, text) = self.display.passwordbox("Password?")
if answer != self.display.OK:
return
config.set("Server", "password", text)
else:
config.set("Server", "auth", False)
self.write_config(config)
def log(self):
os.system("/usr/bin/sudo chmod 755 /var/log/upstart/gns3.log")
with open("/var/log/upstart/gns3.log") as f:
try:
while True:
line = f.readline()
sys.stdout.write(line)
except (KeyboardInterrupt, MemoryError):
return
def edit_config(self):
"""
Edit GNS3 configuration file
"""
major_version = self.gns3_major_version()
if major_version == "2.2":
os.system("nano ~/.config/GNS3/{}/gns3_server.conf".format(major_version))
else:
os.system("nano ~/.config/GNS3/gns3_server.conf")
def edit_network(self):
"""
Edit network configuration file
"""
if (
self.display.yesno(
"The server will reboot at the end of the process. Continue?"
)
!= self.display.OK
):
return
os.system("sudo nano /etc/network/interfaces")
os.execvp("sudo", ["/usr/bin/sudo", "reboot"])
def edit_proxy(self):
"""
Configure proxy settings
"""
res, http_proxy = self.display.inputbox(
text="HTTP proxy string, for example http://<user>:<password>@<proxy>:<port>. Leave empty for no proxy."
)
if res != self.display.OK:
return
res, https_proxy = self.display.inputbox(
text="HTTPS proxy string, for example http://<user>:<password>@<proxy>:<port>. Leave empty for no proxy."
)
if res != self.display.OK:
return
with open("/tmp/00proxy", "w+") as f:
f.write('Acquire::http::Proxy "' + http_proxy + '";')
os.system("sudo mv /tmp/00proxy /etc/apt/apt.conf.d/00proxy")
os.system("sudo chown root /etc/apt/apt.conf.d/00proxy")
os.system("sudo chmod 744 /etc/apt/apt.conf.d/00proxy")
with open("/tmp/proxy.sh", "w+") as f:
f.write('export http_proxy="' + http_proxy + '"\n')
f.write('export https_proxy="' + https_proxy + '"\n')
f.write('export HTTP_PROXY="' + http_proxy + '"\n')
f.write('export HTTPS_PROXY="' + https_proxy + '"\n')
os.system("sudo mv /tmp/proxy.sh /etc/profile.d/proxy.sh")
os.system("sudo chown root /etc/profile.d/proxy.sh")
os.system("sudo chmod 744 /etc/profile.d/proxy.sh")
os.system("sudo cp /etc/profile.d/proxy.sh /etc/default/docker")
self.display.msgbox("The GNS3 VM will reboot")
os.execvp("sudo", ["/usr/bin/sudo", "reboot"])
def kvm_support(self):
"""
Returns true if KVM is available
"""
return subprocess.call("kvm-ok") == 0
def kvm_control(self):
"""
Check if KVM is correctly configured
"""
kvm_ok = self.kvm_support()
config = self.get_config()
try:
if config.getboolean("Qemu", "enable_kvm") is True:
if kvm_ok is False:
if (
self.display.yesno(
"KVM is not available!\n\nQemu VM will crash!!\n\nThe reason could be unsupported hardware or another virtualization solution is already running.\n\nDisable KVM and get lower performances?"
)
== self.display.OK
):
config.set("Qemu", "enable_kvm", False)
self.write_config(config)
os.execvp("sudo", ["/usr/bin/sudo", "reboot"])
else:
if kvm_ok is True:
if (
self.display.yesno(
"KVM is available on your computer.\n\nEnable KVM and get better performances?"
)
== self.display.OK
):
config.set("Qemu", "enable_kvm", True)
self.write_config(config)
os.execvp("sudo", ["/usr/bin/sudo", "reboot"])
except configparser.NoSectionError:
return
def display_loop(self):
try:
while True:
code, tag = self.display.menu(
"GNS3 {}".format(self.gns3_version()),
choices=[
("Information", "Display VM information"),
("Upgrade", "Upgrade GNS3"),
("Migrate", "Migrate data to another GNS3 VM"),
("Shell", "Open a console"),
("Security", "Configure authentication"),
("Keyboard", "Change keyboard layout"),
(
"Configure",
"Edit server configuration (advanced users ONLY)",
),
("Proxy", "Configure proxy settings"),
("Networking", "Configure networking settings"),
("Log", "Show server log"),
("Test", "Check internet connection"),
("Shrink", "Shrink the VM disk"),
("Version", "Select the GNS3 version"),
("Restore", "Restore the VM (if you have trouble for upgrade)"),
("Reboot", "Reboot the VM"),
("Shutdown", "Shutdown the VM"),
],
)
self.display.clear()
if code == Dialog.OK:
if tag == "Shell":
print("Type: 'welcome.py' to get back to the dialog menu.")
sys.exit(0)
elif tag == "Version":
self.mode()
elif tag == "Restore":
os.execvp(
"sudo", ["/usr/bin/sudo", "/usr/local/bin/gns3restore"]
)
elif tag == "Reboot":
os.execvp("sudo", ["/usr/bin/sudo", "reboot"])
elif tag == "Shutdown":
os.execvp("sudo", ["/usr/bin/sudo", "poweroff"])
elif tag == "Upgrade":
self.update()
elif tag == "Information":
self.vm_information()
elif tag == "Log":
self.log()
elif tag == "Migrate":
self.migrate()
elif tag == "Configure":
self.edit_config()
elif tag == "Networking":
self.edit_network()
elif tag == "Security":
self.set_security()
elif tag == "Keyboard":
self.keyboard_configuration()
elif tag == "Test":
self.check_internet_connectivity()
elif tag == "Proxy":
self.edit_proxy()
elif tag == "Shrink":
self.shrink_disk()
except KeyboardInterrupt:
sys.exit(0)
if __name__ == "__main__":
ws = Welcome_dialog()
ws.vm_information()
ws.kvm_control()
ws.display_loop()