Skip to content

Commit

Permalink
Merge branch 'dev' of github.com:planctechnologies/gns3-gui into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
jseutter committed Nov 12, 2014
2 parents e89ad3e + 26b6680 commit 3b29e89
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 51 deletions.
29 changes: 22 additions & 7 deletions gns3/cloud/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ def __init__(self, parent, provider):
def run(self):
try:
instances = self._provider.list_instances()
log.debug('Instance list:')
for instance in instances:
log.debug(' name={}, state={}'.format(instance.name, instance.state))
log.debug('Instance list: {}'.format([(i.name, i.state) for i in instances]))
self.instancesReady.emit(instances)
except Exception as e:
log.info('list_instances error: {}'.format(e))
Expand Down Expand Up @@ -132,28 +130,42 @@ class StartGNS3ServerThread(QThread):
# This is for testing without pushing to github
# commands = '''
# DEBIAN_FRONTEND=noninteractive dpkg --configure -a
# DEBIAN_FRONTEND=noninteractive dpkg --add-architecture i386 # for iou
# DEBIAN_FRONTEND=noninteractive apt-get -y update
# DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confnew" --force-yes -fuy dist-upgrade
# DEBIAN_FRONTEND=noninteractive apt-get -y install git python3-setuptools python3-netifaces python3-pip python3-zmq dynamips
# DEBIAN_FRONTEND=noninteractive apt-get -y install libc6:i386 libstdc++6:i386 libssl1.0.0:i386
# ln -s /lib/i386-linux-gnu/libcrypto.so.1.0.0 /lib/i386-linux-gnu/libcrypto.so.4
# mkdir -p /opt/gns3
# tar xzf /tmp/gns3-server.tgz -C /opt/gns3
# cd /opt/gns3/gns3-server; pip3 install -r dev-requirements.txt
# cd /opt/gns3/gns3-server; python3 ./setup.py install
# ln -sf /usr/bin/dynamips /usr/local/bin/dynamips
# ln -sf /usr/bin/dynamips /usr/local/bin/dynamips # for ios
# wget 'https://github.com/GNS3/iouyap/releases/download/0.95/iouyap.tar.gz' # for iou
# python -c 'import struct; open("/etc/hostid", "w").write(struct.pack("i", 00000000))' # set hostid for iou
# hostname gns3-iouvm # set hostname for iou
# tar xzf iouyap.tar.gz -C /usr/local/bin
# killall python3 gns3server gns3dms
# '''

commands = '''
DEBIAN_FRONTEND=noninteractive dpkg --configure -a
DEBIAN_FRONTEND=noninteractive dpkg --add-architecture i386 # for iou
DEBIAN_FRONTEND=noninteractive apt-get -y update
DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confnew" --force-yes -fuy dist-upgrade
DEBIAN_FRONTEND=noninteractive apt-get -y install git python3-setuptools python3-netifaces python3-pip python3-zmq dynamips
DEBIAN_FRONTEND=noninteractive apt-get -y install libc6:i386 libstdc++6:i386 libssl1.0.0:i386
ln -s /lib/i386-linux-gnu/libcrypto.so.1.0.0 /lib/i386-linux-gnu/libcrypto.so.4
mkdir -p /opt/gns3
cd /opt/gns3; git clone https://github.com/planctechnologies/gns3-server.git
cd /opt/gns3/gns3-server; git checkout dev; git pull
cd /opt/gns3/gns3-server; pip3 install -r dev-requirements.txt
cd /opt/gns3/gns3-server; python3 ./setup.py install
ln -sf /usr/bin/dynamips /usr/local/bin/dynamips
ln -sf /usr/bin/dynamips /usr/local/bin/dynamips # for ios
wget 'https://github.com/GNS3/iouyap/releases/download/0.95/iouyap.tar.gz' # for iou
tar xzf iouyap.tar.gz -C /usr/local/bin #
python -c 'import struct; open("/etc/hostid", "w").write(struct.pack("i", 00000000))' # set hostid for iou
hostname gns3-iouvm # set hostname for iou
killall python3 gns3server gns3dms
'''

Expand Down Expand Up @@ -348,19 +360,22 @@ class UploadFileThread(QThread):

completed = pyqtSignal()

def __init__(self, cloud_settings, router_settings):
def __init__(self, cloud_settings, router_settings, upload_path):
super().__init__()
self._cloud_settings = cloud_settings
self._router_settings = router_settings
self._upload_path = upload_path

def run(self):
disk_path = self._router_settings['path']
filename = self._router_settings['image']
# Eg: images/IOS/c3745.img
upload_path = '{}/{}'.format(self._upload_path, filename)

log.debug('Uploading image {}'.format(disk_path))
log.debug('Cloud filename: {}'.format(filename))
provider = get_provider(self._cloud_settings)
provider.upload_file(disk_path, 'images/IOS/{}'.format(filename))
provider.upload_file(disk_path, upload_path)

self._cloud_settings['image'] = filename

Expand Down
3 changes: 3 additions & 0 deletions gns3/cloud_instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ def instance():
def instances(self):
return self._instances

def clear(self):
self._instances.clear()

def add(self, topology_instance):
self._instances.append(topology_instance)

Expand Down
1 change: 1 addition & 0 deletions gns3/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ def __init__(self, parent=None):
self._updateRecentFileActions()

self._cloud_provider = None
CloudInstances.instance().clear()
CloudInstances.instance().load()

# set the window icon
Expand Down
3 changes: 2 additions & 1 deletion gns3/modules/dynamips/pages/ios_router_preferences_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ def _iosRouterNewSlot(self):
self._upload_image_progress_dialog.setWindowTitle("IOS image upload")
self._upload_image_progress_dialog.show()
try:
upload_thread = UploadFileThread(MainWindow.instance().cloudSettings(), self._ios_routers[key])
upload_thread = UploadFileThread(MainWindow.instance().cloudSettings(), self._ios_routers[key],
'images/IOS')
upload_thread.completed.connect(self._imageUploadComplete)
upload_thread.start()
except Exception as e:
Expand Down
7 changes: 6 additions & 1 deletion gns3/modules/iou/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,12 @@ def setupNode(self, node, node_name):
settings["nvram"] = self._iou_devices[iouimage]["nvram"]
settings["ethernet_adapters"] = self._iou_devices[iouimage]["ethernet_adapters"]
settings["serial_adapters"] = self._iou_devices[iouimage]["serial_adapters"]
node.setup(iou_path, initial_settings=settings)

if node.server().isCloud():
settings["cloud_path"] = "images/IOU"
node.setup(self._iou_devices[iouimage]["image"], initial_settings=settings)
else:
node.setup(iou_path, initial_settings=settings)

def reset(self):
"""
Expand Down
30 changes: 16 additions & 14 deletions gns3/modules/iou/dialogs/iou_device_wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from gns3.node import Node
from gns3.servers import Servers

from ....settings import ENABLE_CLOUD
from ..ui.iou_device_wizard_ui import Ui_IOUDeviceWizard
from .. import IOU

Expand Down Expand Up @@ -69,6 +70,10 @@ def __init__(self, iou_devices, parent):
else:
self.uiIOUImageToolButton.setEnabled(False)

if not ENABLE_CLOUD:
self.uiCloudRadioButton.hide()


def _remoteServerToggledSlot(self, checked):
"""
Slot for when the remote server radio button is toggled.
Expand Down Expand Up @@ -140,12 +145,6 @@ def validateCurrentPage(self):
Validates the server.
"""

if self.currentPage() == self.uiServerWizardPage:

#FIXME: prevent users to use "cloud"
if self.uiCloudRadioButton.isChecked():
QtGui.QMessageBox.critical(self, "Cloud", "Sorry not implemented yet!")
return False
if self.currentPage() == self.uiNameImageWizardPage:
name = self.uiNameLineEdit.text()
for iou_device in self._iou_devices.values():
Expand Down Expand Up @@ -188,14 +187,17 @@ def getSettings(self):

if IOU.instance().settings()["use_local_server"] or self.uiLocalRadioButton.isChecked():
server = "local"
elif self.uiLoadBalanceCheckBox.isChecked():
server = next(iter(Servers.instance()))
if not server:
QtGui.QMessageBox.critical(self, "IOU device", "No remote server available!")
return
server = "{}:{}".format(server.host, server.port)
else:
server = self.uiRemoteServersComboBox.currentText()
elif self.uiRemoteRadioButton.isChecked():
if self.uiLoadBalanceCheckBox.isChecked():
server = next(iter(Servers.instance()))
if not server:
QtGui.QMessageBox.critical(self, "IOU device", "No remote server available!")
return
server = "{}:{}".format(server.host, server.port)
else:
server = self.uiRemoteServersComboBox.currentText()
else: # Cloud is selected
server = "cloud"

settings = {
"name": self.uiNameLineEdit.text(),
Expand Down
3 changes: 3 additions & 0 deletions gns3/modules/iou/iou_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ def setup(self, iou_path, name=None, console=None, iou_id=None, initial_settings
if console:
params["console"] = self._settings["console"] = console

if "cloud_path" in initial_settings:
params["cloud_path"] = self._settings["cloud_path"] = initial_settings.pop("cloud_path")

# other initial settings will be applied when the router has been created
if initial_settings:
self._inital_settings = initial_settings
Expand Down
28 changes: 28 additions & 0 deletions gns3/modules/iou/pages/iou_device_preferences_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from gns3.main_window import MainWindow
from gns3.dialogs.symbol_selection_dialog import SymbolSelectionDialog
from gns3.dialogs.configuration_dialog import ConfigurationDialog
from gns3.cloud.utils import UploadFileThread

from .. import IOU
from ..settings import IOU_DEVICE_SETTINGS
Expand Down Expand Up @@ -98,6 +99,33 @@ def _iouDeviceNewSlot(self):
self._items.append(item)
self.uiIOUDevicesTreeWidget.setCurrentItem(item)

if new_device_settings["server"] == 'cloud':
import logging
log = logging.getLogger(__name__)

log.debug(new_device_settings["image"])
# Start uploading the image to cloud files

self._upload_image_progress_dialog = QtGui.QProgressDialog(
"Uploading image file {}".format(new_device_settings['image']), "Cancel", 0, 0, parent=self)
self._upload_image_progress_dialog.setWindowModality(QtCore.Qt.WindowModal)
self._upload_image_progress_dialog.setWindowTitle("IOU image upload")
self._upload_image_progress_dialog.show()
try:
upload_thread = UploadFileThread(MainWindow.instance().cloudSettings(), self._iou_devices[key],
'images/IOU')
upload_thread.completed.connect(self._imageUploadComplete)
upload_thread.start()
except Exception as e:
self._upload_image_progress_dialog.reject()
log.error(e)
QtGui.QMessageBox.critical(self, "IOU image upload", "Error uploading IOU image: {}".format(e))

def _imageUploadComplete(self):
if self._upload_image_progress_dialog.wasCanceled():
return
self._upload_image_progress_dialog.accept()

def _iouDeviceEditSlot(self):
"""
Edits an IOU device.
Expand Down
122 changes: 94 additions & 28 deletions scripts/ssh_to_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,79 @@
file.
"""

import getopt
import os
import sys

from PyQt4 import QtCore, QtGui


if sys.platform.startswith('win') or sys.platform.startswith('darwin'):
QtCore.QSettings.setDefaultFormat(QtCore.QSettings.IniFormat)
SCRIPT_NAME = os.path.basename(__file__)

app = QtGui.QApplication([])
app.setOrganizationName("GNS3")
app.setOrganizationDomain("gns3.net")
app.setApplicationName("GNS3")

settings = QtCore.QSettings()
def parse_cmd_line(argv):
"""
Parse command line arguments
if not os.path.isfile(QtCore.QSettings().fileName()):
print('Config file {} not found! Aborting...'.format(QtCore.QSettings().fileName()))
sys.exit(1)
argv: Passed in sys.argv
"""


usage = """
USAGE: %s [-l] [-s <server_num>]
If no options are supplied a connection to server 1 will be opened.
Options:
-h, --help Display this menu :)
-l, --list List instances that are tracked
-s, --server-num Connect to this server number (1-indexed)
""" % (SCRIPT_NAME)

short_args = "hls:"
long_args = ("help", "list", "server-num=")
try:
opts, extra_opts = getopt.getopt(argv[1:], short_args, long_args)
except getopt.GetoptError as e:
print("Unrecognized command line option or missing required argument: %s" %(e))
print(usage)
sys.exit(2)

cmd_line_option_list = {'action': 'ssh', 'server': '1'}

for opt, val in opts:
if opt in ("-h", "--help"):
print(usage)
sys.exit(0)
elif opt in ("-l", "--list"):
cmd_line_option_list['action'] = 'list'
elif opt in ("-s", "--server-num"):
cmd_line_option_list['server'] = val

return cmd_line_option_list


def setup():
if sys.platform.startswith('win') or sys.platform.startswith('darwin'):
QtCore.QSettings.setDefaultFormat(QtCore.QSettings.IniFormat)

app = QtGui.QApplication([])
app.setOrganizationName("GNS3")
app.setOrganizationDomain("gns3.net")
app.setApplicationName("GNS3")

if not os.path.isfile(QtCore.QSettings().fileName()):
print('Config file {} not found! Aborting...'.format(QtCore.QSettings().fileName()))
sys.exit(1)

print('Config file: {}'.format(QtCore.QSettings().fileName()))

print('Reading config file {}...'.format(QtCore.QSettings().fileName()))

def read_cloud_settings():
settings = QtCore.QSettings()
settings.beginGroup("CloudInstances")

instances = []
# Load the instances
size = settings.beginReadArray("cloud_instance")
for index in range(0, size):
Expand All @@ -42,24 +89,43 @@ def read_cloud_settings():
private_key = settings.value('private_key')
public_key = settings.value('public_key')

# For now, just use the first system.
return name, host, private_key, public_key
raise Exception("Could not find any servers")

instances.append((name, host, private_key, public_key))

if len(instances) == 0:
raise Exception("Could not find any servers")

return instances


def main():
options = parse_cmd_line(sys.argv)
setup()
instances = read_cloud_settings()

if options['action'] == 'ssh':
name, host, private_key, public_key = instances[int(options['server'])-1]
print('Instance name: {}'.format(name))
print('Host ip: {}'.format(host))

public_key_path = '/tmp/id_rsa.pub'
open(public_key_path, 'w').write(public_key)
private_key_path = '/tmp/id_rsa'
open(private_key_path, 'w').write(private_key)
cmd = 'chmod 0600 {}'.format(private_key_path)
os.system(cmd)
print('Per-instance ssh keys written to {}'.format(private_key_path))

name, host, private_key, public_key = read_cloud_settings()
cmd = 'ssh -i /tmp/id_rsa root@{}'.format(host)
print(cmd)
os.system(cmd)
elif options['action'] == 'list':
print('ID Name')
for idx, info in enumerate(instances):
name, host, private_key, public_key = info
print('{:2d} {}'.format(idx+1, name))

print('Instance name: {}'.format(name))
print('Host ip: {}'.format(host))
return 0

public_key_path = '/tmp/id_rsa.pub'
open(public_key_path, 'w').write(public_key)
private_key_path = '/tmp/id_rsa'
open(private_key_path, 'w').write(private_key)
cmd = 'chmod 0600 {}'.format(private_key_path)
os.system(cmd)
print('Per-instance ssh keys written to {}'.format(private_key_path))

cmd = 'ssh -i /tmp/id_rsa root@{}'.format(host)
print(cmd)
os.system(cmd)
if __name__ == "__main__":
sys.exit(main())

0 comments on commit 3b29e89

Please sign in to comment.