Compare commits

...

5238 Commits

Author SHA1 Message Date
grossmj
812aedebe3 Release v2.2.47 2024-05-15 12:14:48 +07:00
grossmj
2f0d2063cf Remove maximum size for capture dialog. Ref #3576 2024-05-10 12:58:35 +07:00
Jeremy Grossmann
ce0515f0ae Merge pull request #3582 from GNS3/drop-python3.7
Drop Python 3.7
2024-05-09 19:09:14 +07:00
grossmj
bc10c69a2d Change sentry-sdk version 2024-05-09 19:03:08 +07:00
grossmj
3707758388 Upgrade aiohttp, sentry-sdk and truststore 2024-05-09 18:58:38 +07:00
grossmj
8aaefac91b Upgrade jsonschema and aiohttp 2024-05-09 18:37:41 +07:00
grossmj
19157ab49d Drop Python 3.7 2024-05-09 18:23:59 +07:00
grossmj
38b98cd883 Remove dev requirements for Python 3.6 2024-05-09 18:05:08 +07:00
Jeremy Grossmann
e9419924c5 Merge pull request #3580 from GNS3/feature/nat-symbols
NAT symbols
2024-04-22 19:00:15 +07:00
grossmj
cf3c5c09fa Add NAT symbols 2024-04-22 18:51:29 +07:00
grossmj
9e89cf5ad5 Only show log message if event has "message" 2024-03-07 17:18:30 +01:00
grossmj
131ef09b55 Development on 2.2.47.dev1 2024-03-05 01:07:17 +08:00
grossmj
2df18ee04e Upgrade sentry-sdk to version 1.40.6 2024-03-05 00:45:26 +08:00
grossmj
31711a9d4e Release v2.2.46 2024-02-26 16:55:13 +08:00
grossmj
fd2e236927 Add GNS3 console command "env" to show what environment variables are used. Ref https://github.com/GNS3/gns3-server/issues/2306 2024-02-14 19:29:07 +08:00
grossmj
21409a899d Add CTRL+C shortcut to copy status bar message. Ref #3561 2024-02-14 17:33:15 +08:00
grossmj
25be9e7ec7 Key modifier (ALT) to ignore snap to grid. Fixes #3538 2024-02-12 17:32:22 +11:00
grossmj
1260c2bc2d Increase timeout to 5s for status bar messages.
The coordinates message has no timeout and can be reset when clicking on the scene. Ref #3561
2024-02-12 16:32:17 +11:00
grossmj
1441e38876 Add reset GUI state feature. Ref #3549 2024-02-12 16:16:07 +11:00
grossmj
3c8cff20b7 Possible fix for hiding Windows terminal. Ref #3290 2024-02-12 15:05:49 +11:00
Jeremy Grossmann
f831d71c3f Merge pull request #3566 from GNS3/feature/drop-python-3.6
Drop support for Python 3.6
2024-02-09 17:02:27 +11:00
grossmj
f71b6dcda1 Change runtime checks for Python version 2024-02-09 16:49:59 +11:00
grossmj
62289e7be3 Drop support for Python 3.6 2024-02-09 16:28:23 +11:00
grossmj
7447e9b7d4 Merge branch 'master' into 2.2 2024-01-27 17:04:54 +11:00
grossmj
c5961f400e Upgrade sentry-sdk, psutil and distro dependencies 2024-01-27 17:04:02 +11:00
grossmj
6ca61905b2 Development on 2.2.46.dev1 2024-01-14 23:45:35 +11:00
Jeremy Grossmann
130e91da76 Merge pull request #3559 from GNS3/2.2
Release v2.2.45
2024-01-14 22:02:24 +11:00
grossmj
bbc5b3e4ac Release v2.2.45 2024-01-12 21:38:26 +11:00
grossmj
2a72ad5e0b Add missing console_type values in appliance_v8.json. Ref https://github.com/GNS3/gns3-registry/issues/849 2024-01-12 16:39:06 +11:00
grossmj
88ed9407b9 Move PATH debug message 2024-01-12 15:46:20 +11:00
grossmj
18be274fed Handle moved project notifications on controller stream 2024-01-12 13:22:48 +11:00
grossmj
fefda50378 Add debug for PATH env variable 2024-01-11 22:57:14 +11:00
grossmj
3df374e784 Add custom executable paths on Windows 2023-12-05 21:24:41 +10:00
grossmj
04fb449b44 Add --suppressApplicationTitle for Windows terminal. Fixes https://github.com/GNS3/gns3-gui/issues/3544 2023-11-28 11:23:20 +10:00
grossmj
fc54b76ee1 Upgrade sentry-sdk and aiohttp 2023-11-22 10:32:51 +10:00
grossmj
59b284e18b Development in 2.2.45.dev3 2023-11-07 19:11:57 +10:00
Jeremy Grossmann
1d4492c911 Merge pull request #3537 from GNS3/release-v2.2.44.1
Release v2.2.44.1
2023-11-07 18:34:54 +10:00
grossmj
9d8b6a172e Release v2.2.44.1 2023-11-07 14:59:28 +10:00
grossmj
8c3ef7a968 Bump version to v2.2.45.dev2 2023-11-07 12:21:39 +10:00
Jeremy Grossmann
947733aada Merge pull request #3536 from GNS3/release-v2.2.44
Release v2.2.44
2023-11-06 17:01:17 +10:00
grossmj
a199fef03b Development on 2.2.45.dev1 2023-11-06 17:00:17 +10:00
grossmj
29b851207b Release v2.2.44 2023-11-06 16:02:23 +10:00
grossmj
ca5557e579 Upgrade sentry-sdk 2023-11-06 15:44:30 +10:00
grossmj
7331ae29ef Fix timeout issue when creating Qemu disk image. Fixes https://github.com/GNS3/gns3-server/issues/2313 2023-11-05 15:41:46 +10:00
grossmj
3a7e06e14b Revert to subprocess.Popen since subprocess.call is the old API 2023-11-03 14:43:25 +10:00
grossmj
0a81af8248 Merge remote-tracking branch 'origin/2.2' into 2.2 2023-10-31 15:53:13 +10:00
grossmj
a882956ec9 Merge branch 'master' into 2.2 2023-10-31 15:52:45 +10:00
Jeremy Grossmann
9f4361d66f Merge pull request #3534 from GNS3/command-variables
Refactor command variables
2023-10-31 15:44:23 +10:00
grossmj
d10c3c7308 Fix tests 2023-10-31 15:40:50 +10:00
Jeremy Grossmann
0cd7d7e4c2 Merge branch '2.2' into command-variables 2023-10-31 15:07:49 +10:00
grossmj
8f3f72ff54 Fix tests 2023-10-31 15:07:35 +10:00
Jeremy Grossmann
7fbc0befa1 Merge branch '2.2' into command-variables 2023-10-31 14:51:53 +10:00
grossmj
9d9668442e Use Python 3.8 in appveyor.yml 2023-10-31 14:48:08 +10:00
grossmj
932083be88 Update custom command help and protect against double quote in project name 2023-10-31 14:43:50 +10:00
grossmj
82e7c151c4 Refactor command variables support 2023-10-31 12:33:52 +10:00
Jeremy Grossmann
7e5c363bc3 Merge pull request #3533 from GNS3/fix/2306
Allow local server to get $PATH environment variable
2023-10-30 14:06:17 +10:00
grossmj
15d029a7fb Pass os.environ in Popen() 2023-10-30 14:03:10 +10:00
Jeremy Grossmann
9087ba8f5a Merge pull request #3512 from magister990/style_edit_width_and_height
Add the ability to edit width and hight in the style edit dialog.
2023-10-24 18:25:58 +10:00
grossmj
3d89d6e6cc Fix issue with line item 2023-10-24 18:01:49 +10:00
grossmj
91bae81300 Merge branch '2.2' into style_edit_width_and_height 2023-10-24 17:40:35 +10:00
Jeremy Grossmann
7de5bf6bd5 Merge pull request #3516 from ventaquil/feature/add-qemu-igb-nic
Add Qemu IGB network device
2023-10-24 17:15:21 +10:00
Jeremy Grossmann
9de238619a Merge branch '2.2' into feature/add-qemu-igb-nic 2023-10-24 17:14:30 +10:00
grossmj
ed88466d63 Upgrade to actions/checkout@v3 and actions/setup-python@v3 2023-10-23 16:17:31 +10:00
grossmj
478b793b04 Merge branch 'master' into 2.2 2023-10-18 17:46:45 +10:00
grossmj
841c29e6f6 Upgrade sentry and psutil dependencies 2023-10-18 14:53:25 +10:00
grossmj
f9d96051f5 Downgrade to PyQt5 v5.15.9 2023-10-18 14:33:27 +10:00
grossmj
607e201674 Fix packaging issue on macOS 2023-10-18 14:29:53 +10:00
grossmj
18950ca64f Upgrade to PyQt5 v5.15.10 2023-10-18 13:24:45 +10:00
grossmj
c0b5f39c4c Add Python 3.12 support. Fixes https://github.com/GNS3/gns3-server/issues/2273 2023-10-09 16:54:47 +10:00
grossmj
3e717999ca Add vendor_logo_url in appliance schemas. Ref https://github.com/GNS3/gns3-registry/pull/825 2023-10-09 16:52:52 +10:00
Konrad Goławski
800d14363d Add Qemu IGB network device 2023-10-02 14:35:09 +02:00
Alex Scott
2dd9d61c57 Add the ability to edit width and hight in the style edit dialog. 2023-09-27 17:08:33 -05:00
grossmj
10afb5a8de Revert "Revert "Install importlib-resources only with Python < '3.9'. Ref #2147""
This reverts commit 3413afe952.
2023-09-23 20:50:39 +10:00
grossmj
3413afe952 Revert "Install importlib-resources only with Python < '3.9'. Ref #2147"
This reverts commit 7222da9512.
2023-09-23 14:47:56 +10:00
grossmj
7222da9512 Install importlib-resources only with Python < '3.9'. Ref #2147 2023-09-23 14:33:15 +10:00
grossmj
dbe8df5a37 Development on 2.2.44.dev1 2023-09-19 21:08:24 +07:00
Jeremy Grossmann
a9890265b9 Merge pull request #3509 from GNS3/release-v2.2.43
Release v2.2.43
2023-09-19 21:04:43 +07:00
grossmj
97b777ceea Release v2.2.43 2023-09-19 20:16:52 +07:00
grossmj
c06e534935 Merge branch 'master' into 2.2 2023-09-19 20:08:11 +07:00
grossmj
025276f8a7 Upgrade sentry-sdk and truststore 2023-09-19 20:07:57 +07:00
grossmj
6777961d29 Add KiTTY to preconfigured telnet consoles. Fixes #3507 2023-09-18 20:23:09 +07:00
grossmj
7f6cace0d5 Fix generic icon in Wayland. Ref #3501 2023-09-15 16:08:45 +07:00
Jeremy Grossmann
1a739c0c37 Merge pull request #3490 from GNS3/appliance-v8-support
Support for appliance version 8 format
2023-08-16 14:18:59 +10:00
grossmj
6d855045ef Show installation instructions when available and fix regression when installing Docker appliance. 2023-08-16 14:11:55 +10:00
grossmj
fef734bbbe Finalize appliance v8 support and add tests. 2023-08-16 00:30:02 +10:00
grossmj
b079443735 Merge remote-tracking branch 'origin/appliance-v8-support' into appliance-v8-support 2023-08-14 12:01:18 +10:00
grossmj
4a32ae9736 Drop "kvm" field. 2023-08-14 12:01:09 +10:00
Jeremy Grossmann
9793d00131 Merge branch '2.2' into appliance-v8-support 2023-08-13 12:21:18 +10:00
grossmj
2b7840279a Downgrade jsonschema 2023-08-12 17:51:24 +10:00
grossmj
9243083321 Upgrade dependencies 2023-08-12 17:47:48 +10:00
Jeremy Grossmann
3a8b3e5c4a Merge pull request #3506 from GNS3/fix/3505
Use importlib instead of pkg_resources
2023-08-12 17:26:51 +10:00
grossmj
e2168a3c81 Use importlib instead of pkg_resources 2023-08-12 17:20:33 +10:00
grossmj
01deb01e6a Upgrade to PyQt 5.15.9 and pywin32 2023-08-11 18:13:41 +10:00
grossmj
1133ee6e1b Development on v2.2.43.dev1 2023-08-09 22:15:15 +10:00
Jeremy Grossmann
7512ffec64 Merge pull request #3503 from GNS3/release-v2.2.42
Release v2.2.42
2023-08-09 22:08:18 +10:00
grossmj
3527e5551c Release v2.2.42 2023-08-09 21:11:57 +10:00
grossmj
72960f8f2b Enable system certificate store later in the code and bump version to 2.2.42.dev4 2023-08-08 17:22:27 +10:00
grossmj
8abb502c72 Use the system's certificate store for SSL connections 2023-08-07 21:33:25 +10:00
grossmj
08c729e83a Upgrade dependencies 2023-08-06 20:39:27 +10:00
grossmj
aac004bd2f Use certifi to get SSL root certificates 2023-08-06 20:37:10 +10:00
grossmj
70677d8f18 Bump version to 2.2.42.dev3 2023-08-06 18:14:22 +10:00
Jeremy Grossmann
fba1ff4208 Merge pull request #3502 from GNS3/use-bundled-cacert
Use bundled cacert file for frozen app
2023-08-05 22:37:08 +10:00
grossmj
e4edbefc23 Use bundled cacert file on Windows and macOS 2023-08-05 22:21:08 +10:00
grossmj
d93f9afe74 Bump version to 2.2.42.dev2 2023-08-05 20:16:30 +10:00
grossmj
162d197e36 Give a node some time to start before opening the console (for console auto start). Fixes #3474 2023-08-02 11:08:58 +10:00
grossmj
5c21dd8a2f Merge branch 'master' into 2.2 2023-08-01 15:50:51 +10:00
Jeremy Grossmann
aa9b9d3b0b Merge pull request #3364 from AbdelbakiBoukerche/feature_rounded_rectangle
Rounded Rectangle
2023-08-01 15:46:32 +10:00
grossmj
eae9eec15b Support for horizontal and vertical corner radius 2023-08-01 15:34:30 +10:00
Jeremy Grossmann
a3bf832721 Merge branch 'master' into feature_rounded_rectangle 2023-07-31 18:34:50 +10:00
Jeremy Grossmann
67890d74d9 Merge pull request #3500 from GNS3/fix/3449
Support for gnome-terminal tabs to be opened in the same window
2023-07-31 18:30:22 +10:00
grossmj
ab4325f951 Remove warning to set open new terminals in tabs for gnome-terminal 2023-07-31 12:32:49 +10:00
grossmj
2a947b9cc5 Add comments for gnome-terminal special case 2023-07-31 01:44:39 +10:00
grossmj
601c082288 Use Mate Terminal by default if installed on Debian, Ubuntu and Linux Mint. 2023-07-31 01:40:20 +10:00
grossmj
7701d57bd0 Check that gnome-terminal is configured to open new terminals in tabs. 2023-07-31 01:34:59 +10:00
grossmj
f0b4148a20 Support for gnome-terminal tabs to be opened in the same window. 2023-07-30 22:15:38 +10:00
grossmj
2fdcbafbc1 Revert "Support for Python 3.12"
This reverts commit 5d82cea935.
2023-07-30 17:50:21 +10:00
grossmj
5d82cea935 Support for Python 3.12 2023-07-30 17:48:30 +10:00
grossmj
b0e3e93c41 Remove import urllib3 and let sentry_sdk import and patch it. Fixes https://github.com/GNS3/gns3-gui/issues/3498 2023-07-30 17:42:52 +10:00
grossmj
535f53737d Merge remote-tracking branch 'origin/master' into 2.2 2023-07-23 12:35:21 +10:00
Jeremy Grossmann
354f3eecec Merge pull request #3497 from kevinchevreuil/master
Add import sys in sudo.py
2023-07-23 12:04:29 +10:00
Kevin Chevreuil - Kaisen
35a6a5c8c7 Add import sys in sudo.py 2023-07-22 23:12:34 +02:00
grossmj
23cba0a28d Development on 2.2.42.dev1 2023-07-12 18:26:26 +10:00
Jeremy Grossmann
9c3d7bc95a Merge pull request #3495 from GNS3/release-v2.2.41
Release v2.2.41
2023-07-12 18:24:05 +10:00
grossmj
cf2802b15a Release v2.2.41 2023-07-12 17:07:39 +10:00
grossmj
b162c55078 Merge remote-tracking branch 'origin/master' into 2.2 2023-07-12 17:03:50 +10:00
grossmj
bb42b0ed0b Change chown in authorize_ubridge.py 2023-07-12 13:28:24 +10:00
grossmj
e108b5194d Bump version to 2.2.41.dev3 2023-07-12 13:26:22 +10:00
grossmj
e9ef8735be Use a small executable to set the correct permissions on uBridge on macOS 2023-07-12 12:40:53 +10:00
grossmj
e8e90bb16a Add debugging for AuthorizationExecuteWithPrivileges 2023-07-11 21:23:15 +10:00
grossmj
49f77930f4 Use alternative method to setuid uBridge on macOS 2023-07-11 18:27:19 +10:00
grossmj
a58451a552 Update to support template_type & template_properties 2023-07-11 17:38:00 +10:00
grossmj
0a43b9e6e9 Fix tests 2023-07-09 20:18:22 +10:00
Jeremy Grossmann
4f32619ed8 Merge pull request #3493 from GNS3/remove-analytics
Remove sending usage stats
2023-07-09 19:04:40 +10:00
grossmj
20740748c1 Remove sending stats to GA 2023-07-09 18:55:31 +10:00
grossmj
8a5ab6b374 Update schema for appliance version 8 2023-07-09 14:10:15 +10:00
grossmj
e11ce27f7b Catch urllib3 exceptions when sending crash report. Ref https://github.com/GNS3/gns3-gui/issues/3483 2023-07-06 17:16:05 +10:00
grossmj
4b7cf4e553 Support legacy "idlepc" field 2023-07-03 19:12:44 +10:00
grossmj
b72358461c Add support for appliance version 8 format 2023-06-25 16:54:12 +09:30
Jeremy Grossmann
2987bcf91a Merge pull request #3489 from GNS3/backport-uefi-boot-mode
Backport UEFI boot mode support for Qemu VMs
2023-06-23 11:31:49 +09:30
grossmj
5e97bc0f86 Backport UEFI boot mode support for Qemu VMs 2023-06-23 11:18:25 +09:30
grossmj
e3a3de5df7 Add debug for dropEvent. Ref https://github.com/GNS3/gns3-server/issues/2242 2023-06-20 14:49:25 +09:30
grossmj
e1693ce113 Developement on v2.2.41.dev2 2023-06-10 21:40:39 +09:30
Jeremy Grossmann
522091d219 Merge pull request #3481 from GNS3/release-v2.2.40.1
Release v2.2.40.1
2023-06-10 21:36:42 +09:30
grossmj
1446748934 Release v2.2.40.1 2023-06-10 20:06:40 +09:30
grossmj
3f0ce380e8 Merge branch 'master' into 2.2 2023-06-10 17:22:50 +09:30
grossmj
bd71383354 Development on v2.2.41.dev1 2023-06-06 12:43:20 +09:30
Jeremy Grossmann
9649895378 Merge pull request #3479 from GNS3/release-v2.2.40
Release v2.2.40
2023-06-06 12:41:46 +09:30
grossmj
8579ffa20a Release v2.2.40 2023-06-06 10:23:42 +09:30
grossmj
3206743329 Merge branch 'master' into 2.2 2023-06-06 10:19:45 +09:30
grossmj
29c87b6e96 Change log messages for Websocket errors 2023-06-03 21:05:26 +09:30
grossmj
93b2721d6a Do not proceed if an appliance symbol cannot be downloaded. Ref #3466 2023-05-23 16:31:51 +08:00
grossmj
1ff369683f Revert "Fix open IPv6 address for HTTP consoles. Fixes #3448"
This reverts commit 7c56a2467c.
2023-05-22 19:39:03 +08:00
grossmj
7c56a2467c Fix open IPv6 address for HTTP consoles. Fixes #3448 2023-05-22 16:46:57 +08:00
grossmj
59ef34c17d Delete a node or link from topology summary view using Delete key. Ref #3445 2023-05-14 21:19:19 +08:00
grossmj
d1fae54049 Fix "Start the capture visualization program" checkbox works only one (first) time for a given link. Fixes #3442 2023-05-14 20:38:34 +08:00
grossmj
49bd61f769 Let the selected link style applied when editing a link. Fixes #3460 2023-05-14 15:33:08 +08:00
grossmj
9a4faddd10 Fix hovered color shown in style editing dialog. Fixes #3460 2023-05-14 14:52:27 +08:00
Jeremy Grossmann
7654681a94 Merge pull request #3468 from GNS3/release-v2.2.39
Release v2.2.39
2023-05-08 20:28:43 +08:00
grossmj
9bfecde957 Development on v2.2.40.dev1 2023-05-08 20:26:40 +08:00
grossmj
705cbf8bb9 Release v2.2.39 2023-05-08 19:17:02 +08:00
Jeremy Grossmann
ab6e0ce496 Merge pull request #3461 from GNS3/fix/3441
Fix nodes are not snapped to the grid at the moment of creation
2023-05-08 17:13:20 +08:00
grossmj
8042c9eb6f Fix tests 2023-05-08 17:08:10 +08:00
grossmj
ad3c8a09db Fix nodes are not snapped to the grid at the moment of creation 2023-04-23 05:18:02 -10:00
grossmj
ea4a7f201e Upgrade sentry-sdk 2023-03-23 21:41:50 -10:00
grossmj
28c82b8718 Upgrade distro and aiohttp dependencies 2023-03-01 18:03:28 +10:00
grossmj
6a4dd59e81 Development on 2.2.39.dev1 2023-02-28 17:09:39 +10:00
Jeremy Grossmann
7418c190a8 Merge pull request #3447 from GNS3/2.2
Release v2.2.38
2023-02-28 14:22:10 +08:00
grossmj
737e32f5c3 Release v2.2.38 2023-02-28 15:35:17 +10:00
grossmj
cfc09d2c14 Merge branch 'master' into 2.2 2023-02-28 15:07:07 +10:00
grossmj
f6ab5cae16 Add long description content type in setup.py 2023-02-01 09:56:02 +08:00
grossmj
39ec7eb8ea Automatically add new issues to GNS3 project 2023-01-31 09:31:52 +08:00
grossmj
64c579d43c Development 2.2.38.dev1 2023-01-25 18:36:39 +08:00
grossmj
98cc82e6fd Release v2.2.37 2023-01-25 15:06:12 +08:00
grossmj
4b795112b4 Merge branch 'master' into 2.2 2023-01-25 14:44:11 +08:00
grossmj
0e186afaf1 Comment AllocConsole() 2023-01-25 14:41:55 +08:00
grossmj
b218f7fdf8 Bump version to 2.2.37.dev3 2023-01-25 14:13:07 +08:00
grossmj
f1cb6d66f3 Try to fix hiding console. Ref #3290 2023-01-25 14:08:52 +08:00
grossmj
29758f1b4f Debug win32console 2023-01-24 22:25:39 +08:00
grossmj
445dcf3e3b Upgrade to PyQt5 v5.15.7 2023-01-24 18:54:15 +08:00
grossmj
f623f28509 Add venv to .gitignore 2023-01-17 13:40:37 +08:00
grossmj
9d02d57162 Bump version to 2.2.37.dev2 2023-01-17 13:30:09 +08:00
Jeremy Grossmann
df03f50e3d Merge pull request #3427 from eantowne/master
Changed Windows Terminal telnet console profile from OS X to Windows ref: #3193
2023-01-17 05:52:31 +05:45
Ean Towne
3b72a66ca5 Changed Windows Terminal telnet console profile from OS X to windows ref: issue #3193 2023-01-16 16:50:57 -05:00
grossmj
f8aee44442 Fix tests 2023-01-10 08:42:25 +08:00
grossmj
6dd4d1700e Convert README to Markdown 2023-01-10 08:16:17 +08:00
grossmj
9b674669db Development on 2.2.37.dev1 2023-01-05 09:13:30 +08:00
grossmj
53073d458f Merge branch '2.2' 2023-01-05 09:12:01 +08:00
grossmj
957d89d450 Release v2.2.36 2023-01-04 19:46:30 +08:00
Jeremy Grossmann
db02cbdb2f Merge pull request #3421 from GNS3/qemu-tpm-support
Trusted Platform Module (TPM) support for Qemu VMs
2023-01-04 10:55:52 +05:45
grossmj
0c9f70152f Add checkbox to enable TPM 2023-01-04 12:45:40 +08:00
grossmj
9016975958 Add Trusted Platform Module (TPM) support for Qemu VMs 2023-01-04 12:13:19 +08:00
grossmj
bf295060fd Add "on_close" setting to appliance schema. Fixes https://github.com/GNS3/gns3-server/issues/2148 2023-01-01 16:23:17 +08:00
grossmj
c22ec9f8bd Add default 'ide' disk interface when manually creating Qemu VM template. Fixes #3360 2022-12-29 08:54:40 +08:00
grossmj
bb49cadc6a Fix zoom factor is multiplied when loading projects. Fixes #3408 2022-12-29 08:49:10 +08:00
grossmj
131a49160c Update sentry-sdk dependency 2022-12-28 15:13:26 +08:00
grossmj
225b829eae Fix syntax error in .whitesource 2022-12-27 12:27:26 +08:00
grossmj
e5ef6180b1 Add more base branches for Mend to scan 2022-12-27 12:25:49 +08:00
grossmj
6e7947eea3 Remove deprecated PuTTY option in preferences. Ref https://github.com/GNS3/gns3-gui/discussions/3415 2022-12-24 11:19:29 +08:00
Jeremy Grossmann
3922d370a8 Create SECURITY.md 2022-12-20 21:28:08 +08:00
grossmj
833b9d00c9 Upgrade dependencies 2022-12-18 14:14:56 +08:00
Jeremy Grossmann
377b8dfcaf Create codeql.yml 2022-12-18 14:08:00 +08:00
grossmj
e68937475f Development on v2.2.36.dev2 2022-11-11 00:36:47 +08:00
grossmj
6f418f0853 Release v2.2.35.1 2022-11-10 22:21:14 +08:00
grossmj
8e59927ada Merge branch 'master' into 2.2 2022-11-10 22:06:25 +08:00
grossmj
1012686053 Development on 2.2.36.dev1 2022-11-09 20:02:20 +08:00
grossmj
672bd850ad Merge branch '2.2' 2022-11-09 20:00:38 +08:00
grossmj
5db5e1f9fe Release v2.2.35 2022-11-08 23:40:25 +08:00
grossmj
ca94c71bf2 Use Visual Studio 2022 in appveyor.yml 2022-11-08 23:09:23 +08:00
grossmj
76264c55ce Merge branch 'master' into 2.2 2022-11-08 19:29:49 +08:00
grossmj
fd243c42a8 Downgrade psutil to v5.9.2 2022-11-08 19:18:07 +08:00
grossmj
a6521ef9e4 Upgrade psutil to v5.9.4 2022-11-08 18:49:31 +08:00
grossmj
9fa833762c Upgrade pywin32 to v305 2022-11-08 18:29:51 +08:00
grossmj
ca0c6468b5 Fix "variables": [] in project file leads to unlimited increase of empty name/value pairs in GUI. Fixes #3397 2022-11-07 22:29:02 +08:00
grossmj
15f6945a94 Upgrade dependencies 2022-11-07 21:48:45 +08:00
grossmj
645deb8c79 Ignore local revision when comparing versions. 2022-11-07 20:03:05 +08:00
grossmj
428f12a2b3 Make version PEP 440 compliant 2022-11-06 17:51:31 +08:00
grossmj
9ad5760ee6 Support for Python 3.11 2022-10-30 19:04:54 +08:00
grossmj
82fc4fb3c9 Revert "Fix issue when using tail.exe with non-ascii paths. Fixes #3021"
This reverts commit df42147d92.
2022-10-19 19:38:43 +08:00
grossmj
df42147d92 Fix issue when using tail.exe with non-ascii paths. Fixes #3021 2022-10-19 19:04:29 +08:00
grossmj
da5520aa90 Upgrade PyQt to 5.15.7 and pywin32 to v304 2022-10-19 18:31:40 +08:00
Jeremy Grossmann
491c66a315 Merge pull request #3395 from GNS3/fix/3393
Update requirements.txt
2022-10-18 22:30:11 +08:00
Jeremy Grossmann
e5c81da700 Merge branch '2.2' into fix/3393 2022-10-18 22:28:32 +08:00
grossmj
65fad1b4f4 Upgrade to Visual Studio 2022 in appveyor.yml 2022-10-18 21:47:10 +08:00
grossmj
34661908d9 Upgrade to Python 3.7 in appveyor.yml 2022-10-18 21:42:51 +08:00
grossmj
aee5ffa17f Upgrade pip and setuptools in appveyor.yml 2022-10-18 21:40:08 +08:00
grossmj
e9e8be42b5 Upgrade pytest. Fixes #3399 2022-10-18 21:16:46 +08:00
grossmj
ae0d928383 Use jsonschema v3.2.0 for Python 3.6 2022-10-12 22:13:34 +08:00
grossmj
8db3c1be42 Allow for more dependency versions at patch level 2022-10-12 22:07:37 +08:00
grossmj
f50da3ebd7 Replace deprecated distro.linux_distribution() call 2022-10-11 23:28:11 +08:00
grossmj
75b52fc9a4 Update dev-requirements.txt 2022-10-11 23:23:15 +08:00
grossmj
1952da5876 Update requirements.txt 2022-10-11 23:01:24 +08:00
Jeremy Grossmann
1f620026d4 Merge pull request #3394 from KaisenCAS/master
CVE-2007-4559 patch
2022-10-10 23:31:52 +08:00
grossmj
1d293618e5 Upgrade dependencies 2022-10-10 14:29:04 +08:00
Kevin Chevreuil - Kaisen
2622549ce6 Add a fix for the CVE-2007-4559 2022-10-09 22:55:15 +02:00
grossmj
900bd1c0b4 Development on 2.2.35dev1 2022-08-29 11:14:44 +02:00
grossmj
0b3dbb2843 Release v2.2.34 2022-08-28 23:28:12 +02:00
grossmj
ef4f6b2b27 Upgrade Sentry dependency 2022-08-28 00:02:54 +02:00
grossmj
e9806345ca Downgrade to pytest v7.0.1 (last version to support 2022-08-27 19:35:36 +02:00
grossmj
ee23e32c75 Upgrade dev dependencies 2022-08-27 19:29:42 +02:00
grossmj
fbeacdcb2a Implement new option (Delete All) to contextual menu in "Console" dock. Fixes #3325 2022-08-16 17:48:58 +02:00
grossmj
b3937c7b94 Fix 2560x1440 resolution for Docker container 2022-08-07 23:56:11 +02:00
Abdelbaki Boukerche
181bf3f360 Rounded Rectangle 2022-08-04 18:20:54 +01:00
grossmj
f2711732db Back to development on v2.2.34dev2 2022-06-21 11:52:58 +02:00
grossmj
148ac4b072 Revert "Development on v2.2.34dev2"
This reverts commit 65eeb79b26.
2022-06-21 11:51:01 +02:00
grossmj
65eeb79b26 Development on v2.2.34dev2 2022-06-21 11:38:09 +02:00
grossmj
537304ce08 Release v2.2.33.1 2022-06-21 10:48:02 +02:00
grossmj
f22df5f016 Development on v2.2.34dev1 2022-06-20 21:47:42 +02:00
grossmj
8dfc8b7714 Release v2.2.33 2022-06-20 20:53:21 +02:00
grossmj
8c6fa9433f Upgrade sentry-sdk and psutil 2022-06-20 20:05:34 +02:00
Jeremy Grossmann
63837578c5 Merge pull request #3340 from GNS3/node-name-checks
Check node names
2022-06-20 19:02:37 +02:00
grossmj
b719703dbe Check that node names for Qemu and Docker are valid 2022-06-18 16:59:14 +02:00
grossmj
084d14c17e Backport reset all console connections. Fixes #2072 2022-06-15 15:58:15 +02:00
grossmj
8c0fca1dd7 Add more video resolutions to Docker containers using VNC. Fixes #3329 2022-06-09 00:26:39 +08:00
grossmj
863d05c923 Add python_requires=">=3.4" in setup.py. Fixes #3326 2022-06-07 18:27:01 +08:00
grossmj
3ebaac8a2c Only allow post release corrective versions of GUI and server to interact 2022-06-07 18:22:06 +08:00
grossmj
16878c9dfa Allow minor versions of GUI and server to interact 2022-06-07 18:06:53 +08:00
grossmj
45da18bb7c Update VirtViewer path. Fixes #3334 2022-06-07 17:35:55 +08:00
grossmj
7a6d06ea0c Development on 2.2.33dev1 2022-04-27 19:51:24 +07:00
grossmj
d371042647 Upgrade distro package to v1.7.0 2022-04-27 19:48:50 +07:00
grossmj
0321c11c34 Release v2.2.32 2022-04-27 18:47:20 +07:00
grossmj
522df41a57 Use public DSNs for Sentry 2022-04-20 18:41:18 +07:00
grossmj
afccdf5b9e Fix exception when doubleclick on NAT node. Fixes #3312 2022-04-20 17:55:16 +07:00
grossmj
b2cd24b511 Upgrade some packages 2022-04-20 17:38:54 +07:00
grossmj
6d131a05f1 Fix "Apply" button in the "Preferences" dialog stays gray when templates/nodes are opened by double-click. Fixes #3307 2022-04-20 16:49:22 +07:00
grossmj
35e6156c6c Add 'reset docks' in the view menu. Ref #3317 2022-04-20 15:53:32 +07:00
grossmj
96d8de4da8 Development on 2.2.32dev1 2022-02-26 20:39:42 +10:30
grossmj
6b5a6f3dfe Release v2.2.31 2022-02-26 18:22:17 +10:30
grossmj
8f82eac321 Development on 2.2.31dev1 2022-02-25 15:59:19 +10:30
grossmj
e03ed64f59 Install setuptools v59.6.0 when using Python 3.6 2022-02-25 15:50:35 +10:30
grossmj
3d702aabd0 Release v2.2.30 2022-02-25 14:51:39 +10:30
grossmj
f5e63c2321 Set setuptools to v60.6.0 2022-02-06 21:02:56 +10:30
grossmj
1047eb916a Upgrade dependencies 2022-02-06 17:33:10 +10:30
grossmj
5dc7d0fbda Upgrade to pywin32 v303. Ref #3290 2022-02-06 17:31:32 +10:30
grossmj
2609be98b6 Fix int() call. Ref #3283 2022-01-15 18:57:15 +10:30
grossmj
6286e596c0 Fix QPoint() as unexpected type 'float'. Fixes #3283 2022-01-15 18:55:38 +10:30
grossmj
3c546086ed Fix painter.drawRect() has unexpected type 'float'. Fixes #3282 2022-01-15 18:32:35 +10:30
grossmj
f4b2c1c5b9 Fix SpinBox.setValue() requires integer. Fixes #3281 2022-01-11 23:12:54 +10:30
grossmj
e578ecdd8a Development on 2.2.30dev1 2022-01-08 22:52:59 +10:30
grossmj
da8adbaa18 Release v2.2.29 2022-01-08 22:14:59 +10:30
grossmj
6d1333f5fe Clear cache when opening symbol selection dialog. Fixes #3256 2021-12-27 12:43:32 +10:30
grossmj
92c858dd07 Fix @ in username issue with HTTP authentication. Fixes #3275 2021-12-25 11:19:07 +10:30
grossmj
0c7a12f68c Merge branch 'master' into 2.2 2021-12-25 10:58:46 +10:30
Jeremy Grossmann
a4d08cce8c Merge pull request #3277 from etiennewan/etiennewan-patch-2
Fixed QPoint called with floats
2021-12-25 10:27:00 +10:00
grossmj
e0dd7a66e1 Use '//' operator instead of int() 2021-12-24 13:39:19 +10:30
grossmj
23be668c97 Fix create drawing item calls since mapToScene() returns a QPointF
https://doc.qt.io/qt-5/qgraphicsview.html#mapToScene-4
2021-12-24 13:38:26 +10:30
Etienne Wan
68d0278140 Fixed QPoint called with floats 2021-12-23 18:37:26 +01:00
Jeremy Grossmann
d8e4c1de4d Merge pull request #3273 from tsndqst/fix_create_link_test
Fix create_link test
2021-12-16 12:26:38 +10:00
Your Name
a5aa9bfb7a Remove problematic lines 2021-12-15 20:13:57 -06:00
grossmj
3e0273848f Development on 2.2.29dev1 2021-12-15 21:38:34 +10:30
grossmj
ec374f173c Release v2.2.28 2021-12-15 13:54:24 +10:30
grossmj
b8abdc79dc Merge branch 'master' into 2.2 2021-12-15 13:52:41 +10:30
Jeremy Grossmann
43744eab7e Merge pull request #3272 from etiennewan/patch-1
Fixed drawLine called with float arguments
2021-12-15 09:28:35 +10:00
Etienne Wan
e16f700e49 Fixed drawLine called with float arguments 2021-12-13 23:27:28 +01:00
Jeremy Grossmann
925d57b2f8 Merge pull request #3263 from FocusedOne/master
Fixed dead VIX API link
2021-11-23 09:15:54 +10:30
FocusedOne
eceaea1317 Fixed dead VIX API link
Replaced old dead vmware link with current 1.17 version download.
2021-11-22 16:40:01 -06:00
grossmj
4326785dfc Development on 2.2.28dev1 2021-11-13 16:31:21 +10:30
grossmj
3920c28bde Release v2.2.27 2021-11-12 15:33:53 +10:30
grossmj
b34f51e4b0 Merge branch 'master' into 2.2 2021-11-12 14:50:55 +10:30
grossmj
ef45b2e0f1 Fix symbols in "Symbol selection" dialog are not placed in alphabetical order. Fixes #3245 2021-11-08 22:20:22 +10:30
grossmj
545a9f53a8 Fix links duplicates in topology summary. Fixes #3251 2021-11-08 21:55:29 +10:30
grossmj
83d9367860 Development on 2.2.27dev1 2021-10-08 21:49:11 +10:30
grossmj
2131f07e5f Merge branch '2.2' 2021-10-08 21:46:38 +10:30
grossmj
cf3e716e63 Release v2.2.26 2021-10-08 21:02:04 +10:30
grossmj
c79f14bcab Open "template configuration" dialog with double click on template name in "Preferences". Fixes #3239 2021-10-08 16:35:25 +10:30
grossmj
acd044a88a Only show "virtio" network adapter when legacy node is enabled. Fixes https://github.com/GNS3/gns3-gui/issues/1969 2021-10-08 15:46:56 +10:30
Jeremy Grossmann
f26c638350 Merge pull request #3237 from SDN-Projects/optimization/pip-no-cache-dir
chore : use --no-cache-dir flag to pip in dockerfiles to save space
2021-09-23 09:59:58 +09:30
Pratik Raj
4ea24e622b chore : use --no-cache-dir flag to pip in dockerfiles to save space
using --no-cache-dir flag in pip install ,make sure downloaded packages
by pip don't cached on system . This is a best practice which make sure
to fetch from repo instead of using local cached one . Further , in case
of Docker Containers , by restricting caching , we can reduce image size.
In term of stats , it depends upon the number of python packages
multiplied by their respective size . e.g for heavy packages with a lot
of dependencies it reduce a lot by don't caching pip packages.

Further , more detail information can be found at

https://medium.com/sciforce/strategies-of-docker-images-optimization-2ca9cc5719b6

Signed-off-by: Pratik Raj <rajpratik71@gmail.com>
2021-09-22 15:13:38 +05:30
grossmj
ab854752d9 Double-click on a template opens "template configuration" dialog. Fixes #3236 2021-09-20 20:28:56 +09:30
grossmj
5cee045a65 Fix "Custom symbols" can't be unfolded after using "Filter" field. Fixes #3231 2021-09-20 18:39:32 +09:30
grossmj
37cd82fb44 Development on v2.2.26dev1 2021-09-14 21:13:04 +09:30
grossmj
334eb5175c Release v2.2.25 2021-09-14 19:20:11 +09:30
grossmj
25841ea7db Fix menu disabled for modal dialogs on macOS. Fixes #3007 2021-09-09 21:21:22 +09:30
grossmj
3d3b4f92b2 Change method to display the recent files menu. Fixes #3007 2021-09-09 09:23:45 +09:30
grossmj
82740da89d Fix bug when using empty port names for custom adapters. Fixes #3228 2021-09-08 16:16:27 +09:30
grossmj
ad19b3dda0 Upgrade PyQt5 to version 5.15.4 for macOS 2021-09-08 15:36:04 +09:30
grossmj
bb8fd18f98 Fix mouse zoom-in/out step value is two times bigger than keyboard one. Fixes #3226 2021-09-08 15:26:56 +09:30
grossmj
336eaf443a Upgrade to Qt 5.15.4 on Windows. Ref #3210 2021-09-08 14:25:25 +09:30
grossmj
0b94be6805 Fix issue with custom adapters at the node level. Fixes #3223 2021-09-05 21:15:30 +09:30
grossmj
671ced78ff Merge branch 'master' into 2.2 2021-09-02 14:45:00 +09:30
Jeremy Grossmann
c8766ce529 Merge pull request #3157 from hrnciar/setuptools
Explicitly require setuptools, utils/get_resource.py imports pkg_resources
2021-08-29 22:06:22 -07:00
Jeremy Grossmann
bec9512c78 Merge branch 'master' into setuptools 2021-08-29 22:02:55 -07:00
grossmj
b2ad5f4158 Development on 2.2.25dev1 2021-08-25 21:23:19 +09:30
grossmj
966873bc6c Release v2.2.24 2021-08-25 20:31:26 +09:30
grossmj
5b9111b55d Merge branch 'master' into 2.2 2021-08-25 20:08:45 +09:30
grossmj
56688f2236 Update dependencies 2021-08-24 21:12:27 +09:30
grossmj
2e656a9d53 Fix incorrect Qemu binary selected when importing template. Fixes https://github.com/GNS3/gns3-gui/issues/3216 2021-08-24 17:26:07 +09:30
grossmj
2790f707c3 Early support for Python3.10 2021-08-15 15:10:02 +09:30
Jeremy Grossmann
ee9002df61 Merge pull request #3217 from GNS3/dependabot/pip/pywin32-301
Bump pywin32 from 300 to 301
2021-08-09 17:59:04 -07:00
dependabot[bot]
52626e9fe9 Bump pywin32 from 300 to 301
Bumps [pywin32](https://github.com/mhammond/pywin32) from 300 to 301.
- [Release notes](https://github.com/mhammond/pywin32/releases)
- [Changelog](https://github.com/mhammond/pywin32/blob/master/CHANGES.txt)
- [Commits](https://github.com/mhammond/pywin32/commits)

---
updated-dependencies:
- dependency-name: pywin32
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-09 20:48:41 +00:00
grossmj
6619c6af97 Add PyQt5==5.12.3 for macOS build 2021-08-07 20:09:41 +09:30
grossmj
60e04c7248 Development on 2.2.24dev1 2021-08-05 21:16:10 +09:30
grossmj
724858f977 Release v2.2.23 2021-08-05 15:58:54 +09:30
Jeremy Grossmann
5a2e05a4fd Merge pull request #3212 from GNS3/handle_no-kvm_deprecated
Handle -no-kvm param deprecated in Qemu >= v5.2
2021-07-27 17:37:45 +09:30
grossmj
010888e3ca Handle -no-kvm param deprecated in Qemu >= v5.2 2021-07-27 16:34:51 +09:30
grossmj
3226921536 Support for invisible links. Fixes #2461 2021-07-27 15:30:58 +09:30
grossmj
022e918301 Add kitty console application command line. Fixes #3203 2021-07-25 16:12:35 +09:30
grossmj
846b19a9e7 Add Windows Terminal profile as an option for Console Applications. Fixes #3193 2021-06-14 13:10:01 +09:30
grossmj
45f5c6e010 Development on 2.2.23dev1 2021-06-10 16:20:10 +09:30
grossmj
963bbb7b89 Release v2.2.22 2021-06-10 15:41:58 +09:30
grossmj
016ad7a775 Fix exception shown when GNS3 is started with empty config. Fixes #3188 2021-06-10 12:28:25 +09:30
grossmj
e8c82566c6 Add ZOC8 console terminal for macOS command line 2021-06-07 19:41:09 +09:30
grossmj
1ed6fceade Fix tests. Ref https://github.com/GNS3/gns3-gui/issues/2461 2021-06-07 14:26:20 +09:30
grossmj
d945fd8b7b Minor changes to style editor dialog. 2021-06-07 14:10:32 +09:30
grossmj
fd6c7eccd0 Link style support. Fixes https://github.com/GNS3/gns3-gui/issues/2461 2021-06-07 14:09:58 +09:30
grossmj
7a1afe2aec Upgrade dependencies 2021-06-07 13:46:06 +09:30
grossmj
6debe56d8e Fix charcoal theme. Ref #3137 2021-06-06 21:45:16 +09:30
grossmj
a4c7d41c26 Fix issue when showing menu to select port. Fixes #3169 2021-05-20 22:15:21 -07:00
grossmj
ea9243dcd9 Merge remote-tracking branch 'origin/2.2' into 2.2 2021-05-20 15:00:49 +09:30
grossmj
e9d8337bd6 Revert "Downgrade to PyQt5 5.12.1. Fixes https://github.com/GNS3/gns3-gui/issues/3169"
This reverts commit ece4d51213.
2021-05-20 14:59:44 +09:30
Jeremy Grossmann
3c92e463f8 Update setup.py
Fixes https://github.com/GNS3/gns3-server/issues/1897
2021-05-16 17:45:11 +09:30
grossmj
3d07db5c5f Development on 2.2.22dev1 2021-05-10 23:44:40 +09:30
grossmj
20cc309ac8 Release v2.2.21 2021-05-10 22:42:47 +09:30
grossmj
262a2839c5 Fix issue with empty project variable name. Fixes #3162 2021-05-10 17:55:06 +09:30
grossmj
ece4d51213 Downgrade to PyQt5 5.12.1. Fixes https://github.com/GNS3/gns3-gui/issues/3169 2021-05-10 17:03:22 +09:30
grossmj
0ef39ba129 Development on 2.2.21dev1 2021-04-09 13:50:21 +09:30
grossmj
f90267b4f0 Release v2.2.20 2021-04-09 12:14:38 +09:30
grossmj
8f16706a22 Merge branch 'master' into 2.2 2021-04-09 12:05:15 +09:30
grossmj
2d3ee3abf9 Fix project does not load anymore. Fixes #3140 2021-04-07 16:47:09 +09:30
grossmj
b8b209fa55 Fix errors while connecting to server 2021-04-07 15:51:52 +09:30
grossmj
18129e3d29 Do not connect to server while waiting for user to accept/reject SSL certificate. Fixes #3144 2021-04-07 12:09:38 +09:30
grossmj
7a2b9c024f Fix invalid server version check request. Fixes #3144 2021-04-07 12:03:37 +09:30
grossmj
4923a6dc17 Revert to PyQt5 v5.12.3 because of SSL not working
Probably the SSL DLLs weren't properly found and included by cx_Freeze
2021-04-06 23:01:07 +09:30
grossmj
73dfc047aa Set PyQt5 version to 5.15.2 on Windows 2021-04-06 22:12:34 +09:30
grossmj
fe0a70c4be Upgrade dependencies 2021-04-06 13:57:00 +09:30
Tomas Hrnciar
67014965be Explicitly require setuptools, utils/get_resource.py imports pkg_resources 2021-03-31 11:53:28 +02:00
Jeremy Grossmann
f14cb43404 Merge pull request #3153 from VidVidex/master
Add terminator as a predefined custom console option
2021-03-26 14:53:00 +10:30
Vid
f8517ee5ac Add terminator as a predefined custom console option 2021-03-24 20:28:19 +01:00
grossmj
7dc607b4c5 Development on 2.2.20dev1 2021-03-05 16:48:09 +10:30
grossmj
882fa76550 Release v2.2.19 2021-03-05 14:51:03 +10:30
grossmj
1490a1ad8f Development on 2.2.19dev1 2021-02-16 20:44:58 +10:30
grossmj
aab0c99cc6 Release v2.2.18 2021-02-16 19:09:46 +10:30
grossmj
a6a987d74c Fix bug with SSL connection on projet websocket stream. 2021-02-16 17:42:18 +10:30
grossmj
9c58b18c20 Merge remote-tracking branch 'origin/2.2' into 2.2 2021-02-16 16:42:45 +10:30
grossmj
8bc499c68f Bump version to 2.2.18dev2 2021-02-16 16:35:26 +10:30
Jeremy Grossmann
bd5eb288b7 Merge pull request #3130 from GNS3/ssl-support
SSL support.
2021-02-16 16:16:32 +10:30
grossmj
465a289568 SSL support. 2021-02-16 16:08:27 +10:30
grossmj
d240ba3056 Merge remote-tracking branch 'origin/2.2' into 2.2 2021-01-26 23:11:11 +10:30
grossmj
3cedfd3649 Remove the useless file "zoom-in (copy).svg". Fixes #3114 2021-01-26 23:10:34 +10:30
Jeremy Grossmann
276d7abdd9 Merge pull request #3104 from b-ehlers/QemuConfig
Add Qemu config disk
2020-12-14 14:23:09 +10:30
grossmj
927e38bd6d Development on 2.2.18dev1 2020-12-04 18:10:11 +10:30
grossmj
376cc29995 Release v2.2.17 2020-12-04 16:26:56 +10:30
grossmj
1f8ebeb084 Merge branch 'master' into 2.2 2020-12-04 16:21:42 +10:30
grossmj
0212755c78 Remove "-nographic" option by default for Qemu VM. Fixes #3094 2020-12-02 18:44:18 +10:30
Jeremy Grossmann
2f7d75eae9 Fix app cannot start on macOS Big Sur. Ref #3037 2020-11-30 20:02:52 +10:30
Jeremy Grossmann
fc1c060922 Merge pull request #3097 from SpikefishSolutions/master
Add yes/no prompts to gui for global project level buttons start/stop/reload/suspend to prevent bad day.
2020-11-21 18:32:45 +10:30
John
0ea72ce782 one more spacing update 2020-11-20 21:33:44 -05:00
John
3de2d2eda2 spacing updates 2020-11-20 21:32:26 -05:00
John
c08262f8af Correct stop/start/reload/suspend button names 2020-11-20 21:26:08 -05:00
John
9ae70bf2fe Add yes/no prompts to all major buttons 2020-11-20 21:11:15 -05:00
John
fa6d250602 oops.. need to build after commit. 2020-11-20 20:27:43 -05:00
John
0668840a2b i don't get it. 2020-11-20 20:26:19 -05:00
John
8b25d1b06c can't fix indent? 2020-11-20 20:25:06 -05:00
John
58c3ba0755 update indent 2020-11-20 20:23:46 -05:00
John
5a91c9aaf8 Create a message box for stopping all devives instead of blindly making someone's day terrible. 2020-11-20 18:28:30 -05:00
grossmj
0fc3f4ef16 Development on 2.2.17dev1 2020-11-05 16:59:58 +10:30
grossmj
f0e5cd2ba2 Release v2.2.16 2020-11-05 15:38:19 +10:30
grossmj
f59ef6378a Fix broken security link (replaced by email). Fixes #3085 2020-11-05 15:00:04 +10:30
grossmj
61ef08d1b7 Fix packets capture stops after some time. Fixes #3067 2020-11-05 14:21:22 +10:30
grossmj
e812c000fd Option to allocate or not the vCPUs and RAM settings for the GNS3 VM. Fixes https://github.com/GNS3/gns3-gui/issues/3069 2020-11-05 11:13:57 +10:30
Bernhard Ehlers
d3d9e1e8ae Use HDD disk image as startup QEMU config disk 2020-10-19 03:45:27 +02:00
Bernhard Ehlers
05f8df345a Fix HDD configuration layout
(cherry picked from commit 4f631669e5)
2020-10-16 10:22:32 +02:00
grossmj
4b0cc11cab Development on 2.2.16dev1 2020-10-07 16:30:03 +10:30
grossmj
b5285cd142 Release v2.2.15 2020-10-07 15:29:52 +10:30
grossmj
69482343ba Fix custom symbol not sent to remote controller when installing appliance 2020-10-07 15:09:08 +10:30
grossmj
d4639c2e61 Development on 2.2.15dev1 2020-09-15 06:49:11 +09:30
grossmj
b85ade9dd7 Release v2.2.14 2020-09-15 05:52:48 +09:30
grossmj
e191cb8aa3 Fix tests. Ref #3002 2020-09-14 00:10:11 +09:30
grossmj
e6bc75ce26 Improvements to add a new version of an appliance from wizard. Fixes #3002. 2020-09-14 00:04:58 +09:30
grossmj
bc1df346f2 Development on 2.2.14dev1 2020-09-05 04:26:16 +09:30
grossmj
27c35321f0 Release v2.2.13 2020-09-04 23:13:28 +09:30
Bernhard Ehlers
3e212fc629 Edit only text mode config files
(cherry picked from commit 880ac5e8c3)
2020-08-18 02:27:31 +02:00
Bernhard Ehlers
25e41dc0f1 Hide config import/export when configFiles attribute is empty
(cherry picked from commit fd7b915e96)
2020-08-17 13:09:59 +02:00
grossmj
c58c7774c4 Qemu disk interfaces must be set to "none" by default. Ref #3035
(cherry picked from commit 5fbb6cbf61)
2020-08-17 12:49:21 +09:30
grossmj
bd2bc8265c Do not allow image to be configured on Qemu VM secondary slave disk if create config disk option is enabled.
(cherry picked from commit 04f9a1cf8c)
2020-08-15 16:05:43 +09:30
grossmj
f2209a2780 Add explicit option to automatically create or not the config disk. Off by default.
(cherry picked from commit af79471afd)
2020-08-14 17:57:24 +09:30
grossmj
7b99ba325b Development on 2.2.13dev1 2020-08-07 21:12:46 +09:30
grossmj
74763287fb Release v2.2.12 2020-08-07 19:27:32 +09:30
grossmj
737ff42d64 Merge branch 'master' into 2.2 2020-08-07 19:04:08 +09:30
Jeremy Grossmann
5656bd2d48 Downgrade psutil to version 5.6.7 2020-07-29 17:36:14 +09:30
Jeremy Grossmann
058c069394 Fix log shows the GUI command line without spaces between its arguments. Fixes #3026 2020-07-27 18:27:23 +09:30
grossmj
926ec48d00 Upgrade to psutil version 5.7.2 2020-07-21 15:49:58 +09:30
grossmj
410e5353b2 Use server host is console host is equal to "0:0:0:0:0:0:0:0" 2020-07-17 21:13:27 +09:30
grossmj
bfb90406ed Remove VMware promotion. 2020-07-17 21:12:59 +09:30
grossmj
439cdce287 Development on 2.2.12dev1 2020-07-09 21:37:03 +09:30
grossmj
4e50c2a4b1 Release v2.2.11 2020-07-09 20:37:10 +09:30
grossmj
94c636ae61 Merge branch 'master' into 2.2 2020-07-09 20:23:31 +09:30
grossmj
f53b9a266e Try to fix "Recent project" selection not working. Ref #3007 2020-07-09 15:37:47 +09:30
grossmj
2476448032 Fix debug entries shown twice in console window and double error messages with remote GNS3VM. Fixes #3010 #3011
Note that the debug level is broken (has been for a long time apparently).
2020-07-07 21:06:56 +09:30
grossmj
a34cd742e3 Merge branch '2.2' 2020-07-06 22:20:05 +09:30
grossmj
39698196ac Fix deprecation warning. Ref #3009 2020-07-06 22:08:10 +09:30
grossmj
61432ced4f Fix tests on macOS. Ref #3009 2020-07-06 22:03:29 +09:30
grossmj
2ddd13c445 Add Snyk badges. 2020-06-27 18:27:04 +09:30
grossmj
af6c4c5b3e Merge branch 'master' into 2.2 2020-06-26 21:30:37 +09:30
grossmj
d4012294bf Run tests inside container 2020-06-26 20:50:48 +09:30
grossmj
4b04b0e855 Use xvfb to run tests 2020-06-26 20:41:08 +09:30
grossmj
1bec5019bf Install PyQt5 using pip 2020-06-26 19:42:42 +09:30
grossmj
ec6b876baa Explicitly install sip 2020-06-26 19:38:10 +09:30
grossmj
7cee0d01ab Install PyQt5 for tests and add GitHub Actions badge 2020-06-26 19:34:02 +09:30
Jeremy Grossmann
dd3314d06b Set up GitHub Actions for running tests 2020-06-26 19:27:22 +09:30
grossmj
9c58b26265 Remove tox, Travis CI and pep8.sh script
Update dependencies
2020-06-26 19:21:51 +09:30
Jeremy Grossmann
83c26f47da Merge pull request #3005 from GNS3/whitesource/configure
Configure WhiteSource for GitHub.com
2020-06-26 09:04:39 +08:00
whitesource-for-github-com[bot]
8ed2f55600 Add .whitesource configuration file 2020-06-26 01:01:54 +00:00
Jeremy Grossmann
b435317904 Merge pull request #3003 from GNS3/snyk-fix-8bf3e4840df4587cc42afb85b857d470
[Snyk] Security upgrade psutil from 5.6.6 to 5.6.7
2020-06-25 11:41:01 +08:00
snyk-bot
acb8aa8ca2 fix: requirements.txt to reduce vulnerabilities
The following vulnerabilities are fixed by pinning transitive dependencies:
- https://snyk.io/vuln/SNYK-PYTHON-PSUTIL-483082
2020-06-24 13:10:33 +00:00
grossmj
c55d6b8a6f Fix sentry SDK is configured twice. 2020-06-24 12:40:06 +09:30
grossmj
a4039a254e Development on 2.2.11dev1 2020-06-18 19:06:00 +09:30
grossmj
85ed4b3026 Release v2.2.10 2020-06-18 12:29:33 +09:30
grossmj
5207a99692 New fix for multi-device selection/deselection not working as expected with right click. Fixes #2986 2020-06-09 13:50:31 +09:30
grossmj
d69527995d Revert "Fix Multi-device selection/deselection not working as expected with right click. Fixes #2986"
This reverts commit ddeb95cb0a.
2020-06-09 13:19:20 +09:30
grossmj
4b000ba2f7 Optimize snap-to-grid code for drawing items. Fixes #2997 2020-06-09 11:47:05 +09:30
grossmj
1b302b77a0 Move jsonschema 2.6.0 requirement in build repository.
https://github.com/GNS3/gns3-server/issues/1751
https://github.com/GNS3/gns3-gui/issues/2849

This is to avoid the following error:

```
ERROR: Double requirement given: jsonschema==2.6.0 (from -r gns3-gui\win-requirements.txt (line 4)) (already in jsonschema==3.2.0 (from -r gns3-gui\requirements.txt (line 1)), name='jsonschema')
```
2020-06-07 13:07:16 +09:30
grossmj
a5b5c404ec Only use jsonschema 2.6.0 on Windows and macOS.
https://github.com/GNS3/gns3-server/issues/1751
https://github.com/GNS3/gns3-gui/issues/2849
2020-06-07 12:55:22 +09:30
grossmj
6b97b0c6cd Disable default integrations for sentry sdk. 2020-06-06 15:37:17 +09:30
grossmj
115dd43eee Development on 2.2.10dev1 2020-06-04 21:06:30 +09:30
grossmj
2530bf97a8 Release v2.2.9 2020-06-04 18:39:27 +09:30
grossmj
9892fd0654 Fix issue editing README.txt on Windows. 2020-06-04 18:12:50 +09:30
grossmj
c71ee73da8 Merge branch 'master' into 2.2 2020-06-04 12:22:11 +09:30
Jeremy Grossmann
0643fd516d Merge pull request #2993 from GNS3/replicate-network-connection-state
Support to activate/deactive network connection state replication in Qemu
2020-06-04 10:49:41 +08:00
grossmj
a25680f2ce Fix GUI doesn't detect another GUI on macOS. Fixes #2994 2020-06-03 20:38:55 +09:30
grossmj
58bd5be920 Support to activate/deactive network connection state replication in Qemu. 2020-06-02 18:45:22 +09:30
Jeremy Grossmann
d95633ba2c Merge pull request #2989 from GNS3/reset-mac-addresses
Option to reset all MAC addresses when exporting or duplicating a project.
2020-05-27 10:53:22 +08:00
grossmj
dfea6d1723 Option to reset or not all MAC addresses when exporting or duplicating a project. 2020-05-27 12:14:47 +09:30
grossmj
ddeb95cb0a Fix Multi-device selection/deselection not working as expected with right click. Fixes #2986 2020-05-26 16:11:53 +09:30
grossmj
5f7ff0d70d Generate MainWindow Ui file. 2020-05-26 13:01:04 +09:30
Jeremy Grossmann
a00e039cec Merge pull request #2875 from fatoms/master
Proposed fix for "Edit readme" is missing in GNS3 GUI. #2854
2020-05-26 11:30:19 +08:00
Dominic
a24e9adef1 Merge branch 'Edit_Readme' 2020-05-21 20:03:03 +02:00
Dominic Harford
ee5f8e8edd Resolve conflict with GNS3 repo 2020-05-21 19:08:29 +02:00
grossmj
f5470130f5 Fix issues with crash reporting & bump version to 2.2.9dev2. Ref https://github.com/GNS3/gns3-server/issues/1758 2020-05-21 18:19:19 +09:30
grossmj
1ff405885e Merge branch 'master' into 2.2 2020-05-20 17:25:37 +09:30
Dominic
9fb42ead9f Revert "Updated GUI pyqt files from Tab Order 'fixes' in "Tab Order in Preferences and Project Dialog #2872""
This reverts commit 0d2f91709c.
2020-05-19 18:31:02 +02:00
grossmj
2ea1946c0f Replace Raven by Sentry SDK. Fixes https://github.com/GNS3/gns3-server/issues/1758 2020-05-19 15:48:53 +09:30
grossmj
963e054918 Fix online help menu URL. Fixes #2984 2020-05-08 12:42:06 +09:30
grossmj
0f5f6ab645 Require setuptools>=17.1 in setup.py. Ref https://github.com/GNS3/gns3-server/issues/1751
This is to support environmental markers.
https://github.com/pypa/setuptools/blob/master/CHANGES.rst#171
2020-05-08 12:34:58 +09:30
grossmj
8a905b5c39 Development on 2.2.9dev1 2020-05-07 23:10:20 +09:30
grossmj
e917193f06 Merge branch '2.2' 2020-05-07 23:09:04 +09:30
grossmj
16846ce49c Release v2.2.8 2020-05-07 18:10:57 +09:30
grossmj
624a670ae7 Make sure "port" is defined. 2020-05-07 17:51:32 +09:30
grossmj
406326ccd8 Merge remote-tracking branch 'origin/master' 2020-05-06 11:57:25 +09:30
grossmj
24bc15fb73 Default port set to 80 for server running in the GNS3 VM. Fixes #1737 2020-05-05 12:40:50 +09:30
grossmj
348d8b9438 Make the Web UI the default page. Ref https://github.com/GNS3/gns3-server/issues/1737 2020-04-30 17:27:06 +09:30
grossmj
6787982408 Fix "export portable project forgets contents of README". Fixes #1724 2020-04-30 16:43:00 +09:30
Jeremy Grossmann
c2384917fa Update README. Ref https://github.com/GNS3/gns3-server/issues/1719 2020-04-29 15:01:45 +09:30
grossmj
b80178d0cf Activate unified title and toolbar on MacOS. Fixes #2968 2020-04-29 13:08:51 +09:30
grossmj
e6084ed834 Confirmation dialog for "console connect to all nodes". Fixes #2971 2020-04-28 15:04:39 +09:30
grossmj
ba924cd0d9 Add "Resume all suspended links". Fixes #2858 2020-04-28 14:00:26 +09:30
grossmj
0c3d43346f Revert "Change default path for SecureCRT. Fixes #2896"
This reverts commit 0c4367d77e.
2020-04-28 13:19:38 +09:30
grossmj
fcf6ef3027 Remove @property from ConfigurationDialog(). Fixes #2819 #2965 2020-04-28 11:57:54 +09:30
grossmj
e0f87e573d Use Environmental Markers to force jsonschema version. Fixes https://github.com/GNS3/gns3-gui/issues/2849
Version 3.2.0 with Python >= 3.8
Version 2.6.0 with Python < 3.8
2020-04-27 12:54:17 +09:30
grossmj
3ec068f0cb Use Environmental Markers to force jsonschema version 2.6.0 on Windows/macOS. Ref https://github.com/GNS3/gns3-gui/issues/2849 2020-04-27 12:43:07 +09:30
grossmj
37f1fcf6f7 Remove preferences dialog geometry restoration. Fixes #2807 2020-04-27 11:55:01 +09:30
grossmj
c51dd1605d Merge branch '2.3'
# Conflicts:
#	gns3/version.py
2020-04-13 11:57:04 +09:30
grossmj
4ebf3b4e1c Development on 2.2.8dev1 2020-04-08 01:26:42 +09:30
grossmj
b1ec9d535c Release v2.2.7 2020-04-08 00:03:13 +09:30
grossmj
7fc9087cf0 Fix unable to configure custom adapters for Qemu VMs. Fixes #2961 2020-04-07 15:47:53 +09:30
Bernhard Ehlers
5dc2c77806 QEMU config disk - enable QEMU config import/export
(cherry picked from commit d01f15c4df)
2020-04-06 13:42:00 +02:00
grossmj
4972d460d2 Fix tests. 2020-04-06 21:09:47 +09:30
grossmj
c388836be7 Fix VNC console template doesn't extract %i (Project UUID). Fixes #2960 2020-04-06 18:34:37 +09:30
grossmj
18ae4a6ce9 Fix contextual menu issues. Ref #2955 2020-03-30 21:37:52 -07:00
grossmj
3020e1fc9f Downgrade to PyQt 5.12.3 Ref #2955 #2952 2020-03-29 18:18:53 +10:30
grossmj
fe2f8424db Downgrade to PyQt 5.13.2 Ref #2955 #2952 2020-03-29 14:46:34 +10:30
grossmj
a744f65199 Merge branch 'master' into 2.3
# Conflicts:
#	gns3/version.py
2020-03-28 13:44:08 +10:30
grossmj
d27578f0fc Release v2.2.6 2020-03-26 12:37:59 +10:30
grossmj
b01c11f19b Prevent locked drawings to be deleted. Fixes https://github.com/GNS3/gns3-gui/issues/2948 2020-03-16 16:30:09 +10:30
grossmj
fb269da4d3 Fix issues with empty project variables. Fixes https://github.com/GNS3/gns3-gui/issues/2941 2020-03-14 17:22:44 +10:30
grossmj
ab15f96bb5 Upgrade psutil to version 5.6.6 due to CVE-2019-18874
https://github.com/advisories/GHSA-qfc5-mcwq-26q8
2020-03-14 15:47:12 +10:30
grossmj
5bb8b8e8bd Use existing README.txt if existing when exporting portable project. Fixes https://github.com/GNS3/gns3-server/issues/1724 2020-03-10 17:32:13 +10:30
grossmj
3f9632fae0 Allow creation of a diskless Qemu VMs. Fixes #2939 2020-03-10 17:04:07 +10:30
grossmj
b5f8195abb Re-enable "create new version" in appliance wizard. Fixes #2837 2020-03-03 13:11:01 +08:00
grossmj
73a293bd17 Fix unable to load project from project library. Fixes #2932 2020-03-03 09:34:45 +08:00
grossmj
0a1dfb99e9 Merge remote-tracking branch 'origin/2.2' into 2.2 2020-02-19 14:13:16 +08:00
grossmj
d352919264 Fix some permission denied errors when loading remote project. Ref #2871 Fixes #2901 2020-02-19 14:13:03 +08:00
Jeremy Grossmann
65f2a1e461 Merge pull request #2931 from inthought/2.2
Add 'Royal TS V5' to predefined console list
2020-02-18 13:29:46 +10:30
Travis Abram
71f289721b Add 'Royal TS V5' to predefined console list 2020-02-16 20:46:40 -08:00
grossmj
c28089d400 Disallow invalid grid sized. Fixes #2908 2020-02-10 16:59:17 +08:00
grossmj
64f009bf71 Check if hostname is blank. Fixes #2924 2020-01-25 18:21:02 +08:00
Jeremy Grossmann
edb2fd7fd9 Merge pull request #2925 from GNS3/qemu-changes
GUI changes to support recent versions of Qemu
2020-01-25 16:04:54 +07:00
grossmj
62e7ad8c8a Add nvme disk interface and fix scsi disk interface for Qemu VMs. 2020-01-25 16:22:34 +08:00
grossmj
caeb5d71c3 Add latest Qemu nic models. 2020-01-24 19:05:46 +08:00
grossmj
cfe96b2311 Upgrade Qt version to 5.14.1. Ref #2778 #2903 2020-01-24 17:47:01 +08:00
grossmj
8955b9ee29 Upgrade to PyQt 5.14.1. Ref #2778 2020-01-22 17:53:04 +08:00
grossmj
e727abf27a Change version to 2.3.0dev1 on 2.3 branch 2020-01-16 18:06:51 +08:00
grossmj
f209bf7644 Development on 2.2.6dev1 2020-01-10 00:32:10 +08:00
grossmj
5860dedc32 Release v2.2.5 2020-01-09 23:52:40 +08:00
grossmj
9e2df17a4e Add gns3-gui.xml and update Linux icons paths & permissions. Ref #2919 2020-01-09 23:49:44 +08:00
grossmj
a95761437a Development on 2.2.5dev1 2020-01-09 05:17:01 +08:00
grossmj
626510865f Update paths to icons for Linux 2020-01-09 04:19:21 +08:00
grossmj
2e248aa340 Release v2.2.4 2020-01-09 00:45:09 +08:00
grossmj
e306f73f01 Fix "Console to all nodes" doesn't open cloud objects with console configured. Fixes #2902 2020-01-08 00:35:57 +08:00
grossmj
0c4367d77e Change default path for SecureCRT. Fixes #2896 2019-12-26 06:13:23 +08:00
grossmj
6dda0ff787 Add icons in setup.py Ref #2898 2019-12-26 06:04:40 +08:00
grossmj
d7d4b84309 Add remote viewer as a VNC console for Linux. Fixes #2913 2019-12-26 04:13:02 +08:00
grossmj
7b57983699 Development on 2.2.4dev1 2019-11-12 16:43:21 +08:00
grossmj
bb89fe2275 Release v2.2.3 2019-11-12 15:29:54 +08:00
grossmj
7eb2a923b2 Fix issue when binding on 0.0.0.0. Fixes #2892 2019-11-11 17:49:09 +08:00
grossmj
58052e3cce Allow double click on cloud with configured console to open session. Fixes #2894 2019-11-11 14:31:35 +08:00
grossmj
e431104f6b Officially support Python 3.8. Ref https://github.com/GNS3/gns3-gui/issues/2895 2019-11-11 12:56:11 +08:00
grossmj
a4e9d6b8ce Set psutil to version 5.6.3 in requirements.txt 2019-11-08 10:44:17 +08:00
grossmj
f58f5c7b95 Developement version on 2.2.3dev1 2019-11-04 19:45:18 +08:00
grossmj
37faa39309 Release v2.2.2 2019-11-04 18:33:29 +08:00
grossmj
4d64598ed2 Fix KeyError: 'spice+agent'. Fixes #2890 2019-11-03 15:19:18 +08:00
grossmj
5132c4e172 Fix wrong log.error() call when exporting file. 2019-11-02 23:19:04 +08:00
grossmj
3c3fdd9ffd Revert "Explicitly cleanup the cache directory."
This reverts commit 8095fef228.
2019-11-02 15:47:24 +08:00
grossmj
efa50571c6 Fix "UnboundLocalError: local variable 'pywintypes' referenced before assignment" 2019-11-02 15:45:16 +08:00
grossmj
ca9b10fcca Fix version string. 2019-11-02 15:27:28 +08:00
grossmj
8660161b10 Fix GUI uses only telnet console. Fixes #2885 2019-11-02 02:23:13 +08:00
grossmj
50ebfb9c06 Fix missing sys module in sudo.py Fixes #2886 2019-11-02 02:06:33 +08:00
grossmj
26df59d6b6 Development on 2.2.2dev1 2019-11-01 18:43:36 +08:00
grossmj
b903e2ad73 Release v2.2.1 2019-11-01 17:53:20 +08:00
grossmj
b2fe7eb643 Check if console_type is None. 2019-11-01 17:47:26 +08:00
grossmj
8095fef228 Explicitly cleanup the cache directory. 2019-11-01 17:46:53 +08:00
grossmj
b8da5440f5 Get Windows interface from registry if cannot load win32com module. 2019-11-01 17:44:47 +08:00
grossmj
6cea094e4e Ignore OSError returned by psutil when bringing console to front. 2019-11-01 17:44:06 +08:00
grossmj
9ac46c9d50 Catch error if NPF or NPCAP service cannot be detected. Ref https://github.com/GNS3/gns3-server/issues/1670 2019-10-30 17:59:19 +08:00
Dominic
c8a8663ff0 Restore editReadme attribute which was removed in Change 'New export project wizard' ( ID c2472bcb22 ) 2019-10-18 17:11:28 +02:00
Dominic
d27e5c1795 Revert "Remove unused edit readme action. Fixes #2816"
This reverts commit 7cd0187f33.
2019-10-18 16:46:48 +02:00
Dominic
0d2f91709c Updated GUI pyqt files from Tab Order 'fixes' in "Tab Order in Preferences and Project Dialog #2872" 2019-10-18 16:45:39 +02:00
grossmj
6dc44d5108 Better handling for reading synchronous JSON response from server. Ref #2874 2019-10-17 12:45:40 +08:00
grossmj
9c6be0341b Fix tests. 2019-10-17 12:34:34 +08:00
grossmj
011a49e998 Fix JSONDecodeError when getting server version. Fixes #2874 2019-10-17 12:31:15 +08:00
grossmj
e18c2df5f5 Fix FileNotFoundError exceptions when launching SPICE or VNC clients. 2019-10-17 12:19:55 +08:00
grossmj
1794b8389f Fix UnboundLocalError local variable 'win32serviceutil' referenced before assignment 2019-10-17 12:12:46 +08:00
grossmj
0379c370eb Merge remote-tracking branch 'remotes/origin/master' into 2.2 2019-10-15 23:36:49 +08:00
Jeremy Grossmann
e03550a89b Merge pull request #2872 from fatoms/Tab_Order
Tab Order in Preferences and Project Dialog
2019-10-15 22:35:53 +07:00
Dominic
c6ea775e81 'Fix' tab order in preferences dialog so it follows the layout 2019-10-12 22:06:30 +02:00
Dominic
38233ba5e9 'Fix' tab order in edit project dialog so it follows the layout 2019-10-12 22:05:52 +02:00
grossmj
89c1272bc1 Use compatible shlex_quote to handle case where Windows needs double quotes around file names, not single quotes. Ref https://github.com/GNS3/gns3-gui/issues/2866 2019-10-09 17:02:30 +08:00
grossmj
8bbb46c599 Use 0.0.0.0 by default for server host. Fixes https://github.com/GNS3/gns3-server/issues/1663 2019-10-09 16:35:42 +08:00
grossmj
74fca3d736 Set default host to "localhost". Fixes https://github.com/GNS3/gns3-server/issues/1663 2019-10-08 18:28:11 +08:00
grossmj
7aeed7aa59 Catch IndexError when configuring port names. Fixes #2865 2019-10-08 16:15:36 +08:00
grossmj
aa15ace887 Bump version to 2.2.1dev1 2019-10-08 16:05:37 +08:00
grossmj
2d0a7b5f58 Release v2.2.0 2019-09-30 16:24:26 +08:00
grossmj
20a09b56c1 Merge branch 'master' into 2.2
# Conflicts:
#	gns3/version.py
2019-09-24 14:07:38 +08:00
grossmj
1938cdabae Bump version to 2.2.0dev18 2019-09-24 14:02:36 +08:00
grossmj
8d1bff782c Release v2.2.0rc5 2019-09-09 15:06:14 +07:00
grossmj
4e3eee2383 Adjust size for setup dialog and remove question about running the wizard again. Ref #2846 2019-09-07 23:46:02 +07:00
grossmj
da8aa0d2fd Release v2.2.0rc4 2019-08-30 15:23:32 +07:00
grossmj
5b4481c43a Fix issue when asking to run the setup wizard again. Ref #2846 2019-08-29 15:59:40 +07:00
grossmj
593cb8c1fd Remove warning about VirtualBox not supporting nested virtualization. Ref https://github.com/GNS3/gns3-server/issues/1610 2019-08-27 17:28:44 +07:00
grossmj
210cf63fe2 Ask user if they want to see the wizard again. Ref #2846 2019-08-27 16:15:50 +07:00
grossmj
3b178013c0 Bump version to 2.2.0dev17 2019-08-23 18:20:44 +07:00
grossmj
6e44d6b919 Merge branch 'master' into 2.2
# Conflicts:
#	gns3/version.py
2019-08-20 17:35:13 +07:00
grossmj
6b520b8036 Bump version to 2.2.0dev16 2019-08-20 17:33:48 +07:00
grossmj
803782b9d8 Release v2.2.0rc3 2019-08-11 19:14:56 -07:00
grossmj
d3d6ca3f2e Revert to jsonschema 2.6.0 due to packaging problem. 2019-08-11 19:11:41 -07:00
grossmj
f545c793f8 Release v2.2.0rc2 2019-08-10 12:04:19 -05:00
grossmj
47d6a4fef6 Release v2.2.0rc1 2019-08-10 11:42:13 -05:00
grossmj
8862b608cf Bump jsonschema to version 3.0.2 2019-08-09 13:47:58 -05:00
grossmj
76832ab83f Fix "Unable to change Remote Main Server IP". Fixes #2823 2019-08-02 17:23:31 -02:30
grossmj
fed245fd34 Fix "AttributeError: 'QGraphicsTextItem' object has no attribute 'locked'". Fixes #2814 2019-07-30 15:50:40 -02:30
grossmj
3e0f1affd0 Merge branch '2.2' 2019-07-12 12:07:33 +02:00
grossmj
2110c2805e Development on 2.2.0dev15 2019-07-11 17:34:56 +02:00
grossmj
46cfdd8314 Release v2.2.0b4 2019-07-11 16:58:35 +02:00
grossmj
f8f648c2b6 Fix issue preventing to open the QFileDialog in the correct directory. 2019-07-11 16:50:59 +02:00
grossmj
7cd0187f33 Remove unused edit readme action. Fixes #2816 2019-07-10 12:10:17 +02:00
grossmj
4d8f362f11 Remove deprecated Qemu parameter to run legacy ASA VMs. Fixes #2827 2019-07-10 11:33:04 +02:00
grossmj
469eaa4737 Upload images on remote controller. Fixes #2828 2019-07-10 11:23:29 +02:00
grossmj
c921224b30 Preferences dialog: send API request only if connected to controller 2019-07-05 18:07:48 +02:00
grossmj
61487b2e2f Fix AttributeError: 'QGraphicsTextItem' object has no attribute 'locked'. Fixes #2814 2019-06-24 15:29:07 +02:00
grossmj
9affca495e Fix KeyError: 'chassis' when converting old IOS templates. Fixes #2813 2019-06-24 15:14:20 +02:00
grossmj
9d8886a640 Development on 2.2.0dev14 2019-06-15 16:38:06 +02:00
grossmj
98cfec1b77 Release v2.2.0b3 2019-06-15 15:39:32 +02:00
grossmj
aed174953e Merge 2.1 into 2.2 branch. 2019-06-15 15:26:20 +02:00
grossmj
f0feea8262 Fix template migration issues from GUI to controller. Fixes https://github.com/GNS3/gns3-gui/issues/2803 2019-06-15 12:52:50 +02:00
grossmj
e2aeaf0a78 Development on 2.1.22dev1 2019-06-14 19:42:18 +02:00
grossmj
b92bb94875 Release v2.1.21 2019-06-14 10:47:08 +02:00
grossmj
c56db59353 Increase timeout from 2 to 5 seconds for synchronous check. Ref #2805 2019-06-10 22:20:40 +02:00
grossmj
a87c4e21d7 %guest-cid% variable implementation for Qemu VMs. Fixes https://github.com/GNS3/gns3-gui/issues/2804 2019-06-04 18:00:44 +02:00
grossmj
ed99a989d7 Fix "General Preferences dialog displays misleading information". Fixes #2801 2019-06-04 17:05:01 +02:00
grossmj
f9a4c9399a Increase timeout from 2 to 5 seconds for synchronous check. Ref #2805 2019-05-31 09:17:34 +02:00
grossmj
efb5c8ca9a Development on 2.2.0dev13 2019-05-29 17:52:38 +07:00
grossmj
0946dff3a0 Release v2.2.0b2 2019-05-29 17:16:59 +07:00
grossmj
d7d96b10e5 Merging 2.1 into 2.2 branch 2019-05-29 16:50:36 +07:00
grossmj
0c0b2d5cb3 Development on 2.1.21dev1 2019-05-29 16:37:43 +07:00
grossmj
450fbc9af3 Release v2.1.20 2019-05-29 15:44:25 +07:00
grossmj
469ee8fab8 Fix KeyError: 'endpoint' issue. Fixes #2802 2019-05-28 23:17:55 +07:00
grossmj
6ccfcaf76e Development on 2.1.20dev1 2019-05-28 16:33:43 +07:00
grossmj
520e857874 Release v2.1.19 2019-05-28 15:23:35 +07:00
grossmj
012c7b4241 Fix wrong aligment of symbols in saved/exported projects. Fixes #2800 2019-05-27 16:33:51 +07:00
grossmj
1d71cd5bf0 Replace urllib.request by Qt implementation for local server synchronous check. Fixes #2793 2019-05-27 16:03:55 +07:00
grossmj
17d1a7f4ed Support snapshots for portable projects. Fixes https://github.com/GNS3/gns3-gui/issues/2792 2019-05-27 15:35:47 +07:00
grossmj
0cd5c08c6b Fix event notification problem for projects and how snapshots are restored. 2019-05-27 15:24:36 +07:00
grossmj
20ac503fe9 Do not close the nodes dock widget when creating project. 2019-05-26 15:20:53 +07:00
grossmj
5f737c2c7c Fix no scan for images on remote controller. Fixes #2799 2019-05-26 15:12:22 +07:00
grossmj
eb1a37be36 Remove problematic tests. 2019-05-25 17:49:33 +07:00
grossmj
07c64b5432 Use QNetworkAccessManager to download custom appliance symbols. 2019-05-25 16:25:02 +07:00
grossmj
ce981d1c49 Experimental auto upgrade should not be available for "frozen" app. Fixes #2797 2019-05-25 15:17:23 +07:00
grossmj
32a9f2556e Use QNetworkAccessManager for synchronous local server check. Ref #2793
Remove unused code.
2019-05-25 15:04:37 +07:00
grossmj
7f08675121 Merging 2.2 into master 2019-05-24 15:27:07 +07:00
grossmj
1dc3c13df2 Don't allow link labels to be moved for locked nodes. Fixes #2794 2019-05-23 15:10:40 +07:00
grossmj
6a6e86b325 Merge 2.1 into 2.2 branch 2019-05-23 14:51:53 +07:00
grossmj
d96277882a Set grid's minimum to 5. Fixes #2795 2019-05-23 14:41:53 +07:00
grossmj
ecec917752 Development on 2.1.19dev1 2019-05-23 14:37:37 +07:00
grossmj
ea9c1a8ee1 Release v2.1.18 2019-05-22 16:13:28 +07:00
grossmj
cfbb09fb57 Fix error in HTTPConnection.request for Python3.6. Fixes #2793 2019-05-22 16:05:34 +07:00
grossmj
dc8aa1fb92 Catch more OSError/PermissionError when checking md5 on remote images. Fixes #2582 2019-05-22 15:23:56 +07:00
grossmj
786cc8aa65 Fix exception when grid size is 0. Fixes #2790 2019-05-22 15:13:16 +07:00
grossmj
4a353e08e3 Catch PermissionError when scanning local image directories. Fixes #2791 2019-05-22 14:55:07 +07:00
grossmj
1371921586 Development on 2.2.0dev12 2019-05-21 19:16:19 +07:00
grossmj
cd8696a714 Release v2.2.0b1 2019-05-21 15:26:54 +07:00
grossmj
17799719d6 Merge branch '2.1' into 2.2 2019-05-21 15:16:19 +07:00
grossmj
2a59013604 Revert "Make sure the latest PyQt5 version 5.12.x is used on Windows." Ref #2778 2019-05-20 12:01:16 +07:00
grossmj
1c46299dd9 Change behavior when an IOU license is verified. Fixes https://github.com/GNS3/gns3-server/issues/1555 2019-05-20 10:51:25 +07:00
grossmj
628d7cb909 Fix cannot load new profile. Fixes #2784 2019-05-19 16:33:33 +07:00
grossmj
b23c92c0fb Fix Docker extra volumes support 2019-05-19 14:26:03 +07:00
Jeremy Grossmann
49ce5a9f38 Merge pull request #2775 from kazkansouh/2.2-docker-volumes
Custom persistent docker volumes
2019-05-18 20:17:20 +07:00
Jeremy Grossmann
4575ea9f6d Merge pull request #2789 from GNS3/update-dockerfile
Update Dockerfile to Ubuntu 18.04
2019-05-18 20:10:31 +07:00
grossmj
fd6a00df6a Update Dockerfile to Ubuntu 18.04 2019-05-18 20:03:04 +07:00
grossmj
58ab4b424a Fix remote packet capture when controller is also remote. Fixes #2785 2019-05-18 17:33:34 +07:00
grossmj
1ea1abf582 Set console type to "none" by default for Ethernet switches and add a warning if trying to use "telnet". Fixes https://github.com/GNS3/gns3-gui/issues/2776 2019-05-18 14:28:20 +07:00
grossmj
e8caab74f4 Bump version to 2.2.0dev11 2019-05-18 14:11:07 +07:00
grossmj
9fce393fd1 Add tooltip for symbol theme support in general preferences. Fixes #2770 2019-05-18 14:01:08 +07:00
grossmj
827c11ae97 Merge remote-tracking branch 'origin/2.2' into 2.2 2019-05-18 13:45:57 +07:00
grossmj
eb370d5672 Merge 2.1 branch into 2.2 2019-05-18 13:45:39 +07:00
grossmj
7732aaf9a5 Release v2.1.17 2019-05-17 15:10:28 +07:00
Karim Kanso
63161eb760 Minor ui tweak to align extra hosts text edit look and feel with extra volume text edit. 2019-04-22 13:03:23 +01:00
Karim Kanso
5dba814d1b Support for persistent docker volumes to be configured via ui (requires corresponding commit on gns3-server) 2019-04-22 11:09:28 +01:00
Jeremy Grossmann
aecdc71f3a Merge pull request #2772 from GNS3/pyup-update-pytest-4.4.0-to-4.4.1
Update pytest to 4.4.1
2019-04-16 20:04:42 +07:00
pyup-bot
3209c1d0e6 Update pytest from 4.4.0 to 4.4.1 2019-04-16 03:33:58 +02:00
grossmj
2b3fb53ef2 Release v2.2.0a5 2019-04-15 17:05:20 +07:00
grossmj
cbbbece0e5 Revert "Drop old Qemu support (Windows and macOS) and legacy ASA support." Ref https://github.com/GNS3/gns3-server/issues/1579
This reverts commit 3e47267e35.
2019-04-15 15:56:01 +07:00
grossmj
56d742b19f Merge 2.1 into 2.2 2019-04-15 15:54:08 +07:00
grossmj
1f566a31cf Development on 2.1.17dev1 2019-04-15 12:41:41 +07:00
grossmj
10d75e15da Release v2.1.16 2019-04-15 12:00:18 +07:00
grossmj
17def7e00a Do not make NPF or NPCAP service mandatory to start the local server on Windows. 2019-04-15 10:33:27 +07:00
grossmj
106afd0987 Do not try to upload a local image that is already installed on the local server. 2019-04-15 00:29:43 +07:00
grossmj
bba9c5e1d8 Back to the major.minor version for config files. Ref https://github.com/GNS3/gns3-gui/issues/2756 2019-04-14 21:31:41 +07:00
grossmj
ae8e8013d4 Some adjustments with compute WebSocket handling. Ref https://github.com/GNS3/gns3-server/issues/1564 2019-04-14 16:48:12 +07:00
grossmj
3a5f1d60f9 Fix AttributeError: 'GraphicsView' object has no attribute '_import_config_dir'. Fixes #2768 2019-04-13 18:45:16 +07:00
grossmj
3f6eb61382 Do not try to lock a SvgIconItem. Fixes #2766 2019-04-13 18:40:54 +07:00
grossmj
32bfff381d Merge 2.1 into 2.2 2019-04-13 18:11:41 +07:00
grossmj
f68a8ea829 Fix OverflowError error with progress dialog. Fixes #2767 2019-04-13 17:38:43 +07:00
grossmj
50066b2f12 More fixes for stuck progress window. Fixes #2765 2019-04-13 17:10:24 +07:00
grossmj
21a99d4376 Fix adding multiple devices - stuck progress window. Fixes #2765 2019-04-13 17:04:23 +07:00
grossmj
f97d3041b8 Make sure the latest PyQt5 version 5.12.x is used on Windows. 2019-04-13 15:43:23 +07:00
grossmj
31d6a065b0 Show a warning when a config export is not supported. Ref #2762 2019-04-11 15:32:22 +07:00
grossmj
20bf63dbbf Prevent locked nodes to be deleted. Fixes https://github.com/GNS3/gns3-gui/issues/2764 2019-04-10 15:43:52 +07:00
grossmj
1c3e0ef640 Fix default telnet console command. 2019-04-09 21:18:55 +07:00
grossmj
5b58d3ab6d Bump version to 2.2.0dev10 2019-04-09 19:20:21 +07:00
grossmj
554c9205f3 Add PuTTY 0.71 and mark GNS3 PuTTY as deprecated. Fixes #2758 2019-04-09 19:19:56 +07:00
grossmj
543a8e7c33 Fix bug with IOS platform detection. Fixes #2760 2019-04-09 16:24:07 +07:00
grossmj
69ef35c674 Development on 2.2.0dev9 2019-04-05 22:01:35 +08:00
grossmj
45102a07b6 Release v2.2.0a4 2019-04-05 19:10:04 +08:00
grossmj
f0b8b22e8a Use the full version number for path to config files. Ref https://github.com/GNS3/gns3-gui/issues/2756 2019-04-05 18:44:31 +08:00
grossmj
d94f5a2d8c Fix error message when shutting down GUI without a started server. 2019-04-01 21:08:17 +07:00
grossmj
a768661c05 Fix remote packet capture and make sure packet capture is stopped when deleting an NIO. Fixes https://github.com/GNS3/gns3-gui/issues/2753 2019-04-01 19:47:32 +07:00
grossmj
4657b005b6 Restore migrate old settings. 2019-04-01 16:20:26 +07:00
grossmj
e71da830b0 Merge remote-tracking branch 'origin/2.2' into 2.2 2019-04-01 15:53:59 +07:00
grossmj
ebf2563200 Store config files in version specific location 2019-04-01 15:53:39 +07:00
Jeremy Grossmann
e8eaa00244 Merge pull request #2755 from GNS3/pyup-update-pytest-4.3.1-to-4.4.0
Update pytest to 4.4.0
2019-04-01 12:00:43 +07:00
pyup-bot
d750e7a427 Update pytest from 4.3.1 to 4.4.0 2019-04-01 06:53:29 +02:00
grossmj
bfc8adc904 Fix error messages on closing GNS3 application. Fixes https://github.com/GNS3/gns3-gui/issues/2750 2019-03-30 17:20:15 +07:00
grossmj
4de38ea590 Fix bug when list of files for an appliance is not displayed. 2019-03-30 15:44:30 +07:00
ziajka
cc0c6d0a7a Update 'local' to 'bundled' in server & gui, Fixes: #1561 2019-03-27 11:56:32 +01:00
grossmj
d1d0810233 Development on 2.2.0dev8 2019-03-25 23:44:19 +08:00
grossmj
ee3c758bb7 Release v2.2.0a3 2019-03-25 19:35:22 +08:00
grossmj
8f077456b1 Development on 2.1.16dev1 2019-03-21 13:56:11 +08:00
grossmj
a29f3e35c0 Release v2.1.15 2019-03-21 11:41:44 +08:00
grossmj
b12cb5c939 Fix bug when changing symbol. Fixes #2740 2019-03-20 15:15:29 +08:00
grossmj
ba646f5efa Fix image upload tests, second try. 2019-03-18 17:34:26 +07:00
grossmj
edafc29cdc Fix image upload tests. 2019-03-18 17:19:23 +07:00
grossmj
5aa67d18c0 Fix issue when images are not uploaded from appliance wizard. Ref https://github.com/GNS3/gns3-gui/issues/2738 2019-03-18 15:33:37 +07:00
grossmj
8067aaadd4 Development on 2.2.0dev7 2019-03-14 23:27:11 +07:00
grossmj
4a012c4d88 Release v2.2.0a2 2019-03-14 17:09:53 +07:00
grossmj
7f234aa648 Try to handle stacked widget layout differently. Ref #2605 2019-03-13 15:46:41 +07:00
Jeremy Grossmann
dbbcdf0f73 Merge pull request #2735 from GNS3/pyup-update-pytest-4.3.0-to-4.3.1
Update pytest to 4.3.1
2019-03-13 11:43:19 +07:00
pyup-bot
a6c56a0963 Update pytest from 4.3.0 to 4.3.1 2019-03-13 00:37:53 +01:00
Jeremy Grossmann
466d427295 Merge pull request #2732 from GNS3/symbol-management-refactoring
Symbol management refactoring
2019-03-12 18:21:23 +07:00
grossmj
e5b8bdc106 Early support for symbol themes. 2019-03-12 18:13:33 +07:00
grossmj
25a6b6b3b1 Download custom appliance symbols from GitHub
Fix symbol cache issue. Ref https://github.com/GNS3/gns3-gui/issues/2671
Fix temporary directory for symbols was not deleted
Fix temporary appliance file was not deleted
2019-03-11 16:55:16 +07:00
Jeremy Grossmann
39723a2212 Merge pull request #2730 from GNS3/lock-unlock-items
Display available appliances in a hierarchical folder structure. Fixes #2702
2019-03-08 18:03:59 +07:00
grossmj
9cd0597879 Change the size of template list on the Preferences window to relative. Fixes #2605 2019-03-08 11:46:43 +07:00
grossmj
c2472bcb22 New export project wizard. 2019-03-07 17:38:27 +07:00
grossmj
b9caf7216a Update paths for binaries moved to the MacOS directory in GNS3.app 2019-03-04 16:07:04 +07:00
grossmj
6b23de94b0 Bump version to 2.2.0dev2 2019-03-04 14:48:57 +07:00
grossmj
ab1324ffba Prevent to change layer position for locked items. Ref #2679 2019-03-02 18:49:19 +07:00
grossmj
21bcfde8f3 Display available appliances in a hierarchical folder structure. Fixes #2702 2019-03-02 17:52:47 +07:00
Jeremy Grossmann
3616bd6c85 Merge pull request #2725 from GNS3/lock-unlock-items
Refactoring for locking/unlocking items
2019-03-02 16:44:22 +07:00
grossmj
740e9bab87 Handle locking/unlocking items independently from the layer position. 2019-03-02 16:26:41 +07:00
grossmj
198cf833e9 Stay with jsonschema 2.6.0 2019-03-01 17:26:23 +07:00
grossmj
21f5a64b07 Merge 2.1 into 2.2 2019-03-01 17:23:49 +07:00
grossmj
fc3781550a Development on 2.1.15dev1 2019-02-27 15:59:16 +07:00
Jeremy Grossmann
a9a2a541c0 Update gns3-feature-request.md 2019-02-27 15:46:57 +07:00
Jeremy Grossmann
8998c07e0e Update gns3-bug-report.md 2019-02-27 15:46:28 +07:00
Jeremy Grossmann
ba01a89af1 Update gns3-feature-request.md 2019-02-27 15:43:07 +07:00
Jeremy Grossmann
eae07d62ad Update gns3-bug-report.md 2019-02-27 15:42:21 +07:00
Jeremy Grossmann
23903cf0c9 Delete feature_request.md 2019-02-27 15:36:33 +07:00
Jeremy Grossmann
4d908fd855 Delete bug_report.md 2019-02-27 15:36:18 +07:00
Jeremy Grossmann
bb0e67be4f Update issue templates 2019-02-27 15:32:18 +07:00
grossmj
d285e62c04 Release v2.1.14 2019-02-27 14:58:52 +07:00
grossmj
44d70de687 Better description to why an appliance cannot be installed. 2019-02-27 14:51:12 +07:00
grossmj
752c516f82 Development on 2.1.14dev1 2019-02-26 18:09:56 +07:00
grossmj
e1ec6c5771 Merge remote-tracking branch 'origin/2.1' into 2.1 2019-02-26 16:43:27 +07:00
grossmj
e8308869d9 Release v2.1.13 2019-02-26 16:43:14 +07:00
Jeremy Grossmann
484c5abe9d Force jsonschema dependency to 2.6.0
This is to fix this issue when starting the (frozen) application on Windows:

```
  File "C:\Python36-x64\lib\site-packages\jsonschema\validators.py", line 505, in <module>
  File "C:\Python36-x64\lib\site-packages\jsonschema\_utils.py", line 57, in load_schema
  File "C:\Python36-x64\lib\pkgutil.py", line 634, in get_data
OSError: [Errno 34] Result too large: 'jsonschema\\schemas\\draft6.json'
```
2019-02-26 15:28:16 +07:00
grossmj
c85112978d Fix broken idle-pc support. Fixes #1515 2019-02-22 22:22:31 +07:00
grossmj
e57f6db9f0 Merge remote-tracking branch 'origin/2.2' into 2.2 2019-02-22 17:37:24 +07:00
grossmj
edee26c77c Merging 2.1 into 2.2 2019-02-22 17:36:59 +07:00
grossmj
fe222b873f Disable computer hibernation detection mechanism. Ref #2678 2019-02-22 17:04:12 +07:00
Jeremy Grossmann
1acf44de21 Merge pull request #2719 from GNS3/drop-old-qemu
Drop old Qemu support (Windows/macOS) and ASA legacy image support. Ref #1516
2019-02-20 17:48:29 +07:00
grossmj
f8bb6661dd Add some advice for request timeout message. Fixes #2652 2019-02-20 00:14:15 +07:00
grossmj
ac50dffabd Fix appliance to template tests. 2019-02-19 23:29:20 +07:00
grossmj
fbb28a4325 Remove -nographic Qemu option when importing appliance. 2019-02-19 23:20:21 +07:00
grossmj
3e47267e35 Drop old Qemu support (Windows and macOS) and legacy ASA support. 2019-02-19 23:14:19 +07:00
grossmj
0f9aab9230 Merge remote-tracking branch 'origin/2.1' into 2.1 2019-02-19 16:07:51 +07:00
grossmj
a5cf5e16b7 Show/Hide interface labels when status points are not shown. Fixes #2690 2019-02-19 16:07:39 +07:00
Jeremy Grossmann
7f8269bb44 Merge pull request #2717 from GNS3/pyup-update-pytest-4.1.1-to-4.3.0
Update pytest to 4.3.0
2019-02-19 15:56:28 +07:00
Jeremy Grossmann
097458d108 Merge pull request #2715 from GNS3/critical-messages-before-running
Show critical messages before the main window runs. Fixes #2710
2019-02-19 15:19:53 +07:00
pyup-bot
2e0ce6afe0 Update pytest from 4.1.1 to 4.3.0 2019-02-19 04:26:58 +01:00
grossmj
f4cafac9c7 Do not print critical message twice on stderr.
Replace QMessageBox calls with no parent by log.error()/log.warning().
2019-02-18 22:09:23 +08:00
grossmj
7f132fdc36 Show critical messages before the main window runs. 2019-02-18 11:22:13 +08:00
grossmj
6b7d629755 Avoid using PyQt5.Qt, which imports unneeded stuff. Fixes #2592 2019-02-16 15:05:42 +08:00
grossmj
b7ccc37ea5 Fix SIP import error with recent PyQt versions. Fixes #2709 2019-02-16 14:38:44 +08:00
Jeremy Grossmann
bbe2826c77 Upgrade to Qt 5.12. Fixes #2636 2019-02-12 11:55:09 +08:00
grossmj
dda0447839 Release v2.2.0a1 2019-01-29 14:39:42 +08:00
grossmj
9398dd0840 Resize some more dialogs. 2019-01-29 11:44:15 +08:00
grossmj
6e3c5c1bb8 Resize some dialogs. 2019-01-28 18:01:52 +08:00
grossmj
a83208178b Fix default NAT interface not restored on Windows. Fixes #2681 2019-01-28 15:39:35 +08:00
grossmj
f1b7c0e176 Fix tests. 2019-01-28 15:24:40 +08:00
grossmj
429c2ab650 Merge and improvements to the setup wizard. Fixes #2676. 2019-01-28 15:13:37 +08:00
grossmj
68e2a0ee39 Adjust the setup wizard (VMware image size, layouts). 2019-01-27 22:44:56 +08:00
Jeremy Grossmann
b27c024449 Merge pull request #2684 from GNS3/refactor-appliance-wizard
Additional improvements for the appliance wizard. Fixes #2224
2019-01-25 15:27:31 +08:00
grossmj
7bbd337801 Refactor appliance wizard. 2019-01-25 14:31:37 +08:00
grossmj
7c545e3860 Natural sorting support for custom adapters tree widget. 2019-01-24 16:14:20 +08:00
grossmj
5b6491a23f Add the word "template" to configuration dialog titles. 2019-01-24 15:56:50 +08:00
grossmj
12e4f8445d Reorder node contextual menu. 2019-01-24 14:57:01 +08:00
grossmj
52418ed94a Development on 2.1.13dev1 2019-01-23 15:25:48 +08:00
grossmj
a1496bffd4 Release 2.1.12 2019-01-23 15:22:26 +08:00
Jeremy Grossmann
911f6305fa Merge pull request #2677 from GNS3/svg-symbols-fixes
Resize SVG node symbols that are too big. Fixes #2674
2019-01-22 22:25:13 +07:00
grossmj
c6594d4845 Checkbox to activate/deactivate the size limit of node symbols. 2019-01-22 22:16:45 +07:00
grossmj
538adc4817 Option to limit the size of node symbols (activated by default). Ref #2674.
(cherry picked from commit 6b38b58633)
2019-01-22 00:28:06 +07:00
grossmj
961c5652ea Resize SVG node symbol only when height is above 80px. Ref #2674
Work on str instead of binary when resizing SVG symbol.

(cherry picked from commit 938e9129cd)
2019-01-22 00:24:30 +07:00
grossmj
c0ecf3ccc4 Automatically resize SVG symbols that are too big. Ref #2674.
(cherry picked from commit 8f381a4720)
2019-01-22 00:24:11 +07:00
grossmj
33bc644688 Resize some dialogs. 2019-01-21 18:19:04 +07:00
grossmj
6b38b58633 Option to limit the size of node symbols (activated by default). Ref #2674. 2019-01-21 18:11:26 +07:00
grossmj
938e9129cd Resize SVG node symbol only when height is above 80px. Ref #2674
Work on str instead of binary when resizing SVG symbol.
2019-01-21 17:22:03 +07:00
grossmj
8f381a4720 Automatically resize SVG symbols that are too big. Ref #2674. 2019-01-21 16:41:46 +07:00
grossmj
c1fd434f75 Bigger new template wizard. 2019-01-17 18:37:07 +07:00
grossmj
2440faf3f5 Fix DeprecationWarning: invalid escape sequence. Fixes https://github.com/GNS3/gns3-gui/issues/2670 2019-01-17 18:01:58 +07:00
grossmj
0bd480eabb Use theme icons in other contextual menus. Fixes #2669 2019-01-17 17:34:30 +07:00
grossmj
dc3d762799 Resize new template dialog. Ref #2671 2019-01-16 19:31:03 +07:00
Jeremy Grossmann
1d139cee4d Merge pull request #2668 from GNS3/new_appliance_installation
Template creation from appliance. Fixes #2642
2019-01-14 17:25:17 +07:00
grossmj
d033268cd9 Change some text regarding appliance installation. 2019-01-14 17:19:37 +07:00
grossmj
82fdeb3a49 Handle errors when creating template from appliance. 2019-01-14 16:45:58 +07:00
grossmj
3462109ef2 Template creation from an appliance. 2019-01-14 16:14:31 +07:00
grossmj
b6e5a588bf Basic support to create new template from appliance. 2019-01-13 15:23:14 +07:00
Jeremy Grossmann
4e2a80e379 Merge pull request #2667 from GNS3/pyup-update-pytest-4.0.2-to-4.1.1
Update pytest to 4.1.1
2019-01-13 12:54:08 +07:00
pyup-bot
fc61079132 Update pytest from 4.0.2 to 4.1.1 2019-01-12 22:56:48 +01:00
grossmj
f48f4eacd2 Fix race condition when trying to automatically open a console and the project is already running. Fixes #1493. 2019-01-12 16:08:21 +07:00
grossmj
92e2920212 Fix issue with IOS c7200 templates and usage variable. 2019-01-12 12:30:20 +07:00
grossmj
ebb2d8bb73 Add usage instructions to node tooltip. Ref #2662. 2019-01-10 15:02:41 +08:00
grossmj
ade748c3b1 Smaller node info dialog. 2018-12-30 21:51:51 +07:00
grossmj
ec334508a6 New node information dialog to display general, usage and command line information.
Ref https://github.com/GNS3/gns3-gui/issues/2662 https://github.com/GNS3/gns3-gui/issues/2656
2018-12-30 19:35:25 +07:00
grossmj
ed88eaa620 Support "usage" field for Dynamips, IOU, VirtualBox and VMware. Fixes https://github.com/GNS3/gns3-gui/issues/2657 2018-12-21 16:54:13 +08:00
grossmj
524f911293 Add "new template" entry to File menu. Fixes #2658 2018-12-21 16:07:06 +08:00
grossmj
fa9fc0ff8d Merge 2.1 into 2.2 branch. 2018-12-21 15:24:34 +08:00
grossmj
cf73db25b4 Update VMware banners and links. 2018-12-21 13:18:29 +08:00
grossmj
dd79939140 Allow users to refresh the template list in the nodes view panel. 2018-12-18 17:52:50 -06:00
grossmj
6d0afd39d7 Merge remote-tracking branch 'origin/2.2' into 2.2 2018-12-14 21:00:15 -06:00
grossmj
1d7a6611bd Fix bug with filter in add template. Fixes #2651. 2018-12-14 21:00:02 -06:00
Jeremy Grossmann
15aa4c6001 Merge pull request #2654 from GNS3/pyup-update-pytest-4.0.1-to-4.0.2
Update pytest to 4.0.2
2018-12-14 11:30:25 -06:00
pyup-bot
6f42208323 Update pytest from 4.0.1 to 4.0.2 2018-12-14 18:20:51 +01:00
grossmj
45b3c17c97 Remove typo. Ref #2648. 2018-12-13 22:37:00 -06:00
grossmj
1ddf3e6388 Fix Dynamips decompress doesn't work with relative images. Fixes #2648. 2018-12-13 22:32:06 -06:00
grossmj
d4f0f76e57 Merge branch '2.1' into 2.2 2018-11-30 12:37:25 +08:00
grossmj
e0c06ecd78 Fix missing method '_newApplianceActionSlot'. Fixes #2643. 2018-11-29 15:00:11 +07:00
Jeremy Grossmann
f839bbf877 Merge pull request #2641 from GNS3/naming-consistency
Review and apply consistent naming
2018-11-28 16:32:34 +07:00
grossmj
52c06f4730 Use "template" to name what we use to create new nodes. 2018-11-28 16:12:58 +07:00
grossmj
a8593bb39e Use project instead of topology where appropriate. 2018-11-27 18:30:16 +07:00
grossmj
396e871b3b Make sure nothing is named "compute server". 2018-11-27 18:14:51 +07:00
Jeremy Grossmann
ba9298735a Merge pull request #2640 from GNS3/kazkansouh-2.2-grid-new-project
Improved grid support
2018-11-27 16:34:03 +07:00
grossmj
f4bae20592 Use "node" instead of "appliance" for grid support. 2018-11-27 16:13:22 +07:00
Karim Kanso
189852862e Support for differing grid sizes for appliances and drawings. Requires corresponding commit on gns3-server. 2018-11-26 15:59:34 +00:00
Karim Kanso
ba59d69536 New projects can be created with show grid/snap to grid. 2018-11-26 15:13:39 +00:00
Jeremy Grossmann
26de22f105 Merge pull request #2597 from GNS3/pyup-update-pytest-pythonpath-0.7.2-to-0.7.3
Update pytest-pythonpath to 0.7.3
2018-11-24 16:11:43 +07:00
Jeremy Grossmann
d47b5040cf Merge branch '2.2' into pyup-update-pytest-pythonpath-0.7.2-to-0.7.3 2018-11-24 16:11:33 +07:00
Jeremy Grossmann
dcf133b297 Merge pull request #2634 from GNS3/pyup-update-pytest-4.0.0-to-4.0.1
Update pytest to 4.0.1
2018-11-24 15:24:49 +07:00
pyup-bot
b50fe81d86 Update pytest from 4.0.0 to 4.0.1 2018-11-24 09:20:07 +01:00
Jeremy Grossmann
1c8e166393 Update download URL for "Check For Update". 2018-11-23 16:28:59 +07:00
grossmj
6afdb18bdb Disallow changing layer of a locked object. Ref #2513. 2018-11-20 14:55:30 +07:00
grossmj
a454283357 Bump version to 2.2.0dev5 2018-11-20 14:37:38 +07:00
Jeremy Grossmann
9369ad9645 Merge pull request #2625 from GNS3/pyup-update-pytest-3.8.1-to-4.0.0
Update pytest to 4.0.0
2018-11-19 17:46:28 +07:00
Jeremy Grossmann
be997d4d25 Merge pull request #2627 from GNS3/pyup-update-pytest-timeout-1.3.1-to-1.3.3
Update pytest-timeout to 1.3.3
2018-11-19 17:46:09 +07:00
grossmj
d1b9185764 Cosmetic changes regarding appliances. 2018-11-19 14:37:33 +07:00
grossmj
2b98e48420 Fix issue when duplicating an appliance on GUI side. 2018-11-19 01:21:03 +07:00
grossmj
ec21134920 Fix issue to access configuration pages for Ethernet switch and hub appliances. 2018-11-18 00:00:17 +07:00
grossmj
9b73d652d3 Fix small bugs when using the new appliance management API. 2018-11-17 22:16:18 +07:00
grossmj
3c67b70ff3 Fix bug with custom adapters and categories for Docker VM. Fixes https://github.com/GNS3/gns3-gui/issues/2613 2018-11-17 21:50:00 +07:00
grossmj
60f58064b3 Fix bug with categories with Docker appliances. 2018-11-17 20:10:22 +07:00
pyup-bot
ca305cefa4 Update pytest-timeout from 1.3.1 to 1.3.3 2018-11-16 13:10:50 +01:00
Jeremy Grossmann
8ce928aec2 Merge pull request #2626 from GNS3/appliance-api
New appliance management API. Fixes #1427
2018-11-15 22:52:28 +07:00
grossmj
9ff8816273 Schema validation for appliance API. Ref #1427. 2018-11-15 17:28:17 +07:00
pyup-bot
42d5d4b542 Update pytest from 3.8.1 to 4.0.0 2018-11-15 00:56:49 +01:00
grossmj
2cf64a99de Remove generic controller settings API endpoint. 2018-11-14 16:24:30 +08:00
grossmj
7e942a7753 Fix tests. 2018-11-13 15:40:18 +08:00
grossmj
23d467f688 Working dedicated appliance management API. Ref https://github.com/GNS3/gns3-server/issues/1427 2018-11-13 14:59:18 +08:00
grossmj
fede614716 Base for dedicated appliance management API. Ref https://github.com/GNS3/gns3-server/issues/1427 2018-11-11 20:13:58 +08:00
grossmj
c31b5dd7a9 Bump version to 2.2.0dev4 2018-10-15 17:06:10 +07:00
grossmj
3ba811e675 Fix tests. 2018-10-15 14:33:23 +07:00
grossmj
f6a738fe3e Fix conflict between the two websocket streams (project & controller). 2018-10-15 14:19:46 +07:00
grossmj
4b577e96dd Fix platform.linux_distribution() is deprecated. Fixes https://github.com/GNS3/gns3-gui/issues/2578 2018-10-04 16:32:50 +02:00
grossmj
c6ed354629 Merge branch '2.1' into 2.2
# Conflicts:
#	gns3/appliance_manager.py
#	gns3/dialogs/appliance_wizard.py
#	gns3/nodes_view.py
#	gns3/version.py
2018-10-04 15:50:00 +02:00
grossmj
ec324f9b01 Development on 2.1.12dev1 2018-09-28 20:44:52 +02:00
grossmj
cbfd59498e Release v2.1.11 2018-09-28 20:40:58 +02:00
grossmj
0216bc8b4d Handle deleted SIP objects. 2018-09-28 15:01:22 +02:00
grossmj
a8477597ab Update paths for UltraVNC and VirtViewer. 2018-09-27 22:22:36 +02:00
pyup-bot
4c7965d70f Update pytest-pythonpath from 0.7.2 to 0.7.3 2018-09-27 21:46:54 +02:00
Jeremy Grossmann
28acb2911f Merge pull request #2594 from GNS3/pyup-update-pytest-3.7.0-to-3.8.1
Update pytest to 3.8.1
2018-09-27 21:45:48 +02:00
grossmj
e240dbad6b Indicate if Solar-PuTTY is included or not. Fixes #2595 2018-09-27 21:08:51 +02:00
pyup-bot
fac27d9df9 Update pytest from 3.7.0 to 3.8.1 2018-09-23 03:52:10 +02:00
grossmj
8d183a3283 Fix bad link to installation instructions in README.rst. Fixes #2590 2018-09-20 14:58:41 +02:00
grossmj
3af5046d0f Downgrade to Qt 5.9. Fixes #2592. 2018-09-20 14:30:57 +02:00
grossmj
c8397a1ef7 Development on 2.1.11dev1 2018-09-15 11:13:39 +02:00
grossmj
b419891950 Release v2.1.10 2018-09-15 11:11:24 +02:00
grossmj
2c1ba697bd Fix small errors like unhandled exceptions etc. 2018-09-11 15:06:01 +02:00
grossmj
3000a9aa7f Fix when appliance version is not available for Dynamips/IOU/Qemu. Fixes #2585. 2018-09-05 15:32:38 +08:00
grossmj
2f8541c543 Fix issue when installing appliance with no version selected. Fixes #2585. 2018-09-05 14:53:47 +08:00
grossmj
5c3d4b2ab6 Check for existing appliance name across all emulator types. Fixes #2584. 2018-09-05 14:08:05 +08:00
grossmj
f44ac8cba5 Improve the invalid port format detection. Fixes https://github.com/GNS3/gns3-gui/issues/2580 2018-09-05 13:35:42 +08:00
grossmj
7ef49fbca7 Catch OSError/PermissionError when checking md5 on remote image. Fixes #2582. 2018-09-05 13:24:01 +08:00
grossmj
5ccf5778a2 Fix UnicodeDecodeError in file editor. Fixes #2581. 2018-09-04 21:52:35 +08:00
grossmj
6030d5e019 Catch import error for win32serviceutil. Fixes #2583. 2018-09-04 21:18:03 +08:00
grossmj
6de8880937 Fix bug with empty project ID when creating a new node. Fixes #2366
..
2018-09-04 20:51:30 +08:00
grossmj
08c89c4fac Fix various small errors, mostly about non-existing C/C++ objects. 2018-09-03 16:48:23 +07:00
grossmj
e411d497c4 Send extra controller and compute information in crash reports. 2018-09-02 21:47:33 +07:00
grossmj
e037835769 Update setup.py and fix minor issues. 2018-09-02 15:32:34 +07:00
grossmj
a5f4ec0135 Set the default delay console all value to 1500ms if using Solar-PuTTY. 2018-08-29 21:15:40 +07:00
grossmj
3ee68b22bd Merge branch '2.1' into 2.2
# Conflicts:
#	gns3/compute.py
#	gns3/nodes_view.py
#	gns3/version.py
2018-08-29 15:35:31 +07:00
grossmj
154f10a686 Make Solar-Putty the default if installed. Ref #2519. 2018-08-27 16:24:38 +07:00
grossmj
e5320c318f Fix tests. 2018-08-22 20:37:55 +07:00
grossmj
07ea6207c1 Fix issue with custom appliance. Fixes https://github.com/GNS3/gns3-registry/issues/361 2018-08-22 20:18:35 +07:00
grossmj
12398881f8 Forbid controller and compute servers to be different versions.
Report last compute server error to clients and display in the server summary.
2018-08-22 16:54:43 +07:00
grossmj
27a8e3c7f8 Fix issue with appliance categories. Fixes https://github.com/GNS3/gns3-registry/issues/361 2018-08-22 15:52:32 +07:00
grossmj
d92ff1abe3 Add compute information to crash reports. 2018-08-21 20:40:01 +07:00
grossmj
e97b3b6a42 Add controller version in Sentry bug reports. 2018-08-21 19:16:49 +07:00
grossmj
5ee3f73213 Backport: Fix "Network session error" issues. Fixes #2560. 2018-08-21 18:29:57 +07:00
grossmj
a30aa2f5f1 Add SolarPutty command line. Fixes #2519. 2018-08-21 18:16:51 +07:00
grossmj
98bb6590aa Add missing Qemu boot priority values. Fixes https://github.com/GNS3/gns3-server/issues/1385 2018-08-21 17:49:58 +07:00
grossmj
4250e961a3 Merge remote-tracking branch 'origin/2.1' into 2.1 2018-08-21 17:32:24 +07:00
grossmj
3c46a3a72d Update PyQt5 from version 5.8 to version 5.10. Fixes #2564. 2018-08-21 17:32:09 +07:00
grossmj
c82d262975 Allow multiple appliances to be installed. Ref #2490 2018-08-21 17:06:03 +07:00
grossmj
aa84d100b1 Add more information about appliance templates. 2018-08-20 16:50:47 +07:00
grossmj
e51477d989 New appliance wizard to install an appliance from different sources. Ref #2490 2018-08-19 16:51:48 +07:00
grossmj
e4a29f30e3 Fix tests. 2018-08-16 22:01:24 +07:00
grossmj
3d8bd16536 Redesign appliance handling part 1. Ref #2490
- Removed appliance templates from device dock
 - Use new controller notification stream
 - Fixed device update and remove from device dock
2018-08-16 21:47:52 +07:00
ziajka
c55442a517 Development on 2.1.10dev1 2018-08-13 13:50:31 +02:00
ziajka
45e0080726 Release v2.1.9 2018-08-13 13:14:20 +02:00
grossmj
bb013804d4 Merge branch '2.1' into 2.2 2018-08-13 16:10:06 +07:00
grossmj
95558ec2e6 Fix incorrect short port names in topology summary. Fixes https://github.com/GNS3/gns3-gui/issues/2562 2018-08-13 15:10:21 +07:00
grossmj
f1cd31baa6 Fix "Network session error" issues. Fixes #2560. 2018-08-12 21:06:00 +07:00
grossmj
cf7176559d Set default layer for newly created nodes to 1 and 2 for all other drawings. Ref #2513. 2018-08-08 14:34:58 +07:00
grossmj
2504085db2 Deactivate TraceNG module 2018-08-08 14:02:23 +07:00
grossmj
75d3b61783 Merge remote-tracking branch 'origin/2.2' into 2.2 2018-08-07 21:02:40 +07:00
grossmj
5da8e77d01 Merge branch '2.1' into 2.2
# Conflicts:
#	gns3/dialogs/appliance_wizard.py
#	gns3/node.py
#	gns3/version.py
2018-08-07 21:02:10 +07:00
grossmj
5b56d54030 Add compute version in server summary tooltip. 2018-08-07 15:32:16 +07:00
Jeremy Grossmann
3de38d2ccb Merge pull request #2552 from GNS3/pyup-update-pytest-3.6.1-to-3.7.0
Update pytest to 3.7.0
2018-07-31 21:10:18 -05:00
pyup-bot
76553ff102 Update pytest from 3.6.1 to 3.7.0 2018-07-31 08:03:53 +02:00
Jeremy Grossmann
67b2d145da Merge pull request #2543 from GNS3/pyup-update-pytest-timeout-1.2.1-to-1.3.1
Update pytest-timeout to 1.3.1
2018-07-30 11:30:58 -05:00
Jeremy Grossmann
d5ee1ea5d2 Merge pull request #2538 from ehlers/osx_telnet_utf8_path
Support PATH with UTF-8 characters in OSX telnet console, fixes #2537
2018-07-30 10:13:52 -05:00
grossmj
69b8c07c0a Fix test for Qemu boot priority. Fixes #2548. 2018-07-30 09:48:38 -05:00
grossmj
dbe73eb8d7 Fix boot priority missing when installing an appliance. Fixes #2548. 2018-07-30 09:29:51 -05:00
pyup-bot
ba0559bf08 Update pytest-timeout from 1.2.1 to 1.3.1 2018-07-23 22:51:41 +02:00
Bernhard Ehlers
706f89debb Support PATH with UTF-8 characters in OSX telnet console, fixes #2537 2018-07-14 12:38:53 +02:00
grossmj
ec0be9e22b Allow users to accept different MD5 hashes for preconfigured appliances. Fixes #2526. 2018-07-10 16:02:44 +08:00
grossmj
0e6fa597ec Do not try to update drawing if it is being deleted. Ref #2483. 2018-07-10 15:39:35 +08:00
grossmj
f81450c65a Merge remote-tracking branch 'origin/2.1' into 2.1 2018-07-10 11:54:26 +08:00
grossmj
38cbe70aaa Catch exception when loading invalid appliance file. 2018-07-10 11:54:11 +08:00
ziajka
9fd07b6379 Merge pull request #2528 from GNS3/local-web-ui
Main menu actions to WebUI and Light Web Interface
2018-06-26 12:05:17 +02:00
ziajka
c84b262303 Main menu actions to WebUI and Light Web Interface 2018-06-26 12:04:02 +02:00
Jeremy Grossmann
0150515338 Enable TraceNG module 2018-06-18 23:54:13 +07:00
ziajka
47d335f4c9 Release v2.1.8 2018-06-14 15:16:54 +02:00
grossmj
ffc08361ce Add Solar-Putty command line. Ref #2519. 2018-06-14 17:04:44 +08:00
grossmj
ab90f5f458 Fix merging issue from 2.1 to 2.2 for DockerVMConfigurationPage. Fixes #2516. 2018-06-14 12:03:07 +08:00
grossmj
a0d6a43b51 Fix issues when locking/unlocking items. Ref #2513. 2018-06-13 17:31:27 +08:00
grossmj
20d4f73f56 Add error information when cannot access/read IOS/IOU config file. Ref #2501 2018-06-13 16:27:43 +08:00
grossmj
5204184029 Fallback when using process name to bring console to front. 2018-06-12 17:55:09 +08:00
grossmj
9915beeb8e Use process name to bring console to front. Fixes #2514. 2018-06-12 17:45:54 +08:00
ziajka
1ea383fce2 Development on v2.1.8dev1 2018-06-12 11:15:26 +02:00
ziajka
2744e669b4 Release v2.1.7 2018-06-12 11:12:49 +02:00
grossmj
8fd9ec5319 Merge branch '2.1' into 2.2
# Conflicts:
#	gns3/node.py
2018-06-12 15:22:46 +08:00
grossmj
a5f3164feb Merge branch '2.1' into 2.2
# Conflicts:
#	gns3/node.py
2018-06-10 21:24:57 +07:00
grossmj
3d949df14c Fix tests for default note font/color. 2018-06-10 17:53:00 +07:00
grossmj
6a5764fda9 Console support for clouds (to connect to external devices or services). Fixes #2500. 2018-06-10 17:45:34 +07:00
grossmj
f312d57165 Fix LabelItem tests. 2018-06-09 19:19:16 +07:00
grossmj
973793e6b6 Separate appliance font from note font. Fixes #2477. 2018-06-09 19:13:36 +07:00
grossmj
2a7ce661da Do not include spaces in link description (%d replacement) for packet analyzer command. Ref #2485. 2018-06-09 18:25:09 +07:00
grossmj
a85f99185a Fix error when trying to open project. Fixes #2508 2018-06-09 18:20:03 +07:00
grossmj
d511d0f5f8 Launch packet capture analyzer command without creating pipe. 2018-06-09 18:08:42 +07:00
Jeremy Grossmann
b92a589762 Merge pull request #2510 from GNS3/pyup-update-pytest-3.4.2-to-3.6.1
Update pytest to 3.6.1
2018-06-07 21:56:13 +07:00
grossmj
6ab2d63bdc Do not try to update link if it is being deleted. Fixes #2483. 2018-06-06 21:00:08 +07:00
grossmj
0de6bfe7e1 Fix can't add SVG image to project. Fixes #2502 2018-06-06 18:26:37 +07:00
pyup-bot
b024eb63e9 Update pytest from 3.4.2 to 3.6.1 2018-06-05 19:44:09 +02:00
grossmj
f144103bca Remove unwanted trailing characters and other white spaces when reading .md5sum files. Fixes #2498. 2018-06-04 23:59:53 +07:00
grossmj
7c1af696b9 Merge branch '2.1' into 2.2
# Conflicts:
#	gns3/modules/docker/pages/docker_vm_preferences_page.py
#	gns3/modules/docker/ui/docker_vm_configuration_page.ui
#	gns3/modules/docker/ui/docker_vm_configuration_page_ui.py
#	gns3/modules/qemu/pages/qemu_vm_configuration_page.py
#	gns3/modules/virtualbox/pages/virtualbox_vm_configuration_page.py
#	gns3/modules/vmware/pages/vmware_vm_configuration_page.py
#	gns3/version.py
2018-06-04 22:45:24 +07:00
grossmj
c0b26aff48 Update interface sequence number check. Fixes #2491. 2018-06-04 22:31:19 +07:00
ziajka
9601e4e6f2 Logo should not have context menu, Fixes: #2507 2018-05-24 13:21:13 +02:00
ziajka
88708c2a8d Update logo position only when changes, Fixes: #2506 2018-05-24 13:15:32 +02:00
ziajka
8eff12194d Development on v2.1.7dev1 2018-05-22 14:14:46 +02:00
ziajka
b0520b2bd4 Release v2.1.6 2018-05-22 14:11:59 +02:00
ziajka
17d2c023bf Fix redraw logo on Windows 2018-05-22 13:16:48 +02:00
ziajka
ce9fdea0a0 Merge pull request #2492 from GNS3/extra-hosts
Extra hosts for Docker, global variables for project and supplier logo support, Fixes: #2482
2018-05-15 09:23:42 +02:00
ziajka
24d7dacb4e Variables fix on ProjectWelcomeDialog 2018-05-10 10:46:57 +02:00
ziajka
bb36765407 Remove project_created_signal 2018-05-09 15:24:41 +02:00
ziajka
250db92ce0 Ask for global variables when project is loaded 2018-05-09 11:54:13 +02:00
ziajka
d59ec39505 Add/Edit global variables of project 2018-05-08 18:31:26 +02:00
ziajka
5e9ae04dc1 Rename tabs at Edit Project 2018-05-08 17:05:25 +02:00
ziajka
ddb0fccda3 Global variables tab on Edit project 2018-05-08 17:03:04 +02:00
ziajka
9b22a52f14 Support of supplier logo and url 2018-05-08 16:22:01 +02:00
grossmj
948878bfdd Add missing crowdfunder name in About dialog. 2018-05-08 21:52:37 +08:00
ziajka
7340abbaa9 Project variables and supplier 2018-05-08 13:00:32 +02:00
grossmj
1c1ea50adc Merge branch '2.1' into 2.2
# Conflicts:
#	gns3/node.py
#	gns3/version.py
2018-04-28 19:44:49 +07:00
grossmj
4ea0528bf2 No timeout when duplicating a project. 2018-04-28 17:09:08 +07:00
grossmj
49005e6add No timeout when restoring snapshot. 2018-04-28 16:41:54 +07:00
ziajka
5484c039b5 Fix tests 2018-04-27 14:47:09 +02:00
ziajka
daaf71b6d2 Add advanced settings for docker and param, Ref. #2482 2018-04-27 14:28:14 +02:00
grossmj
450f0e006b Merge remote-tracking branch 'origin/2.1' into 2.1 2018-04-23 15:40:18 +07:00
grossmj
a6a967fbde Replace "not supported" by "none" in topology summary view. 2018-04-23 15:39:58 +07:00
ziajka
1a6293709e Development on v2.1.6 2018-04-18 11:41:43 +02:00
ziajka
2ed53225e0 Release v2.1.5 2018-04-18 11:28:52 +02:00
grossmj
b8798fbda5 Disable TraceNG for version 2.1.5 2018-04-18 17:19:44 +08:00
grossmj
c2ac68be49 Merge branch '2.1' into 2.2
# Conflicts:
#	gns3/modules/traceng/traceng_node.py
2018-04-18 17:10:50 +08:00
grossmj
368de32faa Fix Qemu binary list locks when a version is deleted. Fixes #2474. 2018-04-18 15:44:33 +08:00
grossmj
98d01cbfa0 Fix invalid answer from the PyPi server. Fixes #2473. 2018-04-18 15:10:31 +08:00
grossmj
ad62bb7832 Fix wrong wizard page name. 2018-04-16 17:16:20 +08:00
grossmj
637061663a Add default destination setting for traceng + some checks. Ref #2450. 2018-04-16 15:03:02 +08:00
grossmj
c137198985 Grid size support for projects. Fixes #2469. 2018-04-13 16:56:37 +08:00
grossmj
946efb61de Remove 'include INSTALL' from MANIFEST. Fixes #2470. 2018-04-13 14:17:03 +08:00
grossmj
cb74a8e12f Cleanup more code. 2018-04-11 16:56:18 +07:00
grossmj
c42fecaea3 Cleanup node code. 2018-04-10 20:48:00 +07:00
grossmj
088b020ac0 More spring cleaning. 2018-04-09 16:50:33 +07:00
grossmj
af507e7668 Some spring cleanup. 2018-04-08 16:44:12 +07:00
grossmj
204ff1f8fd Streamline appliance wizard. Fixes #2224. 2018-04-08 16:42:07 +07:00
grossmj
8c7e8e412a Fix "Node list view not updated when renaming or deleting appliance template". Fixes #2356. 2018-04-06 16:57:07 +07:00
grossmj
030169dc10 Automatically resize the Custom adapters configuration dialog. Fixes #2467. 2018-04-06 16:24:50 +07:00
grossmj
e877adca35 Change size of custom adapters configuration dialog. Ref #2467. 2018-04-06 14:42:30 +07:00
grossmj
18dc8fab14 Fix tests. 2018-04-06 14:35:39 +07:00
grossmj
60018612b1 Improve node tooltips. Fixes #2462. 2018-04-06 13:25:23 +07:00
Jeremy Grossmann
0410c446fc Merge pull request #2466 from dhalperi/fix-typo
Fix a minor typo in the setup wizard
2018-04-05 13:19:38 +07:00
Daniel Halperin
18486e4772 Fix a minor typo in the setup wizard
Eveything -> Everything
2018-04-04 22:53:09 -07:00
grossmj
3c9787effb Do not activate "console auto start" by default. Ref #1910. 2018-04-05 11:08:40 +07:00
grossmj
664da8ee3d Remove unused code. 2018-04-04 21:52:29 +07:00
grossmj
b4da9b7bae Support for console auto start. Fixes #1910 2018-04-04 21:32:08 +07:00
grossmj
5ef612815b Bump version to 2.2.0dev2 2018-04-03 12:51:09 +07:00
grossmj
06d7ed783f Add custom_adapters setting support for appliance files. Ref #2361. 2018-04-02 23:13:45 +07:00
grossmj
cc5b55a7ce Fix tests. 2018-04-02 22:59:47 +07:00
grossmj
c8e1602a26 Possibility to customize port names and adapter types for Qemu, VirtualBox, VMware and Docker. Fixes #2361.
MAC addresses can customized for Qemu as well.
2018-04-02 22:27:12 +07:00
grossmj
43688cb9bd Allow to have the projects with the same name in different locations. Fixes #2380. 2018-03-30 23:18:07 +07:00
grossmj
eb34715178 Save state feature for VirtualBox and VMware. New "On close" setting to
select the action to execute when closing/stopping a Qemu/VirtualBox/VMware VM.
2018-03-30 21:18:44 +07:00
grossmj
b7d78b92fc Support for suspend to disk / resume (Qemu). Ref #725. 2018-03-30 19:27:46 +07:00
grossmj
ab7930d3d9 Fix bug with 'none' console type for Ethernet switch.
Fix some tests related to traceng.
2018-03-30 13:00:52 +07:00
grossmj
c684e63be2 Merge branch '2.1' into 2.2
# Conflicts:
#	gns3/ui/resources_rc.py
2018-03-30 12:16:31 +07:00
grossmj
4c610acfa4 Fix traceng tests. 2018-03-30 12:10:57 +07:00
grossmj
37f74824f1 Merge branch 'traceng' into 2.1 2018-03-29 15:19:29 +07:00
grossmj
5ccf8c414d Sync 2018-03-29 15:19:18 +07:00
grossmj
913f0d5e4a Check for valid IP address and prevent to run on non-Windows platforms. 2018-03-29 13:26:43 +07:00
grossmj
061bac0cc6 Support for source and destination for traceNG. 2018-03-27 16:58:49 +07:00
grossmj
20ff8a19f6 Allow to resize a Qemu VM disk (extend only). Ref #2382. 2018-03-26 18:05:20 +07:00
grossmj
53ba302515 Allow to select the default NAT interface in preferences for local server. 2018-03-26 14:23:01 +07:00
grossmj
4b43dfb77c Fix missing lock and unlock icons in resources. 2018-03-25 18:50:52 +07:00
grossmj
f8555f4008 Consistent icon styles for contextual menu. Fixes #1272. 2018-03-25 18:40:10 +07:00
grossmj
75c3092724 Spice with agent support for Qemu VMs. Fixes #2355. 2018-03-25 14:35:25 +07:00
grossmj
89e274d040 Fix zoom-in zoom-out step values. Ref #2457. 2018-03-25 13:05:50 +07:00
grossmj
f9619d79ae Support for console type "none" for all VMs. Fixes #2452. 2018-03-24 18:12:06 +07:00
grossmj
7fd9f39c36 Allow to copy Dynamips, IOU, Qemu and Docker templates in preferences. Fixes #2451. 2018-03-23 21:11:20 +07:00
grossmj
bb732bc202 Support for none console type (Qemu & Docker only) 2018-03-23 15:41:56 +07:00
grossmj
481e6c3450 Fix some issues with hardware acceleration support for Qemu. 2018-03-22 15:45:41 +07:00
grossmj
7ad663cc2a Support Qemu with HAXM acceleration. 2018-03-21 16:41:47 +07:00
ziajka
ec59cd87bd Back to development on v2.1.5dev1 2018-03-15 08:46:06 +01:00
grossmj
d4a0b21206 Some spring cleaning. 2018-03-15 14:17:40 +07:00
ziajka
05d9ee8499 Re-release v2.1.4 due to travis issue 2018-03-14 15:28:15 +01:00
grossmj
3e0242ada7 Merge branch '2.1' into 2.2
# Conflicts:
#	gns3/version.py
2018-03-14 18:39:08 +07:00
grossmj
a72ece5c18 Custom icons and small fixes for TraceNG integration. 2018-03-14 16:56:39 +07:00
grossmj
63baa2eff0 Base support for TraceNG. 2018-03-12 17:57:13 +07:00
ziajka
b91fd4a0c2 Development on v2.1.5dev1 2018-03-12 09:25:41 +01:00
ziajka
718217e332 Release v2.1.4 2018-03-12 09:17:16 +01:00
grossmj
ba71e560f9 Merge remote-tracking branch 'origin/2.2' into 2.2 2018-03-12 13:34:31 +07:00
grossmj
1989ec3a40 Merge branch '2.1' into 2.2 2018-03-12 13:30:46 +07:00
ziajka
c202c5e4be Move connect to update settings into one place 2018-03-09 13:31:55 +01:00
ziajka
71830dd69f Merge pull request #2449 from GNS3/update-nodes
Update node on server on any change, Fixes: #2429
2018-03-09 12:55:48 +01:00
ziajka
37a7fdfa68 Update node on server on any change, Fixes: #2429 2018-03-09 12:54:29 +01:00
ziajka
cb074be0a1 Merge pull request #2446 from GNS3/pyup-update-pytest-3.4.1-to-3.4.2
Update pytest to 3.4.2
2018-03-06 09:24:50 +01:00
pyup-bot
08784158c1 Update pytest from 3.4.1 to 3.4.2 2018-03-06 04:56:24 +01:00
grossmj
0efe006cad Mark IOU layer 1 keepalive messages feature as non-functional. Fixes #2431. 2018-03-05 16:44:42 +07:00
ziajka
4a663a5910 Fix typo 2018-02-27 16:08:33 +01:00
ziajka
a559bd4ae4 Images refresh when added via settings, Fixes:#2423 2018-02-27 16:07:06 +01:00
ziajka
2539abd445 Merge pull request #2436 from GNS3/pyup-update-pytest-timeout-1.2.0-to-1.2.1
Update pytest-timeout to 1.2.1
2018-02-22 09:23:16 +01:00
ziajka
e76f1ca5cc Merge pull request #2437 from GNS3/pyqt-update
PyQt 5.10 with AV builds, Ref. #2434
2018-02-21 16:18:36 +01:00
pyup-bot
bc338b6232 Update pytest-timeout from 1.2.0 to 1.2.1 2018-02-21 16:15:38 +01:00
ziajka
ddb581623a Use PyQt 5.10 and change AV build to use MSVS2017 2018-02-21 16:11:53 +01:00
ziajka
486faf6718 Merge branch '2.2' into pyqt-update 2018-02-21 12:59:52 +01:00
ziajka
a081dcddb8 Merge branch '2.1' into 2.2 2018-02-21 12:04:56 +01:00
ziajka
c4160ec942 Test with PyQt5.9 2018-02-21 12:04:02 +01:00
ziajka
f38d9ef525 Back to PyQt5.8 2018-02-21 12:02:48 +01:00
ziajka
6639108354 Merge pull request #2435 from GNS3/pyup-update-pytest-3.1.0-to-3.4.1
Update pytest to 3.4.1
2018-02-21 10:05:37 +01:00
ziajka
a63a097341 Merge branch '2.2' into pyup-update-pytest-3.1.0-to-3.4.1 2018-02-21 10:05:27 +01:00
ziajka
94bad69198 Merge pull request #2412 from GNS3/pyup-update-pytest-pythonpath-0.7.1-to-0.7.2
Update pytest-pythonpath to 0.7.2
2018-02-21 10:04:19 +01:00
ziajka
e9057e75a0 PyQt5.10 support, Ref. #2434 2018-02-21 10:01:20 +01:00
pyup-bot
b80b86d365 Update pytest from 3.1.0 to 3.4.1 2018-02-21 03:02:35 +01:00
ziajka
5ebb3011d3 Merge pull request #2433 from GNS3/show-if-labels-on-new-project
Show labels on the new project, Fixes: #2308
2018-02-19 13:05:22 +01:00
ziajka
81300fd40e Adjust tests 2018-02-19 12:55:52 +01:00
ziajka
d4dda2a285 Emit project_loaded_signal after project creation 2018-02-19 12:54:36 +01:00
ziajka
5a4342d4b8 Add option Show interface labels on new project, Ref. #2308 2018-02-16 14:32:07 +01:00
ziajka
94fc5e6c4f Improve finding pyuic3.exe on Windows 2018-02-16 14:30:49 +01:00
grossmj
a3e81fbf2e Use debug for error downloading file messages. Fixes #2398. 2018-02-07 16:12:50 +08:00
grossmj
514eb97eac Merge remote-tracking branch 'origin/2.1' into 2.1 2018-02-06 15:38:38 +08:00
grossmj
7637039cb2 Refresh buttons in the cloud node to query the server for available interfaces. Fixes #2416. 2018-02-06 15:36:27 +08:00
pyup-bot
e46c92e92f Update pytest-pythonpath from 0.7.1 to 0.7.2 2018-02-03 04:13:02 +01:00
Jeremy Grossmann
ac989b191b Merge pull request #2410 from GNS3/new-appliance-symbol-from-controller
Appliance import looks for symbols on server, Fixes. #2405
2018-02-02 10:24:32 +01:00
Dominik Ziajka
c971cef31b Handle Certifacte Error, Ref. gns3-server#1262 2018-02-02 10:02:18 +01:00
Dominik Ziajka
c1af2df780 Backward compatibility for tests, Ref. #2405? 2018-02-02 08:47:56 +01:00
grossmj
eaaa141be9 Use UTF-8 for IOURC file migration. 2018-02-02 15:41:42 +08:00
ziajka
226169cdc6 Look for symbols on controller, Ref. #2405 2018-02-01 17:42:02 +01:00
grossmj
42a4c89f20 Display an error message if Telnet console program cannot be executed. 2018-01-29 18:59:28 +07:00
Jeremy Grossmann
38ade919df Merge pull request #2404 from GNS3/allow-different-md5
Allow to accept a different md5 hash than the one in the appliance file.
2018-01-26 16:13:10 +07:00
grossmj
6458f88d1c Remove leftover debug message. 2018-01-26 15:26:27 +07:00
ziajka
1e936da469 Allow to accept a different md5 hash than the one in the appliance file. Ref. server#1246 2018-01-25 11:55:33 +01:00
ziajka
f90ec81fca Critical information during upload file with different md5, Ref. #1246 2018-01-24 11:43:32 +01:00
grossmj
141578a1e1 Restore locked item state. 2018-01-23 17:39:35 +07:00
grossmj
e1d2bcca20 Merge branch '2.1' into 2.2
# Conflicts:
#	gns3/ui/main_window_ui.py
#	gns3/ui/resources_rc.py
#	gns3/version.py
#	resources/resources.qrc
2018-01-23 12:44:02 +07:00
grossmj
a5435280d7 Bump to version 2.2.0dev1 & refresh resources/ui files. 2018-01-23 11:36:58 +07:00
grossmj
1482b0e804 Back to development on v2.1.4dev1 2018-01-21 15:57:41 +07:00
grossmj
8ebe3435c4 Re-release v2.1.3 to fix idna packaging issue. 2018-01-21 15:16:25 +07:00
ziajka
a1cd34d7c4 Back to development on v2.1.4dev1 2018-01-19 08:18:19 +01:00
ziajka
1e4a44135c Re-release v2.1.3 2018-01-19 08:11:46 +01:00
ziajka
a407f1ec90 Update to python3.6 in tests - running xvfb 2018-01-19 08:05:07 +01:00
ziajka
faab113384 Update to python3.6 in tests 2018-01-19 08:01:11 +01:00
ziajka
c158b7fc46 Use Ubuntu 17.10 for TCI tests 2018-01-19 07:55:13 +01:00
ziajka
16de9e830f Use Ubuntu 16.04 for TCI tests 2018-01-19 07:44:37 +01:00
ziajka
25c625c0bb Development on v2.1.4dev1 2018-01-19 07:17:22 +01:00
ziajka
bf42d1a355 Release v2.1.3 2018-01-19 07:15:24 +01:00
grossmj
1c0f3493ee Fix more client/server version tests. 2018-01-18 16:14:09 +08:00
grossmj
c3c1f87c5e Change messages when there are different client and server versions. Fixes #2391. 2018-01-18 15:58:21 +08:00
grossmj
6b80914385 Bump version number to 2.1.3dev1 2018-01-18 15:32:06 +08:00
grossmj
a114d9ace7 Fix "Transport selection via DSN is deprecated" message. Sync is configured with HTTPTransport. 2018-01-15 16:56:16 +07:00
grossmj
4dca4d057a Refresh CPU/RAM info every 1 second. Ref #2262. 2018-01-15 14:42:01 +07:00
grossmj
17af21e29a Only check for AVG on Windows 2018-01-14 13:40:31 +07:00
grossmj
7fbce0266d Improve the search for VBoxManage. 2018-01-11 16:33:15 +07:00
grossmj
d5cdbdbf90 Allow telnet console to node with name containing double quotes. Fixes #2371. 2018-01-10 22:16:35 +07:00
ziajka
e5a790f4b2 Development v2.1.3dev1 2018-01-08 14:21:28 +01:00
ziajka
f3769df0d6 Add to CHANGELOG changes 2018-01-08 14:09:21 +01:00
ziajka
a21db74941 Release v2.1.2 2018-01-08 14:08:12 +01:00
grossmj
d1e1f6dfb6 Update VMware promotion in setup wizard. 2018-01-08 18:41:40 +07:00
grossmj
cc45c9631a Confirm exit. Fixes #2359. 2018-01-08 18:00:59 +07:00
ziajka
d16a52e389 Development on v2.1.2dev1 2017-12-22 13:28:39 +01:00
ziajka
ee2bea7cdd Release v2.1.1 2017-12-22 13:26:55 +01:00
grossmj
7cbc25cbbf Bump version to 2.1.1dev2 2017-12-20 11:20:07 +01:00
ziajka
7237cf1b88 Merge pull request #2373 from GNS3/fix-2363
Fix dragging appliance into topology from nodes window, fixes: #2363
2017-12-20 09:54:05 +01:00
ziajka
965923900b Fix dragging appliance into topology from nodes window, fixes: #2363 2017-12-20 09:53:19 +01:00
ziajka
a5a3a4e8cc Merge pull request #2372 from GNS3/fix-2362-2
Fix Appliances in Docked mode, fixes: #2362
2017-12-20 09:29:21 +01:00
ziajka
d898b30d84 Fix Appliances in Docked mode, fixes: #2362 2017-12-20 09:28:33 +01:00
ziajka
e86ced750e Merge pull request #2370 from GNS3/fix-2366
Create local variable in order to debug issue in the next occurrence,…
2017-12-19 14:48:44 +01:00
ziajka
e15b717cb0 Create local variable in order to debug issue in the next occurrence, #2366 2017-12-19 14:46:24 +01:00
ziajka
d8bd33f0e7 Merge pull request #2369 from GNS3/fix-2364
Fix ParseError: not well-formed (invalid token), #2364
2017-12-19 12:52:25 +01:00
ziajka
bc2fbe33ef Fix ParseError: not well-formed (invalid token), #2364 2017-12-19 12:51:20 +01:00
ziajka
b99b26f463 Merge pull request #2368 from GNS3/fix-2365
Fix local variable 'vm' referenced before assignment #2365
2017-12-19 11:41:30 +01:00
ziajka
5b7606793f Fix local variable 'vm' referenced before assignment #2365 2017-12-19 11:40:24 +01:00
ziajka
b8b5e8739e Merge pull request #2367 from GNS3/fix-2362
Fix: 'NodesDockWidget' object has no attribute 'uiNodesView', #2362
2017-12-19 11:38:11 +01:00
ziajka
0126c30887 Fix: 'NodesDockWidget' object has no attribute 'uiNodesView', #2362 2017-12-18 14:30:26 +01:00
grossmj
a89086ff60 Fix test. 2017-12-07 14:31:41 -06:00
grossmj
9ca35c56de Tentative fix for packet capture not working correctly when remote main server is configured. Ref #2111. 2017-12-07 13:59:02 -06:00
grossmj
3ddccf40a8 Log Qt messages with log.debug() instead of log.info(). 2017-12-05 14:24:24 -06:00
grossmj
d51c96f105 Merge remote-tracking branch 'remotes/origin/2.1' into 2.2 2017-11-27 14:21:31 +07:00
grossmj
a47b839cc2 Merge remote-tracking branch 'remotes/origin/2.1' into 2.2
# Conflicts:
#	gns3/ui/main_window_ui.py
#	gns3/ui/resources_rc.py
2017-11-27 14:19:29 +07:00
Jeremy Grossmann
1398ef323a Merge pull request #2345 from GNS3/no-timeout-snapshots
Snapshoting project without timeout but with Cancel button. Ref. #2314
2017-11-24 18:19:26 +07:00
grossmj
d52c4d839d Fix auto idle-pc from preferences. Fixes #2344. 2017-11-23 23:01:01 +07:00
ziajka
6989ee2c8b Snapshot creation, busy all the time as we cannot calculate progress. 2017-11-23 15:06:44 +01:00
ziajka
5c182e95ca Snapshoting project without timeout but with button. Ref. #2314 2017-11-23 14:13:56 +01:00
grossmj
bcb7a8e57b Improve validation for idle-pc. 2017-11-23 10:41:30 +07:00
grossmj
dba75e844e Activate faulthandler. 2017-11-21 13:44:29 +07:00
Jeremy Grossmann
6733739fa5 Merge pull request #2340 from ehlers/fix-osx-telnet
Fix OS X Telnet
2017-11-20 11:44:02 +07:00
Bernhard Ehlers
f5de62aa05 Add PATH to OS X console commands 2017-11-19 15:40:54 +01:00
Bernhard Ehlers
4087d35f6a Use raw triple quotes in large console settings
This eliminates one level of quoting
2017-11-19 15:31:26 +01:00
grossmj
f6a1af46a0 Fix issue in node summary when console is not supported by a node. 2017-11-19 20:30:58 +07:00
Bernhard Ehlers
6cef2fed5a Revert "Add preferred path to use Telnet console in DMG package. Ref #2274." 2017-11-19 12:37:21 +01:00
Bernhard Ehlers
e16c8db311 Revert "Force to use the telnet client embedded in DMG. Ref #2274." 2017-11-19 12:36:33 +01:00
Bernhard Ehlers
61c95a93ca Revert "Add debug when using Telnet path on OSX. Ref #2274." 2017-11-19 12:35:55 +01:00
Bernhard Ehlers
0df36dab30 Revert "Fix bug when replacing Telnet path on OSX. Ref #2274." 2017-11-19 12:33:54 +01:00
Bernhard Ehlers
9a5da633e0 Revert "Fix problem when embedded telnet client path contains a space on macOS. Ref #2328." 2017-11-19 12:32:29 +01:00
Bernhard Ehlers
02fed964f2 Revert "Support Telnet path containing spaces. Ref #2328." 2017-11-19 12:30:15 +01:00
grossmj
84ba56ae74 Remove unused symbols. Fixes #2320. 2017-11-19 14:50:12 +07:00
grossmj
e8c4758cb7 Show console information in Topology Summary Dock. Fixes #2258. 2017-11-19 13:56:54 +07:00
grossmj
d8dc31965f New option: require KVM. If false, Qemu VMs will not be prevented to run without KVM. 2017-11-19 12:39:37 +07:00
grossmj
9af48ba9a3 Implement variable replacement for Qemu VM options. 2017-11-18 17:36:11 +07:00
grossmj
67d8e317e0 Show on what server a node is installed in the servers summary pane. Fixes #2279. 2017-11-18 16:02:31 +07:00
grossmj
64392780c5 Add more info when cannot remove capture file after stopping packet capture in a remote project. Ref #1223. 2017-11-17 18:32:18 +07:00
grossmj
81bb159d45 Do not overwrites the disk images when copied to default directory. Fixes #2326. 2017-11-17 15:42:33 +07:00
ziajka
85352af9bd Update pyup config to use 2.2 branch 2017-11-15 13:21:14 +01:00
grossmj
65cfdf6b33 Revert "Only replace quoted telnet for macOS Telnet commands. Ref #2328." 2017-11-15 10:39:24 +07:00
grossmj
5d45dbebf6 Only replace quoted telnet for macOS Telnet commands. Ref #2328. 2017-11-14 18:42:17 +07:00
grossmj
0a7b6d81d8 Support Telnet path containing spaces. Ref #2328. 2017-11-14 18:34:06 +07:00
grossmj
588dcadd3a Fix problem when embedded telnet client path contains a space on macOS. Ref #2328. 2017-11-14 17:22:44 +07:00
grossmj
f24c93a55f Do not launch console for builtin nodes when using the "Console to all nodes" button. Fixes #2309. 2017-11-12 17:02:00 +08:00
grossmj
26e5c80406 Merge remote-tracking branch 'remotes/origin/master' into 2.1 2017-11-12 14:22:13 +08:00
ziajka
eb502232a2 Development on 2.1.1dev1 2017-11-09 10:50:12 +01:00
ziajka
25e17d718c Release 2.1.0 2017-11-09 07:29:33 +01:00
ziajka
89108070df Development on v2.1.0dev10 2017-11-07 10:19:46 +01:00
ziajka
f4df3ff9c0 Release v2.1.0rc4 2017-11-07 08:48:00 +01:00
Jeremy Grossmann
90f80b9804 Merge pull request #2322 from GNS3/upload-dialogs-progress
Accurate upload progress dialogs for large files
2017-11-06 20:50:59 +08:00
ziajka
3e86044132 Fix tests 2017-11-06 09:31:39 +01:00
ziajka
78d805cebc Disable showProgress during obtaining endpoint 2017-11-06 09:28:07 +01:00
ziajka
289f754108 Accurate upload progress dialogs for large files 2017-11-03 11:38:04 +01:00
Jeremy Grossmann
1a0c1f826b Merge pull request #2313 from GNS3/disable-direct-file-upload
Disable direct file upload on default
2017-10-30 17:18:36 +07:00
ziajka
9837d661a5 Disable direct file upload on default 2017-10-26 13:41:27 +02:00
grossmj
ff60776769 Merge remote-tracking branch 'origin/2.1' into 2.1 2017-10-26 15:47:02 +07:00
grossmj
7ac442631a Add registry version 5 2017-10-26 15:46:39 +07:00
Jeremy Grossmann
8da2ff3a97 Merge pull request #2310 from GNS3/image-upload-manager
Safe approach to send files to computes and dialogs fixes, Fixes: #2307, Ref: #2188
2017-10-26 13:01:14 +07:00
Jeremy Grossmann
a04d9784f2 Merge branch '2.1' into image-upload-manager 2017-10-26 12:24:17 +07:00
ziajka
623aa4a2de Code style and tests 2017-10-25 16:10:24 +02:00
ziajka
ef3c2afab9 Direct file upload enabled on default 2017-10-25 15:22:39 +02:00
ziajka
73e59d92ca Progress Dialog: don't count finished queries done in background 2017-10-25 13:50:35 +02:00
ziajka
8f3d5bf038 Add debug messages to file upload 2017-10-25 10:27:17 +02:00
ziajka
d638c6e0d7 Image Upload Manager for uploading 2017-10-24 17:20:30 +02:00
grossmj
c5688cacf9 Restore timer for refreshing the progress dialog status. 2017-10-24 20:12:01 +07:00
Jeremy Grossmann
b34bcd6369 Merge pull request #2305 from GNS3/race-nodes-view
Fix race condition on NodesDockWidget, fixes: #2304
2017-10-23 16:10:40 +07:00
ziajka
5e0fc3675f Fix race condition on NodesDockWidget, fixes: #2304 2017-10-23 11:08:33 +02:00
grossmj
e75a21e2ed Do not write an error message when importing non existing config from a directory. Fixes #2296. 2017-10-21 12:30:08 +07:00
grossmj
aeee44e597 Fix bug when replacing Telnet path on OSX. Ref #2274. 2017-10-19 16:32:16 +07:00
ziajka
3cebee64ad Back to development on 2.1.0rc3 2017-10-19 09:56:56 +02:00
ziajka
fd1619cfd3 Fix Travis deploy - urlib3 2017-10-19 09:51:05 +02:00
ziajka
4573d2aed8 Fix Travis deploy - urlib3 2017-10-19 09:47:22 +02:00
ziajka
7f29c497cc Fix Travis deploy 2017-10-19 09:21:57 +02:00
ziajka
6da42b5013 Development on 2.1.0dev9 2017-10-19 08:58:15 +02:00
ziajka
430366947f Release 2.1.0 rc3 2017-10-19 08:56:10 +02:00
grossmj
3870f8ecdc Add debug when using Telnet path on OSX. Ref #2274. 2017-10-18 18:47:24 +07:00
grossmj
f68626e4cc Force to use the telnet client embedded in DMG. Ref #2274. 2017-10-18 17:26:44 +07:00
Jeremy Grossmann
6b4126b688 Merge pull request #2297 from GNS3/direct-file-upload
Direct file upload, Fixes #2264
2017-10-18 00:36:28 +07:00
ziajka
2ef9890dc1 Upload directly to compute 2017-10-17 12:32:38 +02:00
ziajka
100e3dbf27 Load endpoing and execute post image 2017-10-16 09:44:16 +02:00
Jeremy Grossmann
b85db6e24f Merge pull request #2294 from ddragic/qxcb-log-filter
Filter additional QXcbConnection log messages
2017-10-14 15:38:52 +02:00
Dušan Dragić
05d2077b16 Filter additional QXcbConnection log messages 2017-10-14 13:21:55 +02:00
grossmj
80f3dab152 Rebuild resources file. 2017-10-13 18:21:48 +08:00
grossmj
eef4d6e9fd Merge 2.1 to 2.2 2017-10-13 18:11:27 +08:00
ziajka
357d039434 Preparation to load endpoint before usage 2017-10-13 12:05:31 +02:00
ziajka
0288384c85 Direct file upload settings 2017-10-13 11:22:32 +02:00
grossmj
84347848e9 Do not add missing file extension for screenshot file names on Mac. Fixes #2287. 2017-10-11 04:58:59 +08:00
grossmj
24e5ef885c Add preferred path to use Telnet console in DMG package. Ref #2274. 2017-10-10 23:57:34 +08:00
grossmj
0d8255ecaf Merge remote-tracking branch 'origin/2.1' into 2.1 2017-10-10 22:32:18 +08:00
grossmj
679548e4ad Log Qt messages as info instead of error. Ref #2281. 2017-10-10 22:13:22 +08:00
ziajka
e5384af45d Fix Travis bug with missing twine library. Fixes: #2283 2017-10-06 09:55:43 +02:00
ziajka
ae68d4d84b Development on 2.1.0dev8 2017-10-04 11:40:14 +02:00
ziajka
2ab81816ef Release 2.1.0 rc2 2017-10-04 11:36:51 +02:00
grossmj
4c4241183a Only show "can't get settings from controller" message in debug mode. 2017-10-04 16:24:29 +08:00
grossmj
46406d1e7b Remove explicit Telnet path on OS X. Ref #2274 2017-10-03 04:31:08 +08:00
Jeremy Grossmann
a92573394f Merge pull request #2280 from GNS3/fix-pyqt-version-check
Disable WebSocket notification for lower PyQT version than 5.6. Fixes…
2017-10-02 18:03:31 +02:00
ziajka
6baf628997 Disable WebSocket notification for lower PyQT version than 5.6. Fixes #2272 2017-10-02 10:44:28 +02:00
grossmj
8f9190e094 Increase timeout to 5 minutes when creating and restoring a snapshot. 2017-10-02 05:02:26 +08:00
grossmj
7e14e734b2 Bump version to 2.1.0dev7 2017-10-02 04:04:38 +08:00
grossmj
76fc2f07ce Add more information when a request timeouts. Ref #2277. 2017-10-02 00:46:23 +08:00
grossmj
eee066d5f3 Do not show the progress dialog when moving a node. Ref #2275. 2017-10-02 00:44:58 +08:00
grossmj
9dead47a37 Increase timer before showing a progress dialog from 250ms to 500ms. Ref #2275. 2017-10-01 23:56:28 +08:00
grossmj
a22bd8e9be Use embedded Telnet client on OS X. Ref #2274. 2017-10-01 23:33:12 +08:00
grossmj
a4b897d458 Fix small bug when adding an appliance template and the name already exists. 2017-09-19 16:32:19 +07:00
grossmj
e784f21c0f Use RAW sockets by default on Linux for VMware VM connections. 2017-09-19 12:47:30 +07:00
grossmj
3a000cdc60 Increase timeout to get compute servers from controller. Ref #2269. 2017-09-15 19:40:42 +07:00
grossmj
405f3b3382 Fix "Node doesn't exist" after deletion, but still on the canvas. Fixes #2266. 2017-09-15 17:23:15 +07:00
grossmj
7397f76566 Remove debug test. 2017-09-15 16:24:57 +07:00
grossmj
178cb35d6a Make sure the warning button icon appears in cloud properties dialog on Windows. Fixes #2245. 2017-09-15 16:21:05 +07:00
grossmj
012e5d331d Fix bug when cancelling the importation of a configuration file. Fixes #2260. 2017-09-15 15:52:36 +07:00
ziajka
bd81d36635 Development on v2.1.0dev6 2017-09-13 09:30:56 +02:00
ziajka
234eab57c8 Release 2.1.0rc1 2017-09-13 09:28:55 +02:00
grossmj
e4b19714f4 Fix missing spice console option in appliance template schema. Fixes #2255. 2017-09-13 13:55:30 +07:00
ziajka
7bfba1015b Back to development at 2.1.0dev5 2017-09-05 11:24:08 +02:00
ziajka
498ba2d2b1 Re-release 2.1.0b2 2017-09-05 11:16:02 +02:00
ziajka
f3756b8401 Fix unicode error during appliance tests 2017-09-05 09:56:56 +02:00
ziajka
68f6d37aab Fix link tests 2017-09-05 09:43:33 +02:00
ziajka
6ce35fa5b5 Development on 2.1.0dev5 2017-09-05 08:41:08 +02:00
ziajka
e376753859 Release 2.1.0 beta 2 2017-09-05 08:37:42 +02:00
Jeremy Grossmann
7b03c3eae7 Merge pull request #2250 from GNS3/dont-move-under-layer-0
Disabled possibility of moving items under zero layer (Fixes #2220)
2017-09-01 16:20:04 +07:00
ziajka
902ba42be1 Merge pull request #2252 from GNS3/fix-resources
Fix resources dependencies for cloud configuration page (Fixes: #2251)
2017-09-01 11:06:58 +02:00
ziajka
73fe898eda Fix resources dependencies for cloud configuration page (Fixes: #2251) 2017-09-01 11:05:53 +02:00
ziajka
1ff488d39a Disabled possibility of moving items under zero layer (Fixes #2220) 2017-09-01 10:13:19 +02:00
Jeremy Grossmann
1622a79383 Merge pull request #2248 from GNS3/dialog-warning-fallback
dialog-warning.svg fallback for themed icon (Ref. #2245)
2017-09-01 12:51:38 +07:00
Jeremy Grossmann
1564c63a42 Merge pull request #2247 from GNS3/wide-packet-filters-dialog
Change width of packet filters dialog (Fixes #2244)
2017-09-01 12:50:24 +07:00
ziajka
29f651aaea dialog-warning.svg fallback for themed icon (Ref. #2245) 2017-08-31 11:37:32 +02:00
ziajka
9ee0222339 Change width of packet filters dialog (Fixes #2244) 2017-08-31 09:46:08 +02:00
grossmj
6e1384c985 Fix high CPU usage when using packet filters. Fixes #2240. 2017-08-28 11:40:50 +07:00
Jeremy Grossmann
20190c5816 Merge pull request #2232 from GNS3/toggle-node-menu-item
Toggle Node menu item (Fixes #2227)
2017-08-25 16:32:49 +08:00
ziajka
cab3412ddc Toggle Node menu item (Fixes #2227) 2017-08-22 13:01:50 +02:00
grossmj
78e7b78315 Have the contextual menu use icons from the active style. Ref #1272. 2017-08-15 19:38:23 +08:00
grossmj
b3f8170e01 Individually lock or unlock an item on the scene. Fixes #1228. 2017-08-11 17:35:24 +08:00
grossmj
18321f5347 Improve lock and unlock all items so some actions can still be performed on objects. Fixes #1134. 2017-08-11 15:03:33 +08:00
grossmj
734fcdfe9e Lock or unlock all items button. Fixes #1134. 2017-08-11 14:37:45 +08:00
Jeremy Grossmann
6d74ce4070 Merge pull request #2215 from GNS3/fix-qemu-edit-symbol
Fixes loading symbols for QEMU at Edit Page (#2214)
2017-08-10 21:41:58 +08:00
Jeremy Grossmann
159d21af9a Merge pull request #2217 from GNS3/fixes-lineitem
Fixes multiselection styles change crash on LineItem (#2216)
2017-08-10 21:39:42 +08:00
ziajka
713feff11f Fixes multiselection styles change crash on LineItem (#2216) 2017-08-10 09:38:22 +02:00
ziajka
64c5ca712e Fixes loading symbols for QEMU at Edit Page (#2214) 2017-08-10 09:09:07 +02:00
Jeremy Grossmann
1572a6f67f Merge pull request #2212 from GNS3/2211
Fixes exception when right click on Dynamips router in the device dock
2017-08-08 22:16:53 +08:00
ziajka
fcee5c6916 Fixes exception when right click on Dynamips router in the device dock (#2211) 2017-08-08 13:59:47 +02:00
grossmj
378d454e1e Move console to all devices icon after the separation bar. Ref #1272 2017-08-08 15:56:22 +08:00
grossmj
eb90950be1 Lock icons. Ref #1134. 2017-08-08 15:46:52 +08:00
Jeremy Grossmann
3d21f9a997 Merge pull request #2210 from CapnCheapo/patch-1
Update frame_relay_switch_configuration_page_ui.py
2017-08-08 11:14:19 +08:00
Jeremy Grossmann
d93ad5e9d5 Merge pull request #2209 from CapnCheapo/2.1
Update frame_relay_switch_configuration_page.ui
2017-08-08 11:14:08 +08:00
Stephen C. Moore
13739281da Update frame_relay_switch_configuration_page_ui.py
Fixes #2205
2017-08-07 14:04:44 -05:00
Stephen C. Moore
1f281a807b Update frame_relay_switch_configuration_page.ui
Fixes #2205
2017-08-07 14:03:00 -05:00
ziajka
2ca250d2c2 Development on 2.1.0dev4 2017-08-04 11:36:47 +02:00
ziajka
b82b031168 Release 2.1.0 beta 1 2017-08-04 11:35:21 +02:00
Julien Duponchelle
c48048f013 Info added to the Nat node
Ref #2197
2017-08-02 13:19:24 +02:00
Julien Duponchelle
9aaca9955a Add missing popup information in cloud and docker node
Fix #2197
2017-08-02 12:14:30 +02:00
Julien Duponchelle
a0e6a82ea2 Handle invalid json in websockets
Fix #2192
2017-08-01 16:32:52 +02:00
Julien Duponchelle
9a3e320e95 Avoid invalid bad request error when receiving partial answer
Fix #2194
2017-08-01 16:29:31 +02:00
Julien Duponchelle
c3fce51493 Catch parse error for broken SVG
Fix #2193
2017-08-01 16:14:08 +02:00
Julien Duponchelle
116cf55758 Filter QXcbConnection log messages
It's Qt noise on Linux we can't do nothing to avoid it.

Fix #2191
2017-08-01 16:14:08 +02:00
Julien Duponchelle
269c6bd0cd Catch class 'PyQt5.QtNetwork.QNetworkReply'> returned a result with an error set
Fix #2195
2017-08-01 16:14:08 +02:00
Julien Duponchelle
31aa612a62 Fix KeyError: 'overlay_notifications'
Fix #2196
2017-08-01 16:14:07 +02:00
ziajka
55f396694f Development on 2.1.0dev3 2017-07-31 11:35:40 +02:00
ziajka
b51fd9c92f Release 2.1.0 alpha 2 2017-07-31 11:31:42 +02:00
Julien Duponchelle
5857d3709b Fix permission error when importing a project on a remote server
Fix #2082
2017-07-27 10:20:28 +02:00
Julien Duponchelle
0c00e1309c Fix RecursionError
Fix #2185
2017-07-26 15:46:40 +02:00
Julien Duponchelle
06dbf9f7d8 Fix 'NodesDockWidget' object has no attribute 'loadPath'
Fix #2182
2017-07-26 14:59:13 +02:00
Julien Duponchelle
ef651d9e9a Fix 'MainWindow' object has no attribute '_settings
Fix #2183
2017-07-26 14:55:13 +02:00
Julien Duponchelle
65dd3a23c6 Fix object has no attribute 'warning_signal'
Fix #2184
2017-07-26 14:53:25 +02:00
Julien Duponchelle
85f697d47b Fix timeout issues when using an appliance 2017-07-26 11:08:39 +02:00
Jeremy Grossmann
0988fdca09 Merge pull request #2180 from GNS3/ubridge_dir
Make sure ubridge path is not a directory
2017-07-25 06:40:36 -07:00
Julien Duponchelle
eba3d5751e Make sure ubridge path is not a directory
Ref https://twitter.com/andreppires/status/889594139800719360
2017-07-25 09:03:57 +02:00
Julien Duponchelle
93e140ae05 2.1.0dev2 2017-07-24 16:19:52 +02:00
Julien Duponchelle
b81a531a7b 2.0.1a1 2017-07-24 16:19:16 +02:00
Jeremy Grossmann
089b4108cc Merge pull request #2179 from GNS3/duplicate
Allow to duplicate a node
2017-07-24 01:39:32 -07:00
grossmj
b89f70370a Updating text for duplicating node/project. 2017-07-24 15:38:54 +07:00
Jeremy Grossmann
81b4ded30a Merge pull request #2174 from GNS3/fix_segfault
Try to fix segfault at exit
2017-07-21 08:44:06 -07:00
Julien Duponchelle
b658eea427 Poll local server return code when waiting for server stop 2017-07-21 13:36:03 +02:00
Julien Duponchelle
da225ffdf9 Try to avoid websocket garbage collection 2017-07-21 13:25:02 +02:00
Jeremy Grossmann
b7fb6e6b13 Merge pull request #2171 from GNS3/fix_wifi_off
Fix issues when Wifi is turned off
2017-07-21 02:50:08 -07:00
Julien Duponchelle
078cef064b Allow to duplicate a node
Ref #1065
2017-07-20 18:05:46 +02:00
Julien Duponchelle
bec1c41f75 Handle recent version of Chicken of VNC
Fix #2146
2017-07-20 16:15:35 +02:00
Julien Duponchelle
64f3516153 Catch unknown protocol errors
The server should use a different port automaticaly.

Fix #2120, #2131
2017-07-20 15:31:02 +02:00
Julien Duponchelle
558e8ad8ce Set main window as parent of LocalServer class 2017-07-20 11:51:05 +02:00
Julien Duponchelle
5f7408809e Fix a race condition when we got a project error 2017-07-20 11:09:38 +02:00
Julien Duponchelle
8359da3c76 Increase timeout before quitting GNS3 because server could be slow to stop 2017-07-20 11:07:11 +02:00
Julien Duponchelle
c613e20971 Try to avoid multiple error dialog in case of network issues 2017-07-20 11:03:39 +02:00
Julien Duponchelle
34ab6c2e1b Try to fix segfault at exit
Fix #2166
2017-07-20 10:46:34 +02:00
Julien Duponchelle
5382a8a397 Fix image permissions
Fix #2169
2017-07-20 09:35:05 +02:00
grossmj
507f104ae5 os.geteuid() doesn't exist on Windows. 2017-07-20 12:15:00 +07:00
Jeremy Grossmann
ada2f647a0 Merge pull request #2170 from GNS3/appliances_dir
Add an appliance templates directory
2017-07-19 22:10:03 -07:00
grossmj
347b76d39e Update text for "My custom appliances" 2017-07-20 12:08:58 +07:00
Jeremy Grossmann
3749819016 Merge pull request #2172 from GNS3/suspend_link
Suspend link
2017-07-20 11:15:28 +07:00
grossmj
4d4871d165 Improve link suspend support. 2017-07-20 11:13:17 +07:00
Julien Duponchelle
59f6a22e81 Suspend link
Fix https://github.com/GNS3/gns3-gui/issues/1295
2017-07-19 17:23:19 +02:00
Julien Duponchelle
0982338e2c Fix tests suite for 2.1 GUI 2017-07-19 15:55:07 +02:00
Julien Duponchelle
20efde749c Turn off timeout for node creation
The timeout is an issue if you use a local GNS3 server and
a remote over a slow link.

Fix https://github.com/GNS3/gns3-server/issues/1126
2017-07-19 15:26:51 +02:00
Julien Duponchelle
23c3576256 Fix docker test env 2017-07-19 15:11:31 +02:00
Julien Duponchelle
1dbf30c6cb Fix issues when Wifi is turned off
Fix #2104
2017-07-19 14:50:40 +02:00
Julien Duponchelle
2081689c12 Change text for my appliances 2017-07-19 13:47:02 +02:00
Julien Duponchelle
983c55928e Add an appliance templates directory
* Settings in general preferences to configure it
* When you import a gns3a the file is copy to this directory
* A filter my appliances is available

Fix https://github.com/GNS3/gns3-gui/issues/2133
2017-07-19 11:55:46 +02:00
Julien Duponchelle
de625d6cfc Allow duplicate name in nodes view if emulator are different
Fix #2158
2017-07-19 09:49:03 +02:00
Jeremy Grossmann
523d791cac Merge pull request #2164 from GNS3/tabs-filters
Tabs in packet filters dialog. Fixes #2159
2017-07-17 21:35:43 +07:00
grossmj
270518f294 Add reset button and tab icons to indicate filter status. 2017-07-17 21:33:55 +07:00
Julien Duponchelle
7ab8d679f7 Fix a rare crash 2017-07-17 12:06:27 +02:00
ziajka
f518464eb2 Tabs in packet filters dialog. Fixes #2159 2017-07-17 10:44:15 +02:00
grossmj
321685acb8 Fixes tests. 2017-07-17 13:25:41 +07:00
grossmj
747ca36a5a Fixes uncaught exception in select server. Fixes #2106. 2017-07-17 12:59:17 +07:00
grossmj
485844f8de Fixes missing "style" in label data. Fixes #2110. 2017-07-17 12:40:14 +07:00
grossmj
b7c0a8c368 Fixes bug when no server selected. Fixes #2163. 2017-07-17 12:25:06 +07:00
grossmj
678c42f941 Fixes uBridge check. Fixes #2143. 2017-07-16 16:56:41 +07:00
Jeremy Grossmann
1eaf6c97e0 Merge pull request #2160 from GNS3/run-as-root
Fixes #2048. Inform the user about running as root, disallow change o…
2017-07-16 12:27:28 +07:00
grossmj
f92282f823 Update message to prevent to run as a user. 2017-07-16 12:26:45 +07:00
ziajka
9ef90210d8 Better os handling and message improvement, fixes #2160 2017-07-14 13:11:41 +02:00
Jeremy Grossmann
f280ea4c68 Merge pull request #2161 from GNS3/fix_2157
Fix Wireshark is restarted when updating packet filters
2017-07-12 22:09:42 +07:00
Julien Duponchelle
0067634990 Fix Wireshark is restarted when updating packet filters
Fix #2157
2017-07-12 16:40:52 +02:00
ziajka
4799fc7c93 Fixes #2048. Inform the user about running as root, disallow change of user and disable crash reports in this case 2017-07-12 14:07:49 +02:00
Jeremy Grossmann
829154fb1c Merge pull request #2156 from GNS3/bpf_filter
BPF filter support
2017-07-12 16:23:48 +07:00
grossmj
7e0caba4b0 Small changes for packet filters Ui. 2017-07-12 16:23:29 +07:00
grossmj
3c3890ff21 Fix typo. 2017-07-12 14:12:48 +07:00
Julien Duponchelle
65411d1742 Merge branch 'master' into 2.1 2017-07-11 17:59:12 +02:00
Julien Duponchelle
146a6a5af2 BPF filter support
Fix #765
2017-07-11 17:28:38 +02:00
grossmj
fc72140402 Bring to front complete (Windows only). Fixes #847. 2017-07-11 21:22:22 +07:00
grossmj
1b13d83e38 New icon for bring to front. Ref #847. 2017-07-11 20:02:43 +07:00
grossmj
e3f073d74b Generic best effort bring console to front for all nodes. Ref #847. 2017-07-11 16:31:18 +07:00
grossmj
8f6e84f8a9 Support bring to front for VMware VMs. Ref #847. 2017-07-11 15:31:42 +07:00
grossmj
c594c3d8a7 Fixes bring to front for VirtualBox VMs. Ref #847. 2017-07-11 14:30:26 +07:00
Jeremy Grossmann
a550527e6d Merge pull request #2153 from GNS3/idlepc_apicall
Idlepc apicall
2017-07-10 11:33:26 +07:00
Jeremy Grossmann
0ce377f321 Merge pull request #2145 from GNS3/preserve-file-permissions
Preserve permissions while copying files. Fixes #2125.
2017-07-08 21:56:50 +07:00
grossmj
ab37a6237c Fix small bug when not capturing/filtering on a link. 2017-07-08 21:47:30 +07:00
Jeremy Grossmann
ecc57133c6 Merge pull request #2139 from GNS3/filters
Filter packet interface
2017-07-08 18:51:50 +07:00
grossmj
fc6c2c0304 Filter icons and bug fixes for topology summary view. 2017-07-08 18:46:31 +07:00
Julien Duponchelle
92c731a9c9 Merge pull request #2151 from GNS3/improve-tpl-error
Fixes #2122. Warning dialog on Win and Mac when user has not choice.
2017-07-07 16:58:42 +02:00
Julien Duponchelle
bc433e5281 Merge pull request #2152 from GNS3/bugfix-2121
New appliance - case without versions in file. Fixes #2121
2017-07-07 16:58:04 +02:00
Julien Duponchelle
21eb0b0f03 Call the new api for getting IDLE PC values
Ref #2103
2017-07-07 16:41:17 +02:00
ziajka
3f70d0238f New appliance - case without versions in file. Fixes #2121 2017-07-07 12:59:41 +02:00
ziajka
8fd3f67378 Fixes #2122. Warning dialog on Win and Mac when user has not choice. 2017-07-07 11:54:27 +02:00
Julien Duponchelle
4e9cb90468 Remove dead code 2017-07-07 11:10:40 +02:00
Julien Duponchelle
d38e62fa38 Renable auth
Fix #2148
2017-07-07 11:09:39 +02:00
Julien Duponchelle
4b7df545aa Test if auth is enabled
Ref #2148
2017-07-07 10:20:22 +02:00
grossmj
6af5f5f3fb Stop all packet filters from the topology summary view. 2017-07-07 14:12:36 +07:00
Julien Duponchelle
b9318dfe6a Merge pull request #2140 from GNS3/bugfix-2137
Fixes #2137
2017-07-07 09:01:32 +02:00
Julien Duponchelle
6ffc2c807b Merge pull request #2144 from GNS3/bugfix-2129
Bugfix 2129 - ValueError: stat: path too long for Windows
2017-07-07 09:00:51 +02:00
grossmj
d177ea44bd Change the way the help is displayed for filter dialog. 2017-07-06 20:40:55 +07:00
ziajka
39f3b22817 Removed initial checks in tests due to Windows 2017-07-06 14:53:44 +02:00
ziajka
d157295550 Preserve permissions while copying files. Fixes #2125. 2017-07-06 14:47:08 +02:00
ziajka
d7b9465850 Typo. Fixes #2129 2017-07-06 13:30:59 +02:00
ziajka
0766dac62b Handle ValueError on Windows during checking path with SVG data. Fixes #2129 2017-07-06 13:29:34 +02:00
ziajka
4f81dde2fd Checking if new project dialog is already open, #2140 2017-07-06 11:47:58 +02:00
Julien Duponchelle
4a716000ff Do not crash if zoom is None 2017-07-06 09:58:13 +02:00
Jeremy Grossmann
d8b0e9234e Merge pull request #2134 from GNS3/use_websocket_for_notification
Use websocket for notifications
2017-07-05 15:42:50 +07:00
Julien Duponchelle
bf0af2a929 Cleanup double include of QtWebsockets 2017-07-05 10:33:48 +02:00
Jeremy Grossmann
a05e47a4d2 Merge pull request #2135 from GNS3/bugfix-725
Bugfix 725 (IPV6)
2017-07-05 14:47:56 +07:00
grossmj
996c5c927c Fix call to protocol() and add :: IPv6 address. 2017-07-05 14:47:07 +07:00
Julien Duponchelle
dab7569575 Fix compatibility with Qt version before 5.6 2017-07-04 18:24:50 +02:00
Julien Duponchelle
2a0e8a3b4f Merge pull request #2138 from GNS3/bugfix-1095
Bugfix 1095
2017-07-04 15:20:42 +02:00
ziajka
872e7199e4 Fixes #2137 2017-07-04 15:14:15 +02:00
Julien Duponchelle
67b57a8d78 Filter packet interface
Ref #765
2017-07-04 15:05:41 +02:00
ziajka
ba3c1e6969 Added protocol filtering on available server bind addresses 2017-07-04 14:00:33 +02:00
ziajka
1879172505 Persistent zoom level - refactor 2017-07-04 09:33:25 +02:00
ziajka
22fe51fe5a Show interface labels - persistance 2017-07-04 08:36:37 +02:00
ziajka
b5ac40896f Snap to grid persistance 2017-07-04 08:27:54 +02:00
ziajka
2d6b53245b Show the grid - save the state 2017-07-04 08:14:19 +02:00
ziajka
eee377c4fc Show layers persistent state 2017-07-03 15:09:12 +02:00
ziajka
c34b82c255 State of the zoom settings 2017-07-03 10:40:23 +02:00
grossmj
c750ce8d80 Add QtWebsockets dependency. 2017-06-30 17:49:30 +08:00
ziajka
2d2e682540 Add warning when user tries to run vncviewer on IPv6 host 2017-06-30 10:19:07 +02:00
Julien Duponchelle
e06cf5b9a1 Use websocket for notifications
Fix #2127
2017-06-29 10:58:06 +02:00
ziajka
d25258c47f IPV6 support for spice client 2017-06-28 15:50:25 +02:00
grossmj
1e40a36a48 Delete duplicated code. 2017-06-28 17:20:25 +08:00
Jeremy Grossmann
d5059d22fc Merge pull request #2119 from GNS3/drop_trusty
Drop support for Qt before 5.5 (ubuntu trusty)
2017-06-24 13:54:29 +02:00
grossmj
bae61bdcaa Allow IOU 64-bit images. 2017-06-23 12:00:33 +02:00
Julien Duponchelle
eb44226ee4 Drop support for Qt before 5.5 (ubuntu trusty)
Fix #2080
2017-06-22 14:32:53 +02:00
Jeremy Grossmann
8ee251cbb2 Merge pull request #2087 from GNS3/ethernet_switch_console
Console for ethernet switch
2017-06-21 23:53:07 +02:00
Julien Duponchelle
a84e081a75 Merge pull request #2116 from GNS3/spice-feature
Spice support
2017-06-21 11:56:15 +02:00
ziajka
d92db4e99d Spice support
* SPICE console type for QEMU settings pages
* SPICE settings tab at General Preferences
* Executing SPICE console type
* Preconfigured SPICE client for Windows
* SPICE commands for Win and Mac
2017-06-21 11:21:33 +02:00
Julien Duponchelle
873e04ed9d Merge branch 'master' into 2.1 2017-06-21 10:39:10 +02:00
Julien Duponchelle
c0c41b99eb Merge pull request #2114 from GNS3/revert-2112-spice-feature
Revert "Spice feature"
2017-06-21 10:31:21 +02:00
Julien Duponchelle
12b694047a Revert "Spice feature" 2017-06-21 10:30:49 +02:00
Julien Duponchelle
59651a3fe5 Merge pull request #2112 from GNS3/spice-feature
Spice feature
2017-06-21 10:29:58 +02:00
ziajka
02ad5d2f3a SPICE commands for Win and Mac 2017-06-20 12:37:44 +02:00
ziajka
a31b98f781 Preconfigured SPICE client for Windows 2017-06-20 10:18:25 +02:00
ziajka
e9a674c4e9 Executing SPICE console type 2017-06-16 14:16:54 +02:00
ziajka
4b383e2b06 SPICE settings tab at General Preferences 2017-06-16 11:11:40 +02:00
ziajka
6d2ca353a3 SPICE console type for QEMU settings pages 2017-06-16 10:57:00 +02:00
ziajka
d8b5caf679 Ignore env directory inside the project 2017-06-16 10:27:24 +02:00
Bernhard Ehlers
d61088e3a7 Sync appliance.json with gns3-registry repository
Fix #2107

Signed-off-by: Julien Duponchelle <julien@gns3.net>
2017-06-15 15:39:08 +02:00
Julien Duponchelle
a3f0569663 2.0.4dev1 2017-06-13 10:34:20 +02:00
Julien Duponchelle
31e82bb410 2.0.3 2017-06-13 10:33:13 +02:00
Julien Duponchelle
cab3baf2c6 Cleanup 2017-06-12 16:04:11 +02:00
grossmj
55b80cc9cb Merge remote-tracking branch 'origin/2.1' into 2.1 2017-06-09 22:37:29 +02:00
grossmj
aec6c37016 Do not enable authentication by default. 2017-06-09 22:37:10 +02:00
Julien Duponchelle
574da9c80a Display error when we can't export files
Fix #2097, #2098
2017-06-09 15:06:33 +02:00
Julien Duponchelle
117f6ec3b1 Merge branch '2.1' into ethernet_switch_console 2017-06-09 14:30:39 +02:00
Julien Duponchelle
574d6b3792 Merge branch 'master' into 2.1 2017-06-09 14:16:17 +02:00
Julien Duponchelle
8321883199 Fix auth header not sent is some conditions
Fix #2099
2017-06-09 14:12:38 +02:00
Julien Duponchelle
9608614aa9 Merge branch 'master' into 2.1 2017-06-09 11:39:24 +02:00
Julien Duponchelle
98e4aefa65 If we have auth issue at server startup continue to get better error 2017-06-09 11:37:54 +02:00
Julien Duponchelle
67d816baa3 Do not override IOU configuration file when you change the image
Fix #2091
2017-06-08 16:20:04 +02:00
Julien Duponchelle
13a8bd4500 Fix some PNG loading issues on Windows
Fix #2085
2017-06-08 14:59:47 +02:00
Julien Duponchelle
802b80b764 Handle label with missing elements
Fix #2096
2017-06-07 19:02:38 +02:00
Julien Duponchelle
fe5f80382a Merge branch '2.1' into ethernet_switch_console 2017-06-07 18:30:42 +02:00
Julien Duponchelle
a4ed59200d Merge branch 'master' into 2.1 2017-06-07 18:28:54 +02:00
Julien Duponchelle
59292ff6cb Support floating value for font size
Fix #2092
2017-06-07 16:34:05 +02:00
Julien Duponchelle
7810d19f4d Handle partial json in a response
Fix #2093
2017-06-07 14:49:31 +02:00
ziajka
0788ce569f Extended 'Thanks to' section - tab selection on first element 2017-06-06 16:14:53 +02:00
ziajka
4b0379892d Extended section 2017-06-06 15:55:15 +02:00
Julien Duponchelle
3ca05c7427 Console for ethernet switch
Ref https://github.com/GNS3/gns3-server/issues/454
2017-05-31 13:23:37 +02:00
Julien Duponchelle
6a16bcedc0 Reduce debug noise 2017-05-31 12:05:48 +02:00
Julien Duponchelle
8f8994e7df 2.0.3dev1 2017-05-30 09:10:54 +02:00
Julien Duponchelle
4e172fc7e3 2.0.2 2017-05-30 09:02:02 +02:00
Julien Duponchelle
56ebfc7fd0 Drop SSL support
Fix #1022
2017-05-26 15:52:09 +02:00
Julien Duponchelle
8ed8a2c115 Show a default symbol in case of corrupted file
Fix https://github.com/GNS3/gns3-server/issues/1043
2017-05-24 12:26:18 +02:00
Julien Duponchelle
073665a75d When another gui is already running exit instead of proper close to avoid any issue
Fix #2059
2017-05-23 18:00:02 +02:00
Julien Duponchelle
4ccc67aa46 Fix duplicate on remote server use wrong location
Fix https://github.com/GNS3/gns3-server/issues/1040
2017-05-23 17:25:29 +02:00
Julien Duponchelle
6e2632e91f Display the location of settings when we disallow opening due to old release 2017-05-23 15:54:35 +02:00
Julien Duponchelle
38ddcde902 Improve search for dynamips in development on OSX 2017-05-23 14:24:54 +02:00
Julien Duponchelle
436563afcb Merge pull request #2079 from GNS3/pyup-update-pytest-3.0.7-to-3.1.0
Update pytest to 3.1.0
2017-05-23 08:29:55 +02:00
pyup-bot
7eaab3e38b Update pytest from 3.0.7 to 3.1.0 2017-05-23 02:25:48 +02:00
Julien Duponchelle
0927a2a8c9 Fix error display when loading a .png custom symbol 2017-05-22 13:38:04 +02:00
Julien Duponchelle
87e6159ff6 Fix a crash in the progress dialog
Fix #2064
2017-05-22 09:56:31 +02:00
Julien Duponchelle
effdcf5e24 Fix a race condition when exporting a closed project
Fix #2078
2017-05-22 09:54:17 +02:00
Julien Duponchelle
021cdd2e65 Fix RuntimeError: wrapped C/C++ object of type NodeItem has been deleted
Fix #2070
2017-05-19 17:39:34 +02:00
Julien Duponchelle
9b559d43be Fix duplicate node in node view
Fix #2004
2017-05-19 17:22:29 +02:00
grossmj
ad7d06ef21 Fixes typo. 2017-05-19 00:06:50 +02:00
Julien Duponchelle
b88bf71be9 Clean IOU code
Ref https://github.com/GNS3/gns3-gui/issues/2065
2017-05-18 17:13:11 +02:00
Julien Duponchelle
3b019edc82 Avoid an error when downloading symbols not available 2017-05-16 11:22:06 +02:00
grossmj
f3504809ed Bring VirtualBox and VMware VM window to front on Windows. Ref #847. 2017-05-16 11:14:53 +02:00
Julien Duponchelle
23735f35ad Rename linked_base to linked_clone
Ref https://github.com/GNS3/gns3-server/issues/1034
2017-05-16 10:28:11 +02:00
Julien Duponchelle
3adc46fbe2 Merge branch '2.0' into 2.1 2017-05-16 09:31:28 +02:00
Julien Duponchelle
363c4a9966 2.0.2dev1 2017-05-16 09:15:18 +02:00
Julien Duponchelle
7082c75511 2.0.1 2017-05-16 08:48:56 +02:00
Julien Duponchelle
8a303e4563 Merge branch '2.0' into 2.1 2017-05-16 08:38:43 +02:00
Julien Duponchelle
842ad8ae26 Merge branch '2.0' into 2.1 2017-05-15 16:07:32 +02:00
grossmj
16c4a837d7 Improve inline help. Fixes #1999.
Add a warning about wifi interfaces in the cloud. Fixes #1902.
2017-05-14 22:18:35 +02:00
grossmj
fd42ac410c Copy remote directory path into clipboard in "Show in FileManager". Fixes #1966. 2017-05-12 16:49:26 +08:00
Jeremy Grossmann
6efc177804 Merge pull request #2054 from GNS3/export_thread
Do not run import / export of project in seperate thread
2017-05-12 10:23:25 +08:00
Julien Duponchelle
6f9e6c9b92 Fix display of error in progress dialog when we don't have thread 2017-05-11 17:48:38 +02:00
Jeremy Grossmann
0411c68150 Merge pull request #2057 from GNS3/lost_slot_and_port
Fix lost slot and port in dynamips settings
2017-05-11 23:37:39 +08:00
Julien Duponchelle
4246e731e5 Fix lost slot and port in dynamips settings
When you reopen a project you no longer have the
wic and slot, until you move the node and retrieve an
update. The settings is just lost in the GUI but is fine
on server.

Fix #2053
2017-05-11 09:49:47 +02:00
Julien Duponchelle
50cca71279 Do not run import / export of project in seperate thread
This trigger warning because you need to do the HTTP request
to the API from the main thread.

Fix #2008
2017-05-10 18:13:45 +02:00
Julien Duponchelle
c78ef8f348 Assert when running an HTTP query outside the main thread
Ref #2008
2017-05-10 17:57:02 +02:00
Julien Duponchelle
c03a5a9e0a Proper error when you try to load the pid file as config file
Fix #2044
2017-05-09 17:27:38 +02:00
Julien Duponchelle
c93b7836d8 Log malformed svg text item
Fix #2045
2017-05-09 17:14:02 +02:00
Julien Duponchelle
690b22cc24 Fix a race condition when right click and delete a node at the same time
Fix #2043
2017-05-09 17:03:23 +02:00
Julien Duponchelle
3560251816 Fix a race condition when snapshoting a closed project
Fix #2046
2017-05-09 16:37:42 +02:00
Jeremy Grossmann
90e861289f Merge pull request #2016 from GNS3/missing_xattr
Catch missing function listxattr on some linux host
2017-05-08 21:04:47 +07:00
Jeremy Grossmann
6e144d6122 Update doctor_dialog.py 2017-05-08 21:04:01 +07:00
grossmj
2f168193d1 Catch remaining missing function listxattr on some Linux host. 2017-05-08 21:01:27 +07:00
Jeremy Grossmann
0fe5559564 Merge pull request #2007 from GNS3/fix_project_close
Fix project closing when we have multiple client connected
2017-05-08 20:42:35 +07:00
Julien Duponchelle
37f0744d7c Fix a race condition when creating node and closing project
Fix #2018
2017-05-05 19:04:06 +02:00
Julien Duponchelle
000f4a4790 Fix Bug with python before 3.4.3
Fix #2035
2017-05-05 18:58:40 +02:00
Julien Duponchelle
a09b7d6738 Fix error if you put a path in a .gns3a file for qemu
Fix #2038
2017-05-05 18:31:13 +02:00
Julien Duponchelle
a1fa8f9ec2 Fix AttributeError: 'NoneType' object has no attribute '_refreshVisibleWidgets'
Fix #2034
2017-05-05 18:29:36 +02:00
Jeremy Grossmann
cd6b0b793e Merge pull request #2009 from GNS3/dissalow_gns3_on_remote
Disallow opening a .gns3 on a remote server
2017-05-05 20:53:29 +07:00
Jeremy Grossmann
6453932421 Update main_window.py 2017-05-05 20:52:03 +07:00
Julien Duponchelle
37a23d9682 Do not crash if the logging code raise an exception
Fix #2017
2017-05-04 12:18:26 +02:00
Julien Duponchelle
e18e10c701 Fix some crash in dynamips device preference page
Fix #2029
2017-05-04 12:02:49 +02:00
Julien Duponchelle
a9240e2e46 Fix warning when loading IOU images on Windows
Fix #2012
2017-05-04 10:43:13 +02:00
Julien Duponchelle
4df0c33013 Do not crash if you don't have configure a packet capture program on Windows
Fix #2026
2017-05-04 10:38:35 +02:00
Julien Duponchelle
4096316ceb Ignore error when we can't kill the packet capture
The user probalby manually kill it.

Fix #2013
2017-05-04 10:30:41 +02:00
Julien Duponchelle
e09292c647 Fix AttributeError: 'NoneType' object has no attribute 'wasCanceled'
Fix #2023
2017-05-04 10:27:45 +02:00
Julien Duponchelle
31c37161fa Fix RuntimeError: wrapped C/C++ object of type QComboBox has been deleted
Fix #2027
2017-05-04 10:25:46 +02:00
Julien Duponchelle
a047cd7f4c Fix RuntimeError: wrapped C/C++ object of type QTreeWidgetItem has been deleted
Fix #2028
2017-05-04 10:13:33 +02:00
Julien Duponchelle
87cde665a8 Fix detection of https when use for the local server
Ref #995
2017-05-03 17:23:03 +02:00
Julien Duponchelle
6361c94bbe Silent the _COMPIZ_TOOLKIT_ACTION warning
This a Qt bug.

Fix #2020
2017-05-03 15:54:55 +02:00
Julien Duponchelle
8a0aeff0bb Cacth TypeError: native Qt signal is not callable
Fix #2011
2017-05-03 10:58:38 +02:00
Julien Duponchelle
508f8b3ad5 Fix AttributeError: 'C7200' object has no attribute 'warning_signal'
Fix #2014
2017-05-03 10:51:12 +02:00
Julien Duponchelle
bfe942c029 Catch missing function listxattr on some linux host
Fix #2010
2017-05-03 10:47:22 +02:00
Julien Duponchelle
b3a86594ff 2.0.1dev1 2017-05-03 10:19:25 +02:00
Julien Duponchelle
debe88bd37 2.0.0 2017-05-02 10:14:01 +02:00
Julien Duponchelle
a948fd07b1 Disallow opening a .gns3 on a remote server
This prevent opening a local .gns3 on a remote server.
Because this is not working you need to import the
project on the server using portable project.

Fix https://github.com/GNS3/gns3-server/issues/984
2017-05-02 09:27:40 +02:00
Julien Duponchelle
072f714e21 Fix project closing when we have multiple client connected
In all case when we close the main window we let the server
manage if he need to close or not the project.

Fix https://github.com/GNS3/gns3-server/issues/991
2017-05-02 09:07:14 +02:00
Julien Duponchelle
466c349642 Remove log noise 2017-04-28 12:51:26 +02:00
Julien Duponchelle
1356fd9c69 Reduce log info noise 2017-04-27 15:46:39 +02:00
Julien Duponchelle
2d1c9444c5 Delete noise 2017-04-27 15:13:56 +02:00
Julien Duponchelle
22d7815d8e Fix can't drag VPCS to topology
Fix #2001
2017-04-27 14:28:58 +02:00
Julien Duponchelle
53487d5937 Merge branch '2.0' into 2.1 2017-04-27 10:56:41 +02:00
Julien Duponchelle
a2059d3e7c Clarify that we don't override vmware custom adapters 2017-04-27 10:06:52 +02:00
Julien Duponchelle
ab729d8f67 Close the program if you close the profile select dialog
Fix #1922
2017-04-26 17:05:16 +02:00
Julien Duponchelle
eb5c10de3d Support node uuid is telnet console parameter
Fix #1918
2017-04-26 16:19:59 +02:00
Julien Duponchelle
c4cc819d50 Strip space from path at project creation
Fix #1997
2017-04-21 14:49:52 +02:00
Julien Duponchelle
0796d9aae5 2.0.0dev13 2017-04-20 10:57:28 +02:00
Julien Duponchelle
c8148c1877 2.0.0rc4 2017-04-20 10:56:55 +02:00
Julien Duponchelle
1b6d534b8e Merge branch '2.0' into 2.1 2017-04-20 10:30:58 +02:00
Julien Duponchelle
d6021afa0f Catch all error during the generation of log messages.
This prevent error loop is something goes wrong.

Fix #1993
2017-04-20 09:26:57 +02:00
Julien Duponchelle
9018bdac07 Remove no longer working capturelog plugin for pytest 2017-04-19 09:41:56 +02:00
Julien Duponchelle
a48b898d92 Catch a rare node creation error
Fix #1991
2017-04-19 09:39:32 +02:00
Julien Duponchelle
949c1bbe37 Fix missing menu text at application startup
Fix #1990
2017-04-19 09:35:31 +02:00
Julien Duponchelle
0089edecc0 Run test on windows also 2017-04-18 16:48:45 +02:00
Julien Duponchelle
91da1d492b Fix a race condition in the drawing item
Fix #1987
2017-04-18 11:32:33 +02:00
Julien Duponchelle
0242f53c17 Catch system error when connecting to local server
Fix #1988
2017-04-18 11:29:42 +02:00
Julien Duponchelle
bab7a1016f Catch a rare error when killing the capture
Fix #1985
2017-04-14 10:39:43 +02:00
Julien Duponchelle
2ec91e1ef7 Improve pcap streaming speed
Fix #1982
2017-04-14 10:30:49 +02:00
Julien Duponchelle
38af30ec15 Merge branch 'master' into 2.0 2017-04-14 09:04:17 +02:00
Julien Duponchelle
3f8a0cb527 Merge master 2017-04-14 09:03:08 +02:00
Julien Duponchelle
fd1a86df03 1.5.5dev1 2017-04-14 09:00:57 +02:00
Julien Duponchelle
c954a16ead 1.5.4 2017-04-13 17:27:37 +02:00
Julien Duponchelle
9418b997eb Mac Qt wheel is not working in our build envirronement 2017-04-13 16:07:52 +02:00
Julien Duponchelle
9682cad4f4 Add security issues section 2017-04-13 12:37:34 +02:00
Julien Duponchelle
60ee9e1374 Limit ubridge permission to the admin group on OSX 2017-04-13 10:04:08 +02:00
Julien Duponchelle
dbd5b9366a Upgrade to 5.7.1 2017-04-13 10:01:40 +02:00
Julien Duponchelle
f63314d4d0 Fix version number 2017-04-13 09:56:17 +02:00
Julien Duponchelle
a9b5b9eda2 Merge pull request #1906 from GNS3/appliances_api
Move appliances management to the server
2017-04-12 14:36:10 +02:00
Julien Duponchelle
96eaec0100 Recent projects list bug
Fix #1976
2017-04-10 17:59:17 +02:00
Julien Duponchelle
5d554976e2 Fix a race condition in the preferences dialog
Fix #1981
2017-04-10 11:42:13 +02:00
Julien Duponchelle
d1d8390b73 Try to fix some windows Z issues
Fix #1955
2017-04-07 11:06:51 +02:00
Julien Duponchelle
5f3f6462c2 Catch a garbage collection issue in the right click on a link 2017-04-03 16:33:14 +02:00
Julien Duponchelle
821809bf6f Fix a compatibility issue with Python 3.4
Fix #1973
2017-03-31 19:30:32 +02:00
Julien Duponchelle
a712fab7a4 2.0.0dev12 2017-03-31 09:44:27 +02:00
Julien Duponchelle
4ab21ea9f9 2.0.0rc3 2017-03-31 09:41:48 +02:00
Julien Duponchelle
ce12eb86e8 Merge branch '2.0' into 2.1 2017-03-30 10:07:55 +02:00
Julien Duponchelle
1a4902279b Check hibernation only if it's a remote main server
Fix #1971
2017-03-29 17:19:00 +02:00
Julien Duponchelle
35412171b9 Improve timeout handling
Ref #1959
2017-03-29 12:34:10 +02:00
Julien Duponchelle
73939847b9 Improve logging when we display a qt message box
Ref #1959
2017-03-29 12:12:22 +02:00
Julien Duponchelle
5acfc5bc56 Fix a problem with settings not pushed to the server 2017-03-28 16:22:17 +02:00
Julien Duponchelle
d67d0d146f Try to detect computer hibernation
I'm not really happy with the patch but it the most simple way
I found. If between two request we have more than 120 seconds
of differences we disconnect.

Fix #1968
2017-03-28 14:41:43 +02:00
Julien Duponchelle
23da6a4c31 Fix crash when we send some errors to the user console 2017-03-27 18:16:11 +02:00
Julien Duponchelle
fd5f999756 Use QtFile for managing file capture
This prevent application freeze when we run a capture.

Fix #1959
2017-03-27 14:19:07 +02:00
Julien Duponchelle
c05304b86f Allow to delete a profile from the profile select dialog
Fix #1961
2017-03-27 10:26:29 +02:00
Julien Duponchelle
6361980591 Filter hidden folder in the profil directory
Fix #1960
2017-03-23 12:02:32 +01:00
Julien Duponchelle
d5ea98ba2a Prevent user putting port in the remote host name
Fix #1948
2017-03-22 11:56:27 +01:00
Julien Duponchelle
3ca01384c9 Fix RuntimeError: wrapped C/C++ object of type EllipseItem has been deleted
Fix #1957
2017-03-21 18:19:47 +01:00
Julien Duponchelle
f35bb6a281 Fix a rare error in LinkItem
Fix #1950
2017-03-21 16:56:23 +01:00
Julien Duponchelle
0c4a7693e6 Fix Image field in nodes list is stale after changing an image
Fix #1956
2017-03-21 16:54:10 +01:00
Julien Duponchelle
20506525c5 Fix RuntimeError: Set changed size during iteration
Fix #1951
2017-03-21 15:13:49 +01:00
Julien Duponchelle
bb00a9f64c Better detection of remote server changes
Fix #1949
2017-03-21 14:38:20 +01:00
Julien Duponchelle
ef36792379 Add a notice about the fact you need to apply server settings
Fix #1952
2017-03-21 11:35:03 +01:00
Julien Duponchelle
873fd409bd Check python version only for setup.py install 2017-03-21 10:10:14 +01:00
Julien Duponchelle
03221e8ab7 Fix refresh issue with link in topology summary
Fix #1938
2017-03-20 18:24:16 +01:00
Julien Duponchelle
55f9836dc9 Remove duplicate code 2017-03-20 17:34:17 +01:00
Julien Duponchelle
3ab5144fe2 Catch appliance error when creating an appliance new version
Fix #1941
2017-03-20 17:10:49 +01:00
Julien Duponchelle
c91a22c9f8 If a node can't be deleted do not remove it
Fix #1933
2017-03-16 19:42:38 +01:00
Julien Duponchelle
a8ba909568 If something is wrong during packet capture do not disconnect us from the server
Fix #1520
2017-03-16 18:14:55 +01:00
Julien Duponchelle
d33e9ed833 If something is wrong during packet capture do not disconnect us from the server
Fix #1520
2017-03-16 14:37:32 +01:00
Julien Duponchelle
aa31af1dca Fix saving dynamips
Fix #1939
2017-03-16 14:33:16 +01:00
Julien Duponchelle
4d07a7391f Try to fix the hang dialog on some computers
Ref #1915
2017-03-16 12:19:09 +01:00
Julien Duponchelle
417395718d Fix a rare crash in progress dialog 2017-03-15 16:36:13 +01:00
Julien Duponchelle
212048c4d1 If we pass --profile skip the profile select dialog
Fix #1934
2017-03-15 16:09:35 +01:00
Julien Duponchelle
11c27063b4 Raise an error if the progress dialog is not created from the main thread
Ref #1915
2017-03-15 15:14:12 +01:00
Julien Duponchelle
b8696fa54e Log qt log to python log 2017-03-15 14:50:19 +01:00
Julien Duponchelle
ba9785f83f Revert "Rollback to Qt 5.7.1"
This reverts commit 5038a72610.
2017-03-15 14:46:57 +01:00
Julien Duponchelle
4ae742529c Fix image are not uploaded to remote main server
Fix #1926, #1927, #1925
2017-03-15 14:33:25 +01:00
Julien Duponchelle
92cc335708 Fix race condition when editing a project
Fix #1932
2017-03-15 14:30:00 +01:00
Julien Duponchelle
2099a4ae9a Poll settings each 5 seconds
Fix #1923, #1924
2017-03-15 12:55:14 +01:00
Julien Duponchelle
5038a72610 Rollback to Qt 5.7.1
Ref #1915
2017-03-15 11:51:22 +01:00
Julien Duponchelle
b9e320996b Merge pull request #1935 from GNS3/pyup-update-pytest-3.0.6-to-3.0.7
Update pytest to 3.0.7
2017-03-15 10:20:50 +01:00
pyup-bot
9c86cd71c8 Update pytest from 3.0.6 to 3.0.7 2017-03-14 23:53:42 +01:00
Julien Duponchelle
7fdf42b442 Avoid progress dialog not disapear
Fix #1915
2017-03-14 15:40:04 +01:00
Julien Duponchelle
61d86e919e Remove wrong mention about the fact super putty is include 2017-03-14 12:02:02 +01:00
Julien Duponchelle
bc71985ee3 Avoid a crash when an ios router don't have a chassis
Fix #1920
2017-03-13 17:25:58 +01:00
Julien Duponchelle
6bebf2d14d Fix a potentatial crash in the progress dialog
Fix #1919
2017-03-13 17:16:34 +01:00
Julien Duponchelle
490021aa47 Fix appliance file 2017-03-13 15:48:59 +01:00
Julien Duponchelle
c8db5e7e49 2.0.0 dev 11 2017-03-13 15:42:06 +01:00
Julien Duponchelle
8efaacbc3d Support official docker images in appliances 2017-03-13 15:41:14 +01:00
Julien Duponchelle
c5da24b954 2.0.0rc2 2017-03-10 20:40:10 +01:00
Julien Duponchelle
4456cfd68e Merge branch 'master' into 2.0 2017-03-10 20:39:03 +01:00
Julien Duponchelle
3468909db1 Deploy on pypi when we tag 2017-03-10 20:37:57 +01:00
Julien Duponchelle
212728eb94 Fix rare crash in GNS3 VM preference page
Fix #1912
2017-03-09 10:51:38 +01:00
Julien Duponchelle
cf4f73a7e1 Fix an error on Windows when loading SVG files
Fix #1913
2017-03-09 10:25:18 +01:00
Julien Duponchelle
d4ffbd9f97 Fix an error on Windows when loading SVG files
Fix #1913
2017-03-09 10:10:06 +01:00
Julien Duponchelle
4c01a465ac Merge branch '2.0' into 2.1 2017-03-08 18:14:32 +01:00
Julien Duponchelle
5948e5c4cb Prevent a potential crash 2017-03-08 18:12:46 +01:00
Julien Duponchelle
791aa27158 Workaround a rare crash when sending analytics
It seem PyQT is confuse between the signal and error function.

Fix #1861
2017-03-08 14:52:47 +01:00
Julien Duponchelle
0b8ab56ffc Catch error when you try to create a node a not existing server
Fix #1905
2017-03-08 14:44:30 +01:00
Julien Duponchelle
12dcfda756 Fix an error when your local server crash and computer return non unicode
Fix #1904
2017-03-08 14:40:29 +01:00
Julien Duponchelle
ef44beac41 Fix KeyError: 'slot1'
Fix #1907
2017-03-08 09:54:17 +01:00
Julien Duponchelle
97a71904f7 Fix a rare crash in import appliance
Fix #1908
2017-03-08 09:53:27 +01:00
Julien Duponchelle
012bc1e406 Display the appliances in the application
Ref #1045
2017-03-07 18:10:15 +01:00
Julien Duponchelle
94f4059d67 Rollback to PyQT 5.8 because 5.8.1 seem to have trouble at install 2017-03-07 15:49:26 +01:00
Julien Duponchelle
14ed2546bc Merge pull request #1903 from GNS3/pyup-update-pyqt5-5.8-to-5.8.1
Update pyqt5 to 5.8.1
2017-03-07 13:25:40 +01:00
pyup-bot
908258c163 Update pyqt5 from 5.8 to 5.8.1 2017-03-07 12:09:10 +01:00
Julien Duponchelle
05ba772715 Remove log noise 2017-03-07 10:30:59 +01:00
Jeremy Grossmann
9ea57f511b Merge pull request #1830 from GNS3/applicance_in_nodes
Display the appliances in the application
2017-03-06 19:49:48 -07:00
grossmj
5aaa2d7280 Some tweaks for appliance wizard. 2017-03-07 08:40:56 +08:00
Julien Duponchelle
704191ba25 2.0.0 dev 10 2017-03-06 19:42:25 +01:00
Julien Duponchelle
be7fc9abe2 2.0.0rc1 2017-03-06 19:39:46 +01:00
Julien Duponchelle
e0daf1dbb1 Fix syntax error 2017-03-01 09:04:05 +01:00
Julien Duponchelle
a8877d4f8a UltraVNC support 2017-02-28 18:08:48 +01:00
Julien Duponchelle
497eb19369 Fix a resize notifications dialog for the first notification 2017-02-28 17:42:23 +01:00
Julien Duponchelle
70049aa877 Merge branch '2.1' into applicance_in_nodes 2017-02-28 15:59:52 +01:00
Julien Duponchelle
ece7930cb1 Merge branch '2.0' into 2.1 2017-02-28 15:59:29 +01:00
Julien Duponchelle
2db850a3f3 Fix tests 2017-02-28 15:58:25 +01:00
Julien Duponchelle
c7df589857 Fix noisy dialog and an error with right click 2017-02-28 15:37:15 +01:00
Julien Duponchelle
8bcc92f319 Merge branch '2.1' into applicance_in_nodes 2017-02-28 15:03:28 +01:00
Julien Duponchelle
dedde63b60 Merge branch '2.0' into 2.1 2017-02-28 14:10:07 +01:00
Julien Duponchelle
ec7cdedb86 Display less noisy dialog when we can't connect to the remote server
Fix #1887
2017-02-28 14:06:52 +01:00
Julien Duponchelle
606fa15a55 Prevent the usage of gns3vm as a remote server name 2017-02-28 13:50:31 +01:00
Jeremy Grossmann
3eca9b0e54 Merge pull request #1881 from GNS3/catch_local_process_errors
Monitor and display local server stderr
2017-02-28 02:46:27 +08:00
Julien Duponchelle
3abaf74580 Fix the VMware wizard for not using a remote server by default
Fix #1893
2017-02-27 19:00:02 +01:00
Julien Duponchelle
9713748633 Prevent the GNS3 VM to appear in remote compute in the VM wizard
Fix #1894
2017-02-27 18:08:34 +01:00
Julien Duponchelle
405e86aff4 Remove iouyap settings
Fix #1892
2017-02-27 15:26:05 +01:00
Julien Duponchelle
4da824dc2b Fix missing permission error management
Fix #1888
2017-02-24 09:49:10 +01:00
Julien Duponchelle
0ec177c644 Avoid a crash when create a new dynamips version in the appliance wizard
Fix #1884
2017-02-23 15:13:00 +01:00
Julien Duponchelle
9ef4f86050 Disallow user to add the same server as a remote server and as local server
Fix #1883
2017-02-23 11:13:14 +01:00
Julien Duponchelle
96b830817e Fix 'module' object has no attribute 'run'
Fix #1878
2017-02-23 09:11:31 +01:00
Julien Duponchelle
0db8b00fb9 Monitor and display local server stderr
It's the best solution I found. Streaming in real time
the log will require to start an aditionnal thread

Fix #1880
2017-02-22 17:51:23 +01:00
Julien Duponchelle
005dde6c2b Fix some import errors 2017-02-22 17:23:58 +01:00
Julien Duponchelle
260f9b352e Remove placeholder string from appliance wizard 2017-02-22 11:02:25 +01:00
Julien Duponchelle
852b0bc498 Avoiding calling multiple time /computes at the same time. And reduce timeout
Fix #1848
2017-02-22 10:29:41 +01:00
Julien Duponchelle
3a503a5fc0 Support for appliance v4 2017-02-22 09:04:22 +01:00
Jeremy Grossmann
88b408695a Merge pull request #1875 from GNS3/hdpi_enable
Disable HDPI by default on Linux and allow to configure it
2017-02-20 20:39:19 -08:00
grossmj
776b45363b Some tweaks for enabling/disabling HDPI mode. 2017-02-21 12:33:09 +08:00
Julien Duponchelle
adb270b64c Do not display error at first step of the setup wizard
Fix #1827
2017-02-20 20:04:43 +01:00
Julien Duponchelle
5329b8fd72 Disable HDPI by default on Linux and allow to configure it
Fix #1870
2017-02-20 19:21:02 +01:00
Julien Duponchelle
d6379e4bb9 Fix an issue when you edit a VPCS node from the node view
Fix https://github.com/GNS3/gns3-gui/issues/1874
2017-02-20 18:09:48 +01:00
Julien Duponchelle
6ca18d5b29 Catch a race condition in managing error static assets download
Fix #1872
2017-02-20 15:11:44 +01:00
Julien Duponchelle
50c008ddec Handle error if you try to import an appliance without having the images
Fix #1871
2017-02-20 12:29:37 +01:00
Julien Duponchelle
4f56f100fa Improve crash proof code of the progress dialog
Fix #1873
2017-02-20 12:16:32 +01:00
Jeremy Grossmann
a81d1443f9 Merge pull request #1835 from GNS3/base_config_server_side
Manage base configuration on server
2017-02-19 22:59:27 -08:00
Jeremy Grossmann
e69089f4cf Merge pull request #1865 from GNS3/status_bar_error
Display a count of errors at the bottom of the screen
2017-02-18 05:53:27 -08:00
Julien Duponchelle
0c052542b3 Display a count of errors at the bottom of the screen
You can test it by typing in the console:
log error test
log warning test

Click on the count hide / show the console and reset the counters.

Also now status bar is a dedicated class we can easyly extend it.

Ref #1864
2017-02-17 16:24:58 +01:00
Julien Duponchelle
00e402f28c Merge pull request #1814 from GNS3/show_error
Display an overlay popup with log messages
2017-02-17 11:20:37 +01:00
Julien Duponchelle
0742b282a3 Change some log level to avoid notifications noises 2017-02-17 11:09:18 +01:00
Jeremy Grossmann
2b588aa0bf Merge pull request #1820 from GNS3/line
Allow drawing lines
2017-02-17 02:08:36 -08:00
Julien Duponchelle
92fb8418ab Add a checkbox to display or not notification in app 2017-02-17 11:08:31 +01:00
Julien Duponchelle
9c7dbc864e Display an overlay popup with log messages
Ref #1334
2017-02-17 11:08:31 +01:00
Julien Duponchelle
25aebaa46c Better support for Vertical Line 2017-02-17 11:01:57 +01:00
Jeremy Grossmann
0e30b3cf5f Merge pull request #1842 from GNS3/qemu_more_adapters
Allow up to 275 adapters for qemu
2017-02-17 01:41:24 -08:00
Julien Duponchelle
755667c4d5 Spawn line at correct position 2017-02-17 10:37:27 +01:00
grossmj
16dbdf70d9 Add line icons 2017-02-17 17:17:05 +08:00
Jeremy Grossmann
806c7479ee Merge pull request #1831 from GNS3/scale_percent
Display zoom percentage when changing scale.
2017-02-17 00:25:04 -08:00
Jeremy Grossmann
cc8b84725a Update graphics_view.py 2017-02-17 16:24:46 +08:00
Julien Duponchelle
e01701614e Remember last appliance filter 2017-02-16 17:21:42 +01:00
Julien Duponchelle
efaffac801 Merge branch '2.0' into 2.1 2017-02-16 16:28:21 +01:00
Julien Duponchelle
0c16a5b0d1 2.0.0dev9 2017-02-16 11:27:49 +01:00
Julien Duponchelle
8f33ad3c70 2.0.0b4 2017-02-16 11:26:32 +01:00
Julien Duponchelle
7dca1b404c Fix a rare crash 2017-02-15 19:28:38 +01:00
Julien Duponchelle
99ff98ff47 Merge pull request #1858 from GNS3/pyup-update-pyqt5-5.7.1-to-5.8
Update pyqt5 to 5.8
2017-02-15 18:55:09 +01:00
pyup-bot
083d6e1298 Update pyqt5 from 5.7.1 to 5.8 2017-02-15 18:44:11 +01:00
Julien Duponchelle
71716c451e Drop from console view the show command not supported by 2.0
Fix #1855
2017-02-15 18:15:09 +01:00
Julien Duponchelle
3c4a244b75 Try to avoid segfault in some PyQT version
Fix #1856
2017-02-15 16:19:13 +01:00
Julien Duponchelle
85892a3bd6 Display git commit version in version number 2017-02-15 12:52:17 +01:00
Julien Duponchelle
1d3d721cf3 Support for strike and underline
Fix #1851
2017-02-14 17:45:48 +01:00
Julien Duponchelle
37a72af75f Do not use native font selector on mac it could crash 2017-02-14 17:01:21 +01:00
Julien Duponchelle
c93713b9e7 Use a dedicated QNetwork manager for notification
I hope this will solve issue for some users where the connection
return random error when they change the project.

Ref #1848
2017-02-14 15:15:29 +01:00
Julien Duponchelle
77b3118cbc Try to workaround unknow error on some user computers
Ref #1848
2017-02-14 12:27:34 +01:00
Julien Duponchelle
bc0cbfd040 Fix a display error in console error message 2017-02-14 11:37:20 +01:00
Julien Duponchelle
0cfc66b4d4 Use signal for writting on console to avoid some potential segfault 2017-02-14 11:23:41 +01:00
Julien Duponchelle
1b9b1cbe3c Fix tests about HTTP errors 2017-02-14 10:19:34 +01:00
Julien Duponchelle
407187c826 Fix a rare warning
Fix https://github.com/GNS3/gns3-server/issues/901
2017-02-14 09:53:12 +01:00
Julien Duponchelle
a6eb1e65ac Add more debug when we have an http error
Ref #1848
2017-02-13 19:15:19 +01:00
Julien Duponchelle
efbb19a862 Disable timeout on project open
Ref #1848
2017-02-13 17:39:13 +01:00
Julien Duponchelle
2a94816b58 Support for gvncviewer
Fix #1845
2017-02-13 15:26:12 +01:00
Julien Duponchelle
aab307a519 Fix a rare crash in the file editor dialog
Fix #1849
2017-02-13 15:22:03 +01:00
Julien Duponchelle
1279e16484 Fix a race condition when we display the error
Ref #1848
2017-02-13 13:08:38 +01:00
Julien Duponchelle
c2e20f9bd6 Fix an issue with invalid hostname detected as an IPV6 2017-02-10 18:13:48 +01:00
Julien Duponchelle
c58366e9cb When an appliance template is added we hide it 2017-02-10 15:55:48 +01:00
Julien Duponchelle
068ebcdea0 "/appliances" => "/appliances/templates" 2017-02-10 15:55:47 +01:00
Julien Duponchelle
51f2b4bfa8 Display the appliances in the application
Ref #1045
2017-02-10 15:55:47 +01:00
Julien Duponchelle
168e4ab86e Merge branch '2.0' into 2.1 2017-02-10 15:55:17 +01:00
Julien Duponchelle
4acdaf6b5a When you update a a node from the node view send settings to controller 2017-02-10 15:51:54 +01:00
Julien Duponchelle
25313cbcde Fix error when permission on the loaded image is broken
Fix #1843
2017-02-08 11:19:41 +01:00
Julien Duponchelle
7ae18ff82a Allow up to 275 adapters for qemu
See https://github.com/GNS3/gns3-server/pull/895 for server part
2017-02-07 17:37:10 +01:00
Julien Duponchelle
c694173f9d Merge branch '2.0' into 2.1 2017-02-07 17:36:45 +01:00
Julien Duponchelle
0de0eb12eb Fix tests 2017-02-07 17:36:21 +01:00
Julien Duponchelle
b58b92c9f0 Merge branch '2.0' into 2.1 2017-02-07 15:03:44 +01:00
Julien Duponchelle
7d0fe52600 Fix crash with invalid image file in appliance wizard
Fix #1837
2017-02-06 17:27:30 +01:00
Julien Duponchelle
ba1d3b2423 Fix error when loading an handmade appliance file
Fix #1839
2017-02-06 17:10:30 +01:00
Julien Duponchelle
cae6afe85d Fix no error if your VNC client is not configured
Fix #1838
2017-02-06 16:59:06 +01:00
Julien Duponchelle
5865ac267b Avoid high cpu usage when connection is lost
Fix #1840
2017-02-06 11:27:36 +01:00
Julien Duponchelle
162993839c Support {name} in cloud template
Fix #1833
2017-02-03 15:15:47 +01:00
Julien Duponchelle
4359b490cc Fix text of the export dialog
Fix #1834
2017-02-03 14:47:07 +01:00
Julien Duponchelle
e4a8e67229 Fix error message when a project is already open
Fix #1832
2017-02-03 14:45:44 +01:00
Julien Duponchelle
3ddb2e70d4 Manage base configuration on server
Fix #786
2017-02-03 13:18:04 +01:00
Julien Duponchelle
05966a9119 Display zoom percentage when changing scale.
It's like other messages display during 2 seconds.

Fix #1263
2017-02-01 14:51:58 +01:00
Julien Duponchelle
8ea24e9920 Remove unused variables 2017-02-01 14:32:05 +01:00
Julien Duponchelle
6605270e64 Fix missing info in tooltip of ethernet switch
Fix  https://github.com/GNS3/gns3-gui/issues/1828
2017-01-31 19:28:03 +01:00
Julien Duponchelle
09e2bfeed0 The server manage the vmname when we update the linked virtual box VM
Ref https://github.com/GNS3/gns3-gui/issues/1821
2017-01-31 18:50:52 +01:00
Julien Duponchelle
47f34fd5af Merge branch '2.0' into 2.1 2017-01-31 17:00:40 +01:00
Julien Duponchelle
b24733466d Fix z value for text
Fix #1822
2017-01-30 16:00:43 +01:00
Julien Duponchelle
c31be48f20 Avoid a segfault when display an error 2017-01-30 10:51:31 +01:00
Julien Duponchelle
a9ed27f42c Add sata options in the appliance schema
Fix #1817
2017-01-27 11:01:11 +01:00
Julien Duponchelle
89321a6cad Allow drawing lines
Ref #997
2017-01-27 10:15:05 +01:00
Julien Duponchelle
1440caa532 Fix a rare crash when exporting IOU configurations
Fix #1800
2017-01-25 13:55:19 +01:00
Julien Duponchelle
513eb21940 Allow additionnal properties in registry files 2017-01-25 12:14:36 +01:00
Julien Duponchelle
de348d39da Fix a potential crash when a symbol is not found 2017-01-25 12:04:40 +01:00
Julien Duponchelle
0a3697962b Strip unused code for OVA support in the registry 2017-01-24 12:14:25 +01:00
Julien Duponchelle
e0edcf3d23 Increase the timeout for killing local server
Fix #1813
2017-01-24 11:20:50 +01:00
Julien Duponchelle
6690ba7108 2.1.0dev1 2017-01-24 10:38:13 +01:00
Julien Duponchelle
57dbff6a8e Merge pull request #1804 from GNS3/pyup-update-pytest-3.0.5-to-3.0.6
Update pytest to 3.0.6
2017-01-24 09:57:13 +01:00
Julien Duponchelle
0149bc90f2 Fix error when changing the layer of a drawing item
Fix #1810
2017-01-23 17:30:55 +01:00
Julien Duponchelle
f7292deb0f Fix double click for open file on OSX
Fix #1808
2017-01-23 17:22:17 +01:00
Julien Duponchelle
be01448c36 Add debug to see the arguments use to start the application
Ref #1808
2017-01-23 13:58:19 +01:00
Julien Duponchelle
484617ce25 Put the selected engine in the first position of the listbox
This avoid trigerring unexpected signals

Fix #1803
2017-01-23 11:31:55 +01:00
Julien Duponchelle
8ec53a6004 Fix rare crash with dynamips
Fix #1806
2017-01-23 10:15:29 +01:00
Julien Duponchelle
cfd1bbd9d1 Fix rare crash in the progress dialog
Fix #1802
2017-01-23 10:13:43 +01:00
Julien Duponchelle
25ae214b6b Fix a rare crash in console view
Fix #1807
2017-01-23 10:11:36 +01:00
Julien Duponchelle
456160beb1 Fix rare crash
Fix #1805
2017-01-23 10:09:49 +01:00
Julien Duponchelle
9affe2d9f4 Fix crash when you drag a file inside GNS3
Fix #1798
2017-01-23 10:08:03 +01:00
pyup-bot
3ed2f89b3b Update pytest from 3.0.5 to 3.0.6 2017-01-22 23:58:47 +01:00
Julien Duponchelle
9bb353fdbd 2.0.0dev8 2017-01-19 11:23:19 +01:00
Julien Duponchelle
c414ea28e4 2.0.0b3 2017-01-19 11:20:31 +01:00
Julien Duponchelle
cb0253f7cb Fix error if you already have an image with a different name on remote server
Fix #1794
2017-01-18 17:13:00 +01:00
Julien Duponchelle
f28663c626 Ask pyup to not monitor pywin32 2017-01-18 09:32:39 +01:00
Julien Duponchelle
3ef018f90e Allow any pywin32 version 2017-01-17 10:59:25 +01:00
Julien Duponchelle
e5ae7f77fa Drop gns3 converter from requirements 2017-01-17 10:58:36 +01:00
Julien Duponchelle
b6bac0cd3b Show correct server name in tooltip
Fix #1783
2017-01-16 20:46:49 +01:00
Julien Duponchelle
6a8e435210 Menu item to open controller webpage
Fix #1784
2017-01-16 17:43:06 +01:00
grossmj
442318af49 Fixes potential exception when adding network module to an IOS router. Fixes #1774. 2017-01-16 13:53:25 +08:00
Julien Duponchelle
ad93b46c94 Merge pull request #1776 from GNS3/pyup-update-pypiwin32-219-to-220
Update pypiwin32 to 220
2017-01-13 09:13:40 +01:00
pyup-bot
f7a9cc09ea Update pypiwin32 from 219 to 220 2017-01-12 18:47:41 +01:00
Julien Duponchelle
0d5507cf3d Merge branch '2.0' of github.com:GNS3/gns3-gui into 2.0 2017-01-12 08:55:17 +01:00
Julien Duponchelle
f885e33cbd Merge branch 'master' into 2.0 2017-01-12 08:53:57 +01:00
Julien Duponchelle
4813a8681f 1.5.4dev1 2017-01-12 08:51:46 +01:00
Julien Duponchelle
829f750c76 1.5.3 2017-01-12 08:14:42 +01:00
Julien Duponchelle
08b9f4a6d2 Merge pull request #1772 from GNS3/sata-qemu
Sata disk interface support for Qemu VMs.
2017-01-11 16:53:58 +01:00
Julien Duponchelle
7fdf022b36 Do not export a file config file if empty 2017-01-10 15:56:17 +01:00
Julien Duponchelle
f12935076e Allow to set console type in qemu wizard
/bin/bash: q: command not found
2017-01-09 13:02:12 +01:00
Julien Duponchelle
7a472d1574 Fix overwrite of projects
Fix #1743
2017-01-09 12:35:36 +01:00
Julien Duponchelle
4a82dc8705 Fix creation of new appliance version when filename is different
Fix #1755
2017-01-09 12:08:09 +01:00
Julien Duponchelle
52acaadfce Fix you can't configure port 0 on ethernet switch
Fix #1765
2017-01-09 10:23:06 +01:00
Julien Duponchelle
ef1967ff00 Fix a race condition when saving as a project and closing it
Fix #1770
2017-01-09 10:17:03 +01:00
Julien Duponchelle
6584f3b2d4 Reorder multi link when you delete one
Fix #1750
2017-01-06 11:42:26 +01:00
Julien Duponchelle
8ad55290b1 Ensure we can't connect to occupy port
Fix https://github.com/GNS3/gns3-gui/issues/1759
2017-01-06 10:30:24 +01:00
Julien Duponchelle
8ff34d63c0 Fix AttributeError: 'QImageSvgRenderer' object has no attribute '_svg'
Fix #1760
2017-01-06 09:12:13 +01:00
Julien Duponchelle
da88947028 Fix Unsaved preferences in GNS3 VM warning 2017-01-05 17:40:05 +01:00
Julien Duponchelle
854dc5db71 Fix Unsaved preferences in GNS3 VM warning
Fix #1740
2017-01-05 15:50:41 +01:00
Julien Duponchelle
e8ac144011 Merge pull request #1753 from GNS3/pyup-update-pyqt5-5.7-to-5.7.1
Update pyqt5 to 5.7.1
2017-01-05 08:22:10 +01:00
grossmj
8b20f4d568 Force margins in configuration tabs. 2017-01-05 14:52:39 +08:00
grossmj
cb88a4f6d9 Sata disk interface support for Qemu VMs. 2017-01-05 11:24:49 +08:00
grossmj
270f12dc1e Remove "sata" disk interface. Does not exist in Qemu. Ref #1749 2017-01-02 15:02:19 +08:00
grossmj
46ff586055 Add SATA and none disk interfaces on Qemu VM configuration page. Fixes #1749. 2017-01-01 23:25:31 +08:00
pyup-bot
78b999be57 Update pyqt5 from 5.7 to 5.7.1 2016-12-29 12:06:02 +01:00
Julien Duponchelle
4f702d9339 Fix TypeError: argument of type 'NoneType' is not iterable
Fix #1733
2016-12-21 14:34:58 +01:00
Julien Duponchelle
6f210c0e91 2.0.0 dev7 2016-12-21 09:38:50 +01:00
Julien Duponchelle
a677cff0a2 Fix an error when you edit readme and no projet is opened
Fix #1732
2016-12-21 09:37:23 +01:00
Julien Duponchelle
5929e3b56d 2.0.0 beta 2 2016-12-20 12:01:10 +01:00
Julien Duponchelle
5b1050e427 1.5.3 dev2 2016-12-20 11:48:07 +01:00
Julien Duponchelle
271e987972 Upgrade Qt 5.7 2016-12-20 11:40:32 +01:00
grossmj
80402185a5 AUX console button text change in MainWindow. 2016-12-20 18:31:46 +08:00
Julien Duponchelle
1df34148b2 1.5.3 rc1 2016-12-20 09:32:38 +01:00
Julien Duponchelle
dc2070b24e Remove debug 2016-12-20 08:56:08 +01:00
grossmj
7dcbb14b75 Remove forgotten code comments. Ref #1713. 2016-12-20 12:27:41 +11:00
Julien Duponchelle
36c90e0d96 Fix GNS3 Client not connecting to remote controller
Fix #1726
2016-12-19 18:58:05 +01:00
Julien Duponchelle
53b0bef527 Delete from project list deleted projects
Fix #1724
2016-12-19 18:52:31 +01:00
Julien Duponchelle
8227cf1aba Keep a shared list of projects internally
Ref #1724
2016-12-19 18:29:48 +01:00
Julien Duponchelle
7e09d9042b Fix recent files in new project dialog 2016-12-19 17:45:16 +01:00
Julien Duponchelle
49688d6c0e Move recent projects to the file menu
Fix #1713
2016-12-19 17:40:20 +01:00
Julien Duponchelle
962ce3e3d8 Fix Tail process for wireshark trace not killed when we change project
Fix #1725
2016-12-19 14:57:55 +01:00
grossmj
8cbae911e9 Move project menu items. Ref #1713. 2016-12-19 23:23:26 +11:00
Julien Duponchelle
10c94baab7 Fix AttributeError: 'NoneType' object has no attribute 'project_updated_signal'
Fix #1728
2016-12-19 09:11:39 +01:00
Julien Duponchelle
2f2c0ba3ba Display recent files for local controller, recent project for remote controller
Ref #1713
2016-12-16 11:43:01 +01:00
Julien Duponchelle
879647de5e Do not display the remote server if the server is use as a GNS3 VM
Fix #1718
2016-12-15 18:07:00 +01:00
Julien Duponchelle
cd2c9d6b0c If the notification stream is stopped by something we auto reconnect 2016-12-14 19:58:09 +01:00
Julien Duponchelle
95c443e127 Ignore system proxy to avoid trouble with "Security Suites"
Fix #1721
2016-12-13 18:04:19 +01:00
Julien Duponchelle
d403b26b44 Avoid close and delete a project at the same time
Ref #1714
2016-12-12 22:08:49 +01:00
Julien Duponchelle
0f4d4e2071 Alpha sort of servers summaries 2016-12-12 21:29:16 +01:00
Julien Duponchelle
b51e772664 Fix new remote server doesn't show up in compute summary
Fix #1703
2016-12-12 21:25:33 +01:00
Julien Duponchelle
83c7be0f60 Fix interface number for Switch & Hub templates
Fix #1711, #1712
2016-12-12 16:30:33 +01:00
Julien Duponchelle
0063f7d97f Fix sync of node alignements with the server
Fix #1710
2016-12-12 12:50:02 +01:00
Julien Duponchelle
0a65eeeee2 Fix rare condition when you close a project and add a node
Fix #1716
2016-12-12 09:57:49 +01:00
Julien Duponchelle
a7e69e7260 Fix 'LocalServer' object has no attribute '_server_started_by_me'
Fix #1715
2016-12-12 09:13:05 +01:00
Julien Duponchelle
cea15dab4c Options -q for quiet startup
Fix #1708
2016-12-12 09:11:13 +01:00
Julien Duponchelle
7646b59078 Fix an error when apply permission on OSX 2016-12-08 18:52:48 +01:00
Julien Duponchelle
a3c996a3d8 Fix test suites 2016-12-08 17:49:06 +01:00
Julien Duponchelle
e6017ea102 Support Qemu cpus in GNS3A
Fix https://github.com/GNS3/gns3-server/issues/811
2016-12-08 17:34:48 +01:00
Julien Duponchelle
e7db81c277 Support for BIOS images
Fix https://github.com/GNS3/gns3-gui/issues/1700
2016-12-08 16:21:30 +01:00
Julien Duponchelle
a182f5e4b6 Fix IdlePC can't be found during setup wizard
Fix #1693
2016-12-08 12:41:16 +01:00
Julien Duponchelle
da73357763 2.0.0 dev 6 2016-12-08 10:31:34 +01:00
Julien Duponchelle
09e37725f7 2.0.0b1 2016-12-07 19:46:33 +01:00
Julien Duponchelle
5ab9f95379 Use osascript on OSX for asking admin permission
Fix #1699
2016-12-07 16:45:01 +01:00
Julien Duponchelle
6731909971 Change the method for creating the tmpdir for symbols cache
Fix #1701
2016-12-07 16:09:05 +01:00
Julien Duponchelle
284948e377 Fix a connection error at the end of the setup wizard
Fix #1698
2016-12-07 15:59:54 +01:00
Julien Duponchelle
1e55c974eb Merge pull request #1702 from GNS3/CapnCheapo-remove_use_local
Remove use local
2016-12-07 15:33:03 +01:00
grossmj
b186dee326 Change some more preferences tab names. 2016-12-07 22:04:28 +11:00
grossmj
3ae0abc19e Change how some tabs are organized or named. 2016-12-07 21:42:09 +11:00
Julien Duponchelle
dde660ae15 General settings => local settings 2016-12-06 19:40:33 +01:00
Julien Duponchelle
d9fbd04552 Drop more reference to use local server 2016-12-06 19:36:24 +01:00
pyup.io bot
a20c15cbac Update pytest from 3.0.4 to 3.0.5 (#1697) 2016-12-05 17:29:42 +01:00
Stephen Moore
5a54b9f5ca Remove local server checkbox from preferences 2016-12-04 22:14:19 -06:00
Julien Duponchelle
3528d85501 Make sure to not start local server during setup wizard remote server
Fix #1674
2016-12-01 18:18:59 +01:00
Julien Duponchelle
b773599c56 Merge branch 'master' into 2.0 2016-12-01 13:43:22 +01:00
Julien Duponchelle
73346c8de7 Fix Error when editing IOS image created using .gns3a file
Fix #1684
2016-12-01 13:42:42 +01:00
Julien Duponchelle
d33b21fdc1 Fix Error when editing IOS image created using .gns3a file
Fix #1684
2016-12-01 13:41:33 +01:00
Julien Duponchelle
8139010796 Fix test suites around sip deleted 2016-12-01 13:30:00 +01:00
Julien Duponchelle
f0bc1a4abb Do not auto start the local server in setup wizard
Until you quit setup wizard or choose local server the server
don't start.

Fix #1687
2016-12-01 12:33:00 +01:00
Julien Duponchelle
9d0d5da3fc On OSX execute all sudo in a single operation
Fix #1687
2016-12-01 12:10:46 +01:00
Julien Duponchelle
26d188f228 Catch key Compute is missing during conversion error
Fix #1690
2016-12-01 11:12:21 +01:00
Julien Duponchelle
c7af6c2ae2 Fix rare crash in gns3.dialogs.appliance_wizard in validateCurrentPage
Fix #1691
2016-12-01 10:52:28 +01:00
Julien Duponchelle
8707113db8 Fix AttributeError: 'Nat' object has no attribute 'configPage'
Fix #1685
2016-12-01 10:10:19 +01:00
Julien Duponchelle
e88b4814e7 Catch one more RuntimeError: wrapped C/C++
Fix #1692
2016-12-01 09:56:19 +01:00
Julien Duponchelle
97926fe6d5 Fix a rare crash in port
Fix #1688
2016-12-01 09:46:14 +01:00
Julien Duponchelle
4fb9d46953 Fix a rare crash when set symbol
Fix #1689
2016-12-01 09:44:57 +01:00
Julien Duponchelle
c066f7f3df Fix a potential crash 2016-11-29 08:51:33 +01:00
Julien Duponchelle
5117ef8a58 Fix a potential crash at exit 2016-11-28 20:00:03 +01:00
Julien Duponchelle
35ebb39e22 Fix crashes 2016-11-28 14:41:54 +01:00
Julien Duponchelle
66f8c19478 Remove unused settings from general preferences
Fix #1681
2016-11-28 14:17:01 +01:00
Julien Duponchelle
e07ea40b24 Catch error when you try to import a IOU bin as a licence
Fix #1679
2016-11-28 11:08:34 +01:00
Julien Duponchelle
149bc38b2b Fix rare crash when exiting
Fix #1676
2016-11-28 11:06:45 +01:00
Julien Duponchelle
23ca81ccc4 Fix crash when freeing some ressources
Fix #1678, #1677
2016-11-28 11:05:01 +01:00
Julien Duponchelle
b4ab559b00 Fix timeout when exporting large project
Fix https://github.com/GNS3/gns3-server/issues/797
2016-11-25 17:32:09 +01:00
Julien Duponchelle
ad88735e63 Avoid a rare crash when we free a port
Fix #1672
2016-11-25 17:20:16 +01:00
Julien Duponchelle
66ec4f9de5 Fix you can't download symbols after you got an error
Fix #1673
2016-11-25 17:15:41 +01:00
Julien Duponchelle
35d6b424e6 2.0.0dev5 2016-11-24 12:52:54 +01:00
Julien Duponchelle
eb6b099fa1 2.0.0a4 2016-11-24 12:09:33 +01:00
grossmj
b8c1a7a4c9 Some cosmetic for the setup wizard. 2016-11-23 23:06:36 +11:00
Julien Duponchelle
bc07bdaf74 Fix project open (merge error) 2016-11-22 18:41:20 +01:00
Jeremy Grossmann
3109befe73 Merge pull request #1491 from GNS3/dissallow_unknow
Dissallow unknown extensions
2016-11-22 19:02:27 +10:30
Julien Duponchelle
044683de21 Mark preferences changes when you change a QPlainTextEdit 2016-11-21 18:16:02 +01:00
Julien Duponchelle
e607663575 Force the VPCS config initial file
Ref #1655
2016-11-21 17:11:22 +01:00
Julien Duponchelle
abcff7192b Replace the IOU licence path by an input text
Ref #1662
2016-11-21 15:29:53 +01:00
Julien Duponchelle
bc43c43c53 Fix 403 when loading a remote project
Fix #782
2016-11-18 17:59:30 +01:00
Julien Duponchelle
dbc7c4675f Fix some possible PID issues
Fix #1658
2016-11-18 16:45:55 +01:00
Julien Duponchelle
3f0e23f34d Hide the connection refused dialog when we success to reconnect
Fix #1665
2016-11-18 12:36:59 +01:00
Julien Duponchelle
ef7bd7c77c Avoid a rare crash when changing topology 2016-11-18 09:43:43 +01:00
Julien Duponchelle
77950c8a2c When loading another project disconnect from current project
Ref #1646
2016-11-17 12:09:21 +01:00
Julien Duponchelle
a801b5b21f Do not crash if we can't list remote list of GNS3 VM engines 2016-11-16 12:02:18 +01:00
Julien Duponchelle
d637a6dcac Init the VPCS base config
Fix #1655
2016-11-16 10:33:36 +01:00
Julien Duponchelle
8370a22966 Fix invalid ressource path on OSX 2016-11-15 11:41:06 +01:00
Julien Duponchelle
7ea8c8b8f1 Disable the usage of the wheel for Qt 5.7 2016-11-15 11:37:57 +01:00
Julien Duponchelle
11ab87245b Crash fix 2016-11-15 11:33:06 +01:00
Julien Duponchelle
cf63b49b82 Fix segfault when deleting a node
Ref #1654
2016-11-14 19:05:01 +01:00
Julien Duponchelle
030384c990 Do not download multiple time the same symbol
Fix #1661
2016-11-14 16:04:19 +01:00
Julien Duponchelle
49c734b52c Kill tail process when capture stop
Fix #772
2016-11-14 10:41:09 +01:00
pyup.io bot
2a7b6144d6 Update pytest from 3.0.3 to 3.0.4 (#1657) 2016-11-14 09:45:47 +01:00
Julien Duponchelle
f1ecc0cc15 Fix Topology summary contain non existing links
Fix #1640
2016-11-11 11:18:29 +01:00
Julien Duponchelle
adb7663d03 Fix a rare crash when deleting a link
Fix #1653
2016-11-11 09:59:54 +01:00
pyup.io bot
118b0a85d2 Update pytest-timeout from 1.0.0 to 1.2.0 (#1652) 2016-11-10 22:54:29 +01:00
Julien Duponchelle
5fcf1e156d Fix export of debug informations when not connected to the controller
Fix #1650
2016-11-10 13:29:30 +01:00
Julien Duponchelle
5272befb60 Fix AttributeError: 'DockerVM' object has no attribute 'server'
Fix #1647
2016-11-06 21:49:17 +01:00
Julien Duponchelle
b10a524496 Fix error message if you double click on builtin switch
Fix #1642
2016-11-04 13:34:43 +01:00
Julien Duponchelle
de7417787b Fix a rare crash in packet capture
Fix #1643
2016-11-04 13:28:16 +01:00
Julien Duponchelle
a00b80529b Restrict ubridge to admin users on OSX 2016-11-04 09:50:14 +01:00
Julien Duponchelle
b1fa44d176 Natural sort of Nodes in topology summary
Fix #1634
2016-11-03 19:53:36 +01:00
Julien Duponchelle
8251b460ad Drop serial console type
Fix https://github.com/GNS3/gns3-server/issues/748
2016-11-03 18:56:39 +01:00
Julien Duponchelle
4403044584 Fix syntax error 2016-11-03 18:45:42 +01:00
Julien Duponchelle
39c7a56041 Display an error if you try to open a 0.8.x file
Fix #1639
2016-11-03 15:15:03 +01:00
Julien Duponchelle
383dbb5fca Fix tab order when editing a compute 2016-11-02 13:35:04 +01:00
Julien Duponchelle
fc94e784cc Fix a crash in ethernet switch settings
Fix #1635
2016-11-02 11:58:24 +01:00
Julien Duponchelle
37937b0096 2.0.0dev4 2016-10-28 19:38:32 +02:00
Julien Duponchelle
3e9d303ec4 Update changelog 2016-10-28 19:25:26 +02:00
Julien Duponchelle
68908e17d3 2.0.0 alpha 3 2016-10-28 19:23:51 +02:00
Julien Duponchelle
026f482b1b Merge branch 'master' into 2.0 2016-10-28 10:29:28 +02:00
Julien Duponchelle
879784cd67 Fix error when opening a project from the cli with a gns3 installed via setup.py
Fix #1581
2016-10-28 10:27:07 +02:00
Julien Duponchelle
8b8cbb4d74 Fix a rare crash in snapshot dialog
Fix #1627
2016-10-28 09:54:20 +02:00
Julien Duponchelle
40783eba15 Fix crash when importing project on a remote server
Fix #1628
2016-10-28 09:52:52 +02:00
Julien Duponchelle
e63d20ce48 Fix crash in appliance wizard
Fix #1624
2016-10-27 21:01:11 +02:00
Julien Duponchelle
f6ecc4d0bb Fix crash when local server is not available 2016-10-27 20:14:36 +02:00
Julien Duponchelle
64339e6846 Disallow to overwrite a running project
Fix https://github.com/GNS3/gns3-server/issues/745
2016-10-27 16:02:08 +02:00
Julien Duponchelle
2fe73056f0 Fix a rare crash when deleting a link
Fix #1623
2016-10-27 15:29:03 +02:00
Julien Duponchelle
95051035a9 Merge branch 'master' into 2.0 2016-10-27 12:30:27 +02:00
Julien Duponchelle
af6294fe7e Fix appliance with wrong file name after import 2016-10-27 12:29:32 +02:00
Julien Duponchelle
2fd53be083 Fix a crash at startup on Mac when coming from old GNS3 version
Fix #1622
2016-10-26 17:51:07 +02:00
Julien Duponchelle
93199e3695 Fix a crash 2016-10-26 17:04:54 +02:00
Julien Duponchelle
d0a3051656 Fix key error in settings if a compute no longer exists
Fix #1612
2016-10-26 16:16:55 +02:00
Julien Duponchelle
516e84d328 All check for vmware linked base are already made server side
Fix #1609
2016-10-26 15:50:13 +02:00
Julien Duponchelle
a06e4cb7ba Fix Save as is not switching to the saved project
Fix #1620
2016-10-26 15:37:13 +02:00
Julien Duponchelle
a1dd5fee9f Auto reopen a project if connection is lost
Fix #1619
2016-10-26 15:28:25 +02:00
Julien Duponchelle
7e00ac4e50 Empty the list of computes nodes when connection is lost
Ref #1619
2016-10-26 15:01:17 +02:00
Julien Duponchelle
59201e8af6 Try to fix duplicate nodes after snapshot restore on some user computer
Fix #1571
2016-10-26 11:28:35 +02:00
Julien Duponchelle
fbde9e0746 Allow only IPV4 in setup wizard
Fix #1608
2016-10-26 10:55:51 +02:00
Julien Duponchelle
f714add057 Catch error if user tmp directory is read only
Fix #1614
2016-10-26 10:25:59 +02:00
Julien Duponchelle
ce2724a892 Raise a proper error if packet capture program is invalid
Fix #1597
2016-10-26 10:23:20 +02:00
Julien Duponchelle
aff475cd5b Fix AttributeError: 'NoneType' object has no attribute 'upper'
Fix #1615
2016-10-26 10:20:55 +02:00
Julien Duponchelle
b18d7c7cc5 Fix rare crash when killing wireshark
Fix #1616
2016-10-26 10:19:00 +02:00
Julien Duponchelle
687088cbd7 Export debug informations also from the controller
Ref #1562, https://github.com/GNS3/gns3-server/issues/740
2016-10-25 11:41:49 +02:00
Julien Duponchelle
31fc18b150 Fix a crash in vm wizard
Fix #1610
2016-10-25 10:41:09 +02:00
Julien Duponchelle
dd960d5556 Fix an invalid test 2016-10-25 10:39:25 +02:00
Julien Duponchelle
004d9f90e3 Fix error when uploading an images from preferences
Fix #1594
2016-10-25 10:27:56 +02:00
Julien Duponchelle
f8f7ee686e Fix snap to grid when initialy drop a node in the topology 2016-10-24 21:58:47 +02:00
Bernhard Ehlers
c695e565ea Optimize snap-to-grid code
Signed-off-by: Julien Duponchelle <julien@gns3.net>

Fix #1599
2016-10-24 21:45:01 +02:00
Julien Duponchelle
d32c3ebebe Fix a crash with linked clone 2016-10-24 19:20:41 +02:00
Julien Duponchelle
b863bae4e7 Move prevent using twice the same VM when linked clone is not enable
Ref #1593
2016-10-24 18:14:01 +02:00
Julien Duponchelle
8f033e8bd3 Fix If you show interface label and delete the link ghost interface label will appear
Fix #1607
2016-10-24 17:40:51 +02:00
Julien Duponchelle
c8776486c5 Display short interface label instead of long version
Fix #1606
2016-10-24 17:30:34 +02:00
Julien Duponchelle
679e9ad4bf Fix error AttributeError: 'NoneType' object has no attribute 'capabilities'
Fix #1595
2016-10-24 17:15:17 +02:00
Julien Duponchelle
877b255f23 Fix PermissionError when killing local server
Fix #1601
2016-10-24 17:03:18 +02:00
Julien Duponchelle
e404716f88 Handle empty color
Fix #1602
2016-10-24 17:01:35 +02:00
Julien Duponchelle
4e58df60ea Fix rare crash in save as
Fix #1592
2016-10-24 16:58:56 +02:00
Julien Duponchelle
e7f761c8d6 Fix crash in restore default server settings
Fix #1603
2016-10-24 16:51:52 +02:00
Julien Duponchelle
50ca85b7ce Fix an error during import of some 0.8x projects
Fix #1578
2016-10-21 10:55:26 +02:00
Julien Duponchelle
9659c29dd0 2.0.0dev3 2016-10-20 22:12:39 +02:00
Julien Duponchelle
535f3193db 2.0.0a2 2016-10-20 21:33:01 +02:00
Julien Duponchelle
7fae1eac48 Support pure remote server for importing appliance
Fix #1590
2016-10-20 21:24:38 +02:00
Julien Duponchelle
4cc2975e97 Dissallow bindingi GNS3 server to an IPV6 (not supported by some emulators)
Ref https://github.com/GNS3/gns3-server/issues/725
2016-10-20 09:51:17 +02:00
Julien Duponchelle
149d1ad590 Drop vmware host type choice in client
Fix https://github.com/GNS3/gns3-gui/issues/1579
2016-10-19 12:05:21 +02:00
Julien Duponchelle
abc900a764 Merge branch 'master' into 2.0 2016-10-19 10:51:12 +02:00
Julien Duponchelle
14084192da Ask for restart after installing vmrun
Fix https://github.com/GNS3/gns3-server/issues/724
2016-10-19 10:50:07 +02:00
Julien Duponchelle
2f6603070b Ask user to restart GNS3 after VMware installation
Ref https://github.com/GNS3/gns3-server/issues/724
2016-10-19 10:29:11 +02:00
Julien Duponchelle
c3aac9f0a6 Improve duplicate prevention in topology summary
Fix #1571
2016-10-19 09:01:23 +02:00
Julien Duponchelle
afde80dab5 Add a duplicate button in the project library dialog
Fix #1585
2016-10-18 16:55:49 +02:00
pyup.io bot
b7f68afbf1 Update dependencies from pyup
* Pin pep8 to latest version 1.7.0
* Pin pypiwin32 to latest version 219
* Pin pytest to latest version 3.0.3
* Pin pytest-capturelog to latest version 0.7
* Pin pytest-pythonpath to latest version 0.7.1

* Pin pytest-timeout to latest version 1.0.0
2016-10-18 15:21:44 +02:00
Julien Duponchelle
08634f330c Fix error introduce in previous commits 2016-10-18 12:04:55 +02:00
Julien Duponchelle
83e35e6aa0 Fix duplicates in recent project list
Fix #1584
2016-10-18 11:28:40 +02:00
Julien Duponchelle
dc3bfef038 Fix a project override error 2016-10-18 11:26:18 +02:00
Julien Duponchelle
c13bb77b08 Fix Duplicated node in node summary when restoring a snapshot
Fix #1571
2016-10-18 10:12:36 +02:00
Julien Duponchelle
fab621bb40 Try pyup.io 2016-10-18 09:41:27 +02:00
Julien Duponchelle
bb760cd861 Fix a crash in the VMware / VirtualBox wizard 2016-10-17 18:44:00 +02:00
Julien Duponchelle
59e7b3fd93 If console host is 0.0.0.0 use controller address 2016-10-17 18:30:44 +02:00
Julien Duponchelle
315870aa09 Fix save issue when importing an appliance
Fix #1564
2016-10-17 14:26:01 +02:00
Julien Duponchelle
5ed17acd6b Strip HTML in console view logs and log files
Fix #1576
2016-10-17 10:01:55 +02:00
Julien Duponchelle
d0dde822dd Fix TypeError: _expandAllSlot() takes 1 positional argument but 2 were given
Fix #1577
2016-10-14 23:02:22 +02:00
Julien Duponchelle
e3023532ed Fix Cannot open created project by using Recents projects
Fix #1544
2016-10-14 22:57:19 +02:00
grossmj
2a4c229c9d Update edit project Ui. 2016-10-08 14:51:00 -06:00
Julien Duponchelle
7b77627db7 Update crash report key 2016-10-07 10:31:36 +02:00
Julien Duponchelle
fd5f32bcc4 Fix a crash when exporting debug without project open 2016-10-05 16:29:30 +02:00
Julien Duponchelle
7e7eecfa3e Fix a crash 2016-10-05 16:28:33 +02:00
Julien Duponchelle
8325339b58 Fix a crash in rare condition when logging informations to the console 2016-10-05 11:35:47 +02:00
Julien Duponchelle
b39185ceb3 Fix a crash in compute summary view 2016-10-05 11:01:55 +02:00
Julien Duponchelle
d93100f3c3 Add a text about how to change the topology size in 2.0 in general preferences
Fix #1561
2016-10-05 10:36:11 +02:00
Julien Duponchelle
1691558989 Merge branch 'master' into 2.0 2016-10-05 09:36:11 +02:00
Julien Duponchelle
17cabba48f Improve warning when connection issue to GNS3 VM 2016-10-05 09:32:31 +02:00
Julien Duponchelle
c9a2cc05ea Fix crash in setup wizard 2016-10-04 21:11:18 +02:00
Julien Duponchelle
f9ac5302ca Fix the wizard for creating appliance template doesn't support remote main server
Fix #1550
2016-10-04 20:44:32 +02:00
Julien Duponchelle
7c8c8dfc20 Appliance wizard support remote controller
Ref #1550
2016-10-04 19:22:47 +02:00
Julien Duponchelle
6622bc7560 Fix Browse button is not working in the local server page in the setup wizard
Fix #1559
2016-10-04 17:14:21 +02:00
Julien Duponchelle
3df7bd99eb Fix test 2016-10-04 17:11:40 +02:00
Julien Duponchelle
da1636af60 Check if local server is running in the setup wizard
Fix #1560
2016-10-04 16:45:36 +02:00
Julien Duponchelle
2378d7ff78 Hide setup wizard after first successful run 2016-10-04 16:00:59 +02:00
Julien Duponchelle
c2f357cc0e Import appliance and New project are display at the same time
Fix #1558
2016-10-04 15:58:33 +02:00
Julien Duponchelle
f2bd85d803 Support remote controller in the setup wizard
Fix #1549
2016-10-04 15:44:56 +02:00
Julien Duponchelle
ec3a856c59 Fix When importing a gns3a the correct qemu binary is not selected
Fix #1556
2016-10-03 22:56:13 +02:00
Julien Duponchelle
1a55487e7b Increase creation timeout for docker container 2016-10-03 22:30:54 +02:00
Julien Duponchelle
0f0ac33345 Make WaitForLambdaWorker more crash proof 2016-10-03 18:41:36 +02:00
Julien Duponchelle
d0b4e5045b Fix a crash when importing appliance
Fix #705
2016-10-03 18:30:36 +02:00
Julien Duponchelle
393cff0343 Fix error in import appliances 2016-10-03 17:24:15 +02:00
Julien Duponchelle
8e56b59bb8 Try to fix the a segfault when importing appliance
Fix https://github.com/GNS3/gns3-server/issues/705
2016-10-03 15:38:56 +02:00
Julien Duponchelle
a939dfe37f Fix crash in upload images 2016-10-03 12:34:51 +02:00
Julien Duponchelle
9b7e06bd54 Trust the server for link creation error (avoid sync issue)
Fix #1553
2016-10-03 12:31:53 +02:00
Julien Duponchelle
cc2f7920b8 Try to fix crash when import appliances
Fix #705
2016-10-03 10:44:37 +02:00
Julien Duponchelle
66a69dd22d Fix an Error in server preference page
Fix #1551
2016-10-03 10:36:58 +02:00
Julien Duponchelle
d3f7eaee1c Fix compatibility with remote server of 1.X
Fix https://github.com/GNS3/gns3-server/issues/696
2016-09-30 16:04:00 +02:00
Julien Duponchelle
3200f4cd28 New appliance dialog should not be display if you cancel the setup wizard
Fix #1545
2016-09-30 10:56:01 +02:00
Julien Duponchelle
fc04b30b7e 2.0.0dev2 2016-09-29 20:41:50 +02:00
Julien Duponchelle
716f65786d 2.0.0 alpha 1 2016-09-29 16:59:35 +02:00
Julien Duponchelle
0c397ba0a8 Retry connection to the server
Fix #1542
2016-09-29 11:38:44 +02:00
Julien Duponchelle
bff8a09147 Change seperator for images directories otherwise bug on windows 2016-09-27 17:09:53 +02:00
Julien Duponchelle
f65ea13c6f Fix tests on Windows 2016-09-27 14:21:59 +02:00
Julien Duponchelle
3975b09898 Add 0.0.0.0 to the list of possible host binding
Fix #1506
2016-09-27 12:03:18 +02:00
Julien Duponchelle
6525d3130c At the end of the setup wizard display add appliance dialog
Fix #1528
2016-09-26 15:45:16 +02:00
Julien Duponchelle
5d8ad83cbe Make first screen of the setup wizard more welcome
Fix #1529
2016-09-23 18:55:11 +02:00
Julien Duponchelle
13a819ee87 Display serial link with a serial line
Fix #1538
2016-09-23 10:36:22 +02:00
grossmj
cd1beb5191 Changes spacer in project dialog. 2016-09-22 22:22:15 -06:00
Julien Duponchelle
483259ba2c Fill cloud interface server side
Fix https://github.com/GNS3/gns3-gui/issues/1535
2016-09-22 17:47:26 +02:00
Julien Duponchelle
3d828c42de Fix tests 2016-09-22 15:55:39 +02:00
Julien Duponchelle
d70dbe82d7 Fix invalid port number for cloud
Fix #1533
2016-09-22 15:44:23 +02:00
Julien Duponchelle
243c5a0f82 Display an error if can't create capture file
Fix #1532
2016-09-22 14:48:43 +02:00
Julien Duponchelle
f4470d8190 Try to improve to speed of Project Dialog with large number of project
Fix #1525
2016-09-22 14:40:58 +02:00
Julien Duponchelle
b435163a3c Prevent a crash in VPCS
Fix #1531
2016-09-22 11:44:47 +02:00
Julien Duponchelle
26f6315b69 Better protection of topologies summary slots
Fix #1526
2016-09-22 11:19:01 +02:00
Julien Duponchelle
b81a02fbb4 Update crash report key 2016-09-22 10:47:02 +02:00
Julien Duponchelle
b19988784f Merge branch 'master' into 2.0 2016-09-21 17:51:20 +02:00
Julien Duponchelle
5caf576f83 Add vpcus and ram settings for GNS3 VM in preferences pages
Fix #1445
2016-09-21 17:08:15 +02:00
Julien Duponchelle
e61b132c93 Fix a bug in setup wizard when you reduce the ram and increase it 2016-09-21 14:55:51 +02:00
Julien Duponchelle
41b826e9ac Make it clear that asa will not work on Windows 10 2016-09-21 12:34:54 +02:00
Julien Duponchelle
4079f19e25 Repare setup wizard
Ref #1329
2016-09-21 12:01:00 +02:00
Julien Duponchelle
04f108cbdf Fix multi drop
Fix #1524
2016-09-21 10:07:53 +02:00
Julien Duponchelle
e222e3e7c2 Allow to change the size of the scene
https://github.com/GNS3/gns3-server/issues/683
2016-09-21 09:44:13 +02:00
grossmj
cb687205a4 Change text in GNS3 VM preferences. 2016-09-20 20:41:55 -06:00
grossmj
4ef19056bb Merge remote-tracking branch 'origin/master' 2016-09-20 17:46:56 -06:00
grossmj
8a4fb55cdf Changes wording in VM wizards. 2016-09-20 17:46:42 -06:00
Julien Duponchelle
805b573370 Fix port name formatting
Fix #1523
2016-09-20 16:34:19 +02:00
Julien Duponchelle
3f87719d02 Bring back import devices from 1.5
Fix #1411
2016-09-20 10:53:26 +02:00
Julien Duponchelle
2a27bb560c Fix a traceback when dragging an IOS router
Fix #1522
2016-09-20 09:51:39 +02:00
Julien Duponchelle
73dbe68301 Display an error if winpcap or npcap is not installed
Fix https://github.com/GNS3/gns3-server/issues/674
2016-09-20 09:43:50 +02:00
grossmj
c2bd4c8984 Force content margins for tab layouts. 2016-09-19 11:17:23 -06:00
Julien Duponchelle
3021cfb164 Fix crash in cloud 2016-09-18 21:45:36 +02:00
Julien Duponchelle
794f317f83 Fix crash in nat node 2016-09-15 18:42:10 +02:00
Julien Duponchelle
e357581587 Fix Sometimes "Duplicate" put text too far in topology
Fix #1501
2016-09-15 18:36:17 +02:00
Julien Duponchelle
e46b699fcb Custom symbol from gns3a are not working
Fix #1515
2016-09-15 18:02:33 +02:00
Julien Duponchelle
c426ea6e03 Allow blank password for remote controller
Fix #1497
2016-09-15 17:36:58 +02:00
Julien Duponchelle
b0a1fdb65a Fix a crash
Fix #1516
2016-09-15 17:22:16 +02:00
Julien Duponchelle
4515620259 Fix import issue with gns3a
Fix #1507
2016-09-15 17:20:16 +02:00
Julien Duponchelle
c36695c59a Dissallow unknown extensions
Fix #1490
2016-09-15 17:12:09 +02:00
Julien Duponchelle
090caa967b Do not show progress when reconnect to fail controller
Fix #1496
2016-09-15 16:20:00 +02:00
Julien Duponchelle
e9ac774464 Do not show progress when refresh list of computes
Fix #1498
2016-09-15 16:15:30 +02:00
Julien Duponchelle
de2de45196 Fix crash in Dynamips preferences
Fix #1513
2016-09-15 16:11:54 +02:00
Julien Duponchelle
64dd0e0be3 Display errors about link creation 2016-09-15 14:49:35 +02:00
Julien Duponchelle
6cd5438c89 Fix duplicate in some cases for interfaces
Fix #1502
2016-09-15 11:50:31 +02:00
Julien Duponchelle
df5a09b46d Fix save project as location
Fix #1503
2016-09-14 19:12:28 +02:00
Julien Duponchelle
cba03a7539 Display error when you can't save as 2016-09-14 17:46:32 +02:00
Julien Duponchelle
069d02d908 Fix a crash when deleting an ethernet switch
Fix #1511
2016-09-14 17:22:19 +02:00
Julien Duponchelle
a207ba61de Fix crash in cloud settings 2016-09-14 16:49:11 +02:00
Julien Duponchelle
496db6427d Update node when you release the mouse
Fix #1494
2016-09-14 15:52:26 +02:00
Julien Duponchelle
1bcf6699f0 Get port names from server
Ref #1502, https://github.com/GNS3/gns3-server/issues/676
2016-09-14 15:30:21 +02:00
Julien Duponchelle
fa12721c3c Cleanup dead code around ports 2016-09-14 11:42:07 +02:00
Julien Duponchelle
65ad43431c Allow node are hotplug now 2016-09-14 11:42:07 +02:00
Julien Duponchelle
081544e778 ports => ports_mapping to avoid confusion 2016-09-14 11:42:07 +02:00
Julien Duponchelle
a30daf03d4 Fix Can't remove a slot from dynamips device
Fix #1510
2016-09-14 11:41:22 +02:00
Jeremy Grossmann
f80af230af Merge pull request #1425 from GNS3/colorblind
Support for colorblind people
2016-09-13 14:33:03 -06:00
Julien Duponchelle
71125a4b58 Fix crash in frame relay switch
Fix #1500
2016-09-13 16:09:21 +02:00
Julien Duponchelle
c1dfaf13fb Force icon size in nodes view 2016-09-08 22:25:23 +02:00
Julien Duponchelle
03a3081361 More debug for #1493 2016-09-08 22:02:27 +02:00
Julien Duponchelle
b5715e46d2 Merge branch 'master' into 2.0 2016-09-08 20:56:12 +02:00
Jeremy Grossmann
3aa9ed61c6 Merge pull request #1488 from GNS3/error_bad_version
Display an error if settings come from a more recent version of GNS3
2016-09-08 12:01:14 -06:00
grossmj
0b6cc588b6 Changed sentence. 2016-09-08 12:00:47 -06:00
Julien Duponchelle
ed4af4a8e7 Avoid to be spam by GNS3 VM errors 2016-09-08 19:52:08 +02:00
Julien Duponchelle
c1f6c3ddeb No error is display if refresh the list of GNS3 VM failed in settings
Fix #1492
2016-09-08 19:02:22 +02:00
Julien Duponchelle
d57652815e Support for colorblind people
Fix #1340
2016-09-08 16:22:37 +02:00
Julien Duponchelle
ea3191739b Fix tests 2016-09-08 16:21:39 +02:00
Julien Duponchelle
378b4f973b Display download url for the GNS3 VM in the preferences
Like in the setup wizard

Ref #1489
2016-09-08 16:00:18 +02:00
Julien Duponchelle
6ecbe59011 Suspend the GNS3 VM
Fix https://github.com/GNS3/gns3-server/issues/656
2016-09-08 15:31:42 +02:00
Julien Duponchelle
2fcaa1f6cc Fix crash in server preferences page 2016-09-08 15:02:59 +02:00
Julien Duponchelle
f0a7582fd2 Display an error if settings come from a more recent version of GNS3
GNS3 patch level version are compatible (ex 1.5.3 and 1.5.2). But if you open
settings from 1.6.1 with 1.5.1 you will have an error

Fix #1487
2016-09-08 12:54:32 +02:00
Julien Duponchelle
2da076a501 Remove a todo already done in another place of the code 2016-09-08 12:30:35 +02:00
Julien Duponchelle
f31cc4806f Fix error when shutdown local server
Fix https://github.com/GNS3/gns3-server/issues/673
2016-09-08 12:29:15 +02:00
Julien Duponchelle
ae228988a5 Merge branch 'master' into 2.0 2016-09-08 12:16:24 +02:00
Julien Duponchelle
185f0463d4 Fix Error when no GNS3 VM is configured and you click on new Docker or IOU
Fix #1486
2016-09-08 12:14:16 +02:00
Julien Duponchelle
cf668e774b Remove the setting slow_device_start_all
Fix #1485
2016-09-08 10:36:45 +02:00
Julien Duponchelle
b933cdd950 Fix a crash when frozen 2016-09-08 10:21:52 +02:00
Julien Duponchelle
f38d3bdb8e Allow to enable profile selection at startup
Fix #1484
2016-09-07 20:23:27 +02:00
Julien Duponchelle
2c5ed9c884 Disable setup wizard 2016-09-07 18:40:31 +02:00
Julien Duponchelle
f2e457de6c Fix VPCS lost his config
Fix #628
2016-09-07 16:46:24 +02:00
Julien Duponchelle
6b146fc7a7 Process node update events
Fix https://github.com/GNS3/gns3-gui/issues/1482, https://github.com/GNS3/gns3-gui/issues/1483
2016-09-07 15:52:30 +02:00
Julien Duponchelle
25b44a2070 Merge branch 'master' into 2.0 2016-09-07 14:21:12 +02:00
Julien Duponchelle
ac8ef05b06 Disallow / in docker container name
Fix https://github.com/GNS3/gns3-server/issues/668
2016-09-07 14:20:25 +02:00
Julien Duponchelle
663185d93e Add hub, switch and cloud in the new template appliance dialog
Fix #1479
2016-09-07 12:18:37 +02:00
Julien Duponchelle
61ac6ed6e0 Fix crash at the end of the cloud wizard
Fix #1480
2016-09-07 11:38:50 +02:00
Julien Duponchelle
0fa51bcd36 Add a default VPCS node
Fix #1382
2016-09-07 10:50:09 +02:00
Julien Duponchelle
f000425350 Fix After adding a router via the new appliance button the settings are not saved
Fix #1478
2016-09-07 10:22:45 +02:00
Julien Duponchelle
8df07808a9 Fix a crash in IOS template edit 2016-09-07 10:22:27 +02:00
Julien Duponchelle
7f169261d4 Remove --controller 2016-09-07 10:08:37 +02:00
Julien Duponchelle
a86c728a99 Fix error when dragging a node and not default Z
Fix #1477
2016-09-07 09:52:52 +02:00
Julien Duponchelle
11d56d1ea7 Fix can't open two GUI
Fix #1475
2016-09-06 18:44:13 +02:00
Julien Duponchelle
9c52cf0b0b Fix layer is lost & PEP8 cleanup
Fix #1473
2016-09-06 18:17:01 +02:00
Julien Duponchelle
cd96492dff Set a minimum height for item in nodes dock
Fix #1476
2016-09-06 17:57:31 +02:00
Julien Duponchelle
43ab1deb24 Fix position are lost when editing multiple items
Fix #1472
2016-09-06 17:51:54 +02:00
Julien Duponchelle
646bf10017 When multiple node are selected select the group config by default 2016-09-06 16:24:04 +02:00
Julien Duponchelle
6a23874054 Test port name 2016-09-06 15:17:44 +02:00
Julien Duponchelle
b6fe18b975 Fix icon missing in node dock
Fix #1471
2016-09-06 14:48:04 +02:00
Julien Duponchelle
84125fe463 Support right click on VPCS template
Ref #1382
2016-09-06 14:11:53 +02:00
Julien Duponchelle
12732715bd Use the VPCS icon
Ref #1382
2016-09-06 13:31:24 +02:00
Julien Duponchelle
ece0b94ae8 Add VPCS template from the new appliance button
Ref #1382
2016-09-06 13:25:12 +02:00
Julien Duponchelle
84d0532039 Support port name format
Fix  #1400, https://github.com/GNS3/gns3-server/issues/667
2016-09-06 11:46:14 +02:00
Julien Duponchelle
ab68c1f1ab Fix crash with empty config 2016-09-06 10:13:14 +02:00
Julien Duponchelle
b360d8d931 Detection of application outside /Applications more reliable 2016-09-06 09:52:27 +02:00
Julien Duponchelle
f9681f2766 Fix When reloading a topology with Nat we can't link
Fix #1470
2016-09-05 18:54:24 +02:00
Julien Duponchelle
e8a09eef72 Repare console open 2016-09-05 18:08:59 +02:00
Julien Duponchelle
3290639e54 Fix I can't change list of adapters
Fix #1467
2016-09-05 15:27:24 +02:00
Julien Duponchelle
02d3275475 Fix crash when changing IOU symbol
Fix #1463
2016-09-05 14:33:56 +02:00
Julien Duponchelle
fd92049cda Remove the internet VM when migrate to 2.0
Fix https://github.com/GNS3/gns3-server/issues/658
2016-09-05 11:28:51 +02:00
Julien Duponchelle
f48a5655ed Display an error if GNS3 is start from outside /Application
Fix #1468
2016-09-05 09:20:44 +02:00
Julien Duponchelle
22267b4123 Fix a crash when you cancel connection to the controller 2016-09-05 09:08:19 +02:00
Julien Duponchelle
b06230ef3d Try to reconnect to the controller if connection failed
Fix #1459
2016-09-05 08:49:01 +02:00
Bernhard Ehlers
87b37e2839 Update iTerm3 console settings
Fix #1466

Signed-off-by: Julien Duponchelle <julien@gns3.net>
2016-09-03 22:07:45 +02:00
Julien Duponchelle
0f3dd2e05d Merge branch 'master' into 2.0 2016-09-03 21:53:54 +02:00
Julien Duponchelle
0495429df8 Fix rename ethernet switch doesn't release the name
Fix #1460
2016-09-03 21:50:58 +02:00
Julien Duponchelle
2e97f1e037 Fix sometimes console host is missing
Fix #1464
2016-09-02 16:26:52 +02:00
Julien Duponchelle
8133ba61a5 Fix tests 2016-09-02 16:15:47 +02:00
Julien Duponchelle
4cce5cd4ff Fix capture status is incorrect when reconnect to a project
Fix #1464
2016-09-02 15:56:47 +02:00
Julien Duponchelle
1f1f95e3da Fix creation of drawing 2016-09-02 12:02:44 +02:00
Julien Duponchelle
7c9c66470d Support pcap capture on remote controller
Ref #1280
2016-09-02 10:57:06 +02:00
Julien Duponchelle
da5bead39c Fix tests 2016-09-01 16:35:43 +02:00
Julien Duponchelle
68a0c74a1f Improve display of node error (also for GNS3 VM errors)
Fix #1446
2016-09-01 15:38:11 +02:00
Julien Duponchelle
949d1a900a Remove MessageBox it was almost never used 2016-09-01 13:28:34 +02:00
Julien Duponchelle
88c7a472b1 Handle error when controller is not available
Fix #1373
2016-09-01 10:36:01 +02:00
Julien Duponchelle
4b49501630 Fix open project from the CLI
Fix #1456
2016-09-01 10:27:56 +02:00
Julien Duponchelle
9eb71b870a Temporary deactivate setup wizard
Ref #1329
2016-09-01 10:10:09 +02:00
Julien Duponchelle
5d46560427 Allow to select multiple project to delete 2016-08-31 17:18:51 +02:00
Julien Duponchelle
d7856af6db Fix Sometimes node are duplicated
Fix #1455
2016-08-31 16:54:04 +02:00
Julien Duponchelle
c0a093d044 Support overwrite existing project
Fix #1435
2016-08-31 15:38:56 +02:00
Julien Duponchelle
03c7df9dad Improve a lot the speed for parsing notifications
This use a different signal to detect that data is downloaded.
With that, detection of new notification is instant when you
have multiple notifications.

Fix #1447
2016-08-31 11:34:03 +02:00
Julien Duponchelle
d847316914 Merge branch 'master' into 2.0 2016-08-31 09:24:52 +02:00
Julien Duponchelle
190e17b445 Fix tests 2016-08-31 09:23:14 +02:00
Julien Duponchelle
ce5d1b56f0 Support for VNC display number in command line replacement
Fix #1453
2016-08-31 09:20:50 +02:00
Julien Duponchelle
cb7cbc15b3 Merge branch 'master' into 2.0 2016-08-31 09:11:17 +02:00
Julien Duponchelle
dc6756da04 Fix a crash when a directory with image is not accessible at gns3a
import

Fix #1454
2016-08-31 09:10:01 +02:00
Julien Duponchelle
e4eeb437eb Fix the invalid VM was selected in GNS3 VM preferences
Fix #1452
2016-08-30 10:25:32 +02:00
Julien Duponchelle
81b94070ac Remote GNS3 VM support
Fix https://github.com/GNS3/gns3-server/issues/623
2016-08-30 10:19:36 +02:00
Julien Duponchelle
de36a04d88 Server select use the server capabilities to filter what should be
display
2016-08-29 18:20:02 +02:00
Julien Duponchelle
1287b77dfe Watch for compute status change 2016-08-29 17:49:17 +02:00
Julien Duponchelle
146bb004c0 Save preference page only when the page change
Fix #1443
2016-08-26 15:05:42 +02:00
Julien Duponchelle
d26abecea7 Fix Even when you don't modify the preferences the pref dialog say "You have unsaved preferences."
Fix #1443
2016-08-26 15:02:36 +02:00
Julien Duponchelle
d2da14a951 Display name of preferences pages with changes
Ref #1443
2016-08-26 14:34:25 +02:00
Julien Duponchelle
4ae17a1f66 Prevent a crash 2016-08-26 12:14:02 +02:00
Julien Duponchelle
473f60167d Fix crash in settings 2016-08-25 14:19:55 +02:00
Julien Duponchelle
5377590520 Fix tests 2016-08-25 11:17:15 +02:00
Julien Duponchelle
58fe1f6e2b Stop send --host and --port as parameter to the GNS3 server
The server can already get them from config file. And since
we are using the same config file we have no longer risk of sync
issues.
2016-08-25 11:15:50 +02:00
Julien Duponchelle
c0564c89c8 Send GNS3 VM settings from the GUI
Fix #1441
2016-08-25 09:34:05 +02:00
Julien Duponchelle
34d27dc120 Display a settings button in the project dialog page
Fix #1442
2016-08-24 18:53:05 +02:00
Julien Duponchelle
d907af46bc In case of exception on dev machine exit immediately 2016-08-24 18:44:45 +02:00
Julien Duponchelle
a8055471cd Stop logging vmware error when we don't use vmware
Fix #1439
2016-08-23 21:45:39 +02:00
Julien Duponchelle
317c28eaf2 Fix start of the local server 2016-08-23 19:34:24 +02:00
Julien Duponchelle
d2b6aeddbd Display error when not connected to the controller
Ref #1373
2016-08-23 19:02:05 +02:00
Julien Duponchelle
4285d01a19 Fix crash 2016-08-23 18:44:36 +02:00
Julien Duponchelle
802c59a1d1 Hide in project dialog what is not require for remote controller
Fix #1280
2016-08-23 17:09:26 +02:00
Julien Duponchelle
f1879c8d4b Hide menu that should not be visible when using a remote controller
Ref #1280
2016-08-23 16:42:22 +02:00
Julien Duponchelle
97ad294623 Fix isolation issue between settings profil 2016-08-23 16:35:14 +02:00
Julien Duponchelle
6147dcd304 Allow connection to a remote controller
Ref #1280
2016-08-23 16:11:18 +02:00
Julien Duponchelle
d900842363 Merge branch 'profil_support' into 2.0 2016-08-23 10:07:21 +02:00
Julien Duponchelle
e6ac92abb4 Fix error with Qt 5.2
Fix #1431
2016-08-22 19:02:03 +02:00
Julien Duponchelle
944b5fc6c9 Support for profil settings
This PR add a --profil command line arguments.

If set a new set of settings will be create in
~/GNS3/profiles/PROFILENAME

Otherwise it's use the default location.

This allow to test settings without losing
original.

Also with the correct GUI this allow to switch from
local server to a remote (home / office).
2016-08-22 17:27:37 +02:00
Julien Duponchelle
bf6c645281 Only one location in the code for the path of the configuration file 2016-08-22 15:53:43 +02:00
Julien Duponchelle
14f04e5f88 Fix a status sync issue
Fix #1433
2016-08-22 11:19:43 +02:00
grossmj
ecbf7bd661 Do not add fw0 and p2p0 to the interfaces for cloud and nat objects. FIxes #1436. 2016-08-21 21:47:28 -06:00
Jeremy Grossmann
de15edcd0a Merge pull request #1437 from GNS3/nat
A nat node
2016-08-21 21:45:56 -06:00
grossmj
a5d619d6a8 Update some edit dialogs. 2016-08-20 11:31:17 -06:00
grossmj
271811d376 Cosmetic changes. 2016-08-20 11:10:34 -06:00
grossmj
6ed9652a2a Remove setTabBarAutoHide. Ref #1431. 2016-08-20 10:28:37 -06:00
Julien Duponchelle
0d62811a17 A nat node
Fix #599
2016-08-19 20:01:31 +02:00
Julien Duponchelle
615f1f2b5d Topology schema is now on controller 2016-08-19 19:14:12 +02:00
Julien Duponchelle
721bff01b0 Fix restore snapshots when running two clients
Fix #1417
2016-08-19 17:38:55 +02:00
Julien Duponchelle
69f671106c Fix invalid error message on Linux in qemu wizard 2016-08-19 10:08:21 +02:00
Julien Duponchelle
0c59970974 Merge branch 'master' into 2.0 2016-08-18 22:15:32 +02:00
Julien Duponchelle
d161a75ab2 1.5.3dev1 2016-08-18 22:14:58 +02:00
Julien Duponchelle
b87f2b2952 1.5.2 2016-08-18 21:58:17 +02:00
Julien Duponchelle
a0b4c38a44 Fix qemu wizard 2016-08-18 19:39:02 +02:00
Julien Duponchelle
c9cc98ae39 Display the warning about OSX and Windows not recommended for qemu
even when you have only one server.

Fix #1397
2016-08-18 18:56:49 +02:00
Julien Duponchelle
ad492e2b90 Fix sync between GUI and server.conf
Fix #1330
2016-08-18 18:50:30 +02:00
Julien Duponchelle
a977042017 Fix small crashes 2016-08-18 18:30:49 +02:00
Jeremy Grossmann
9e4b5ad02b Merge pull request #1423 from GNS3/vmware_wizard
Make more clear that VMware VM are not ESXi
2016-08-18 09:52:13 -06:00
Julien Duponchelle
90b9b2d29c The delete project button is display only for the project library 2016-08-18 17:27:31 +02:00
Julien Duponchelle
54b6efce59 Fix Save preference is broken
Fix #1421
2016-08-18 17:19:04 +02:00
Julien Duponchelle
1f77a825b3 Fix The wizard for Docker allow to select local on mac and windows
Fix #1406
2016-08-18 16:03:55 +02:00
Julien Duponchelle
283d787c8d Handle error when node can't be create
Fix #1398
2016-08-18 14:49:33 +02:00
Julien Duponchelle
47be4d39c2 Properly handle the error project name duplicate
Fix #1379
2016-08-18 14:28:28 +02:00
Julien Duponchelle
8a4fab9528 Merge branch 'master' into 2.0 2016-08-18 14:18:59 +02:00
Julien Duponchelle
a31586fac9 Fix crash after a bad merge
Fix #1424
2016-08-18 14:12:49 +02:00
Julien Duponchelle
3b88c72778 Cleanup the resources.qrc of references to non existing files 2016-08-18 11:25:55 +02:00
Julien Duponchelle
0e4a5da71a Merge branch 'master' into 2.0 2016-08-18 10:41:35 +02:00
Julien Duponchelle
2a6327b2f2 Make more clear that VMware VM are not ESXi
Fix #1420
2016-08-18 10:29:01 +02:00
Jeremy Grossmann
d4d8adf4ac Merge pull request #1375 from GNS3/qslot
Protect one more method from deleted object
2016-08-17 15:35:19 -06:00
Julien Duponchelle
8492a31dd7 Send label settings to the controller 2016-08-17 17:13:35 +02:00
Julien Duponchelle
bb91402d2c Remove dirty code for sync label position between nodes server is
smarter
2016-08-17 16:12:40 +02:00
Julien Duponchelle
35d8b4f848 Fix you can't quit GNS3 when controller is down 2016-08-17 12:01:21 +02:00
Julien Duponchelle
073dc1afe7 We no longer need to compute node size on client
https://github.com/GNS3/gns3-server/issues/620
2016-08-17 12:00:18 +02:00
Julien Duponchelle
b61e6dabd4 Fix tab display when you open new project 2016-08-16 19:18:56 +02:00
Julien Duponchelle
316fa688c3 Fix to project lost when you open the new blank project dialog 2016-08-16 19:16:36 +02:00
Julien Duponchelle
0724387257 Merge node create and update answer parsing to avoid mistake
This fix the bug where the when project is auto start the node
status was still red.
2016-08-16 15:51:23 +02:00
Julien Duponchelle
8e87c8cdbe Allow to configure auto start/auto close/auto open 2016-08-16 14:07:47 +02:00
Julien Duponchelle
9553d3ba25 Allow to delete a project from the project list
Fix #1419
2016-08-16 13:33:06 +02:00
Julien Duponchelle
4bccd6de25 Add in the project menu the list of recent opened projects
Fix #1410
2016-08-16 11:50:23 +02:00
Julien Duponchelle
dd5bafca0a Add an edit project dialog
For the moment only edit name is supported and sync between
the GUI but the architecure is here.

Ref #1410
2016-08-16 11:12:38 +02:00
Julien Duponchelle
6d3e28226a In telnet console command line replace %c by connection string
Ref #1403
2016-08-15 15:48:48 +02:00
Julien Duponchelle
0fc040773a Fix path for recently opened projects 2016-08-15 15:35:36 +02:00
Julien Duponchelle
1f2294f9bf Correctly support closing project when two client are connected
Fix https://github.com/GNS3/gns3-server/issues/602
2016-08-15 13:38:39 +02:00
Julien Duponchelle
bed3f1d8fa Delete ProjectManager and merge it in Topology
Ref #1326
2016-08-15 12:59:41 +02:00
Julien Duponchelle
b1da0b8279 Merge pull request #1412 from athmane/master
Add AppData and Desktop files for Gnome software support and such
2016-08-15 10:38:06 +02:00
grossmj
32f3137f4d Setup wizard to configure GNS3 VM or Local server. 2016-08-11 16:00:08 -06:00
grossmj
df10bca2c0 Fixes local server and uBridge paths loading. 2016-08-10 16:19:53 -06:00
Athmane Madjoudj
21fba1c4f7 Fix appdata 2016-08-05 17:59:57 +00:00
grossmj
f56e7e8dd8 Remove setTabBarAutoHide property in project dialog. 2016-08-04 10:43:00 -06:00
Athmane Madjoudj
41f6119118 Add AppData and Desktop files 2016-08-02 21:21:51 +00:00
Julien Duponchelle
7732f2a27e Merge branch 'master' into 2.0 2016-07-28 15:13:35 +02:00
Julien Duponchelle
0be4f31162 Fix sample readme 2016-07-28 14:22:24 +02:00
Julien Duponchelle
6bc8428dd0 Fix you can not select the server for VPCS
Fix #1372
2016-07-28 12:48:03 +02:00
Julien Duponchelle
fd92e92a4f Fix error when removing an interface from a cloud
This error was when the interface no longer exist on the system.

Fix #1383
2016-07-28 12:22:18 +02:00
Julien Duponchelle
9dc7a4447b Fix crash when scanning a directory for image and you don't have permission on a file
Fix #1402
2016-07-28 12:17:14 +02:00
Julien Duponchelle
c2a597ffcf Repare edit configuration files 2016-07-28 12:06:47 +02:00
Julien Duponchelle
fc4850afab Fix placeholder symbol 2016-07-28 12:03:08 +02:00
Julien Duponchelle
6c31de36ac Import export 2016-07-27 21:45:13 +02:00
Julien Duponchelle
4082aa8d77 Import config 2016-07-27 21:35:05 +02:00
Julien Duponchelle
71a835ff5f Export configuration 2016-07-27 21:08:22 +02:00
Julien Duponchelle
b156df6fc2 Allow to edit a configuration file from the GUI
Fix #1407
2016-07-27 18:49:49 +02:00
Julien Duponchelle
d077621ee9 Fix a crash when pos is None in ImageItem 2016-07-27 09:38:06 +02:00
Julien Duponchelle
3624502a23 restore snapshots in the GUI 2016-07-26 19:38:29 +02:00
Julien Duponchelle
c9f12fece7 PyQt 5.7 2016-07-26 18:27:36 +02:00
Julien Duponchelle
0f43fd4560 Place holder for loading symbols for nodes
Fix #1377
2016-07-25 19:46:47 +02:00
Julien Duponchelle
1c85f980d3 Fix Transport selection via DSN is deprecated. You should explicitly
pass the transport class to Client()

Fix #1341
2016-07-25 19:33:08 +02:00
Julien Duponchelle
49428d3ead Hide open project field when importing a project in new project dialog 2016-07-25 19:11:17 +02:00
Julien Duponchelle
2f48752ff2 Show a dialog when importing a project 2016-07-25 18:58:55 +02:00
Julien Duponchelle
48ac89abc9 Replace save as by a export / import
Fix #995
2016-07-25 16:17:01 +02:00
Julien Duponchelle
bd8bad5e4c Make sure the README is saved before closing the file editor dialog 2016-07-22 18:16:46 +02:00
Julien Duponchelle
13c189fb00 Merge branch 'master' into 2.0 2016-07-22 18:10:16 +02:00
Julien Duponchelle
eaab3c3f5e Fix example readme for export 2016-07-22 18:07:23 +02:00
Julien Duponchelle
61fb8246f0 Display error during the import to the user 2016-07-22 18:00:23 +02:00
Julien Duponchelle
b09249b384 Support import of .gns3project 2016-07-21 16:21:38 +02:00
Julien Duponchelle
7d6b98766c Repare edit readme
Fix #1401
2016-07-20 21:51:34 +02:00
Julien Duponchelle
96bcf55942 Display export errors 2016-07-20 17:16:59 +02:00
Julien Duponchelle
7bb6078b13 Tmp fix for reloading Vbox topologies
Ref #1400
2016-07-20 16:35:48 +02:00
Julien Duponchelle
c8d6a4640a Fix a crash when reloading some topologies 2016-07-20 16:27:38 +02:00
Julien Duponchelle
27be2b7a1d Fix a crash in VirtualBox wizard 2016-07-20 16:21:28 +02:00
Julien Duponchelle
b05d682aa3 Export project call the controller 2016-07-20 14:15:39 +02:00
Julien Duponchelle
636b26b0e8 Fix for the GNS3VM wizard 2016-07-20 14:00:38 +02:00
Julien Duponchelle
ae2a111536 Fix In the remote server list in preferences do not display the VM server
Fix #1396
2016-07-20 12:19:04 +02:00
Julien Duponchelle
33796a8bd3 Replace project id in open console
Fix #1395
2016-07-20 12:06:59 +02:00
Julien Duponchelle
695e5d3daa Merge the multiple telnet console open code 2016-07-20 12:00:27 +02:00
Julien Duponchelle
9d805d5d42 Avoid a race condition at label update 2016-07-20 11:59:15 +02:00
Julien Duponchelle
ec3fd63138 Fix drawing area not reset when cancel new project
Fix #1394
2016-07-20 11:25:45 +02:00
Julien Duponchelle
8e5e2d4a0c Fix selection of GNS3 VM in the wizard 2016-07-20 11:22:16 +02:00
Julien Duponchelle
ee6e2b41f7 Add Francesco Colista as contributor 2016-07-19 17:09:00 +02:00
Julien Duponchelle
42c54ef02f Fix enable the list of GNS3 VM
Fix #1391
2016-07-19 13:19:21 +02:00
Julien Duponchelle
227cbfc79a Do not add the VM to the list of remotes servers 2016-07-18 18:59:37 +02:00
Julien Duponchelle
0fd5a1a91d Fix crash when you have no routers nodes 2016-07-18 18:37:03 +02:00
Julien Duponchelle
4406c940b5 Merge branch 'master' into 2.0 2016-07-13 17:40:23 +02:00
Julien Duponchelle
8eab44349f Bring back the warning dialog when no router is configured 2016-07-13 17:37:52 +02:00
Julien Duponchelle
f50f7153dc Fix crash at startup 2016-07-13 15:52:22 +02:00
Julien Duponchelle
a994f65d79 Handle error when cloud can't be created 2016-07-12 18:24:24 +02:00
Julien Duponchelle
1a3a17e480 Protect one more method from deleted object
Always the same issue:
http://enki-editor.org/2014/08/23/Pyqt_mem_mgmt.html

I propose the creation of a qslot that we could use to decorate
all slot to protect them.

We can't wrap Signal or inherit from it :( So it's impossible to
do it for all slots without modifications everywhere.

Fix #1374
2016-07-12 10:04:15 +02:00
grossmj
840e4aec54 Load/save GNS3 VM settings on controller side. 2016-07-11 21:43:01 -06:00
grossmj
74b660af61 Basic GNS3 VM configuration using the setup wizard. 2016-07-11 17:45:23 -06:00
grossmj
cc0c56087a Warn users they must start a node to console to it. Fixes #1314. 2016-07-11 10:08:45 -06:00
grossmj
990e6c0eed Allow customizable VPCS templates. Fixes #1306. 2016-07-10 20:33:19 -06:00
grossmj
3bc6cd8b4d Allow ports in cloud templates. Fixes #867. 2016-07-10 14:55:27 -06:00
grossmj
515119e1fa Fixes some imports 2016-07-09 19:02:23 -06:00
Julien Duponchelle
570303273c Fix color losts in drawing items 2016-07-09 11:48:07 +02:00
Julien Duponchelle
1739cc58d4 Support alpha channel for drawings 2016-07-09 11:28:30 +02:00
Julien Duponchelle
b3a7d42f9d Fix rare crash in server summary
Fix #1371
2016-07-08 13:55:47 +02:00
Julien Duponchelle
17ed1f9806 Fix crash during export
Fix #1370
2016-07-08 13:52:41 +02:00
Julien Duponchelle
1e3883674e Fix crash when you cancel the creation of a new project 2016-07-08 11:26:11 +02:00
Julien Duponchelle
bead888c67 1.5.2dev1 2016-07-07 18:53:25 +02:00
Julien Duponchelle
07fcd66d8d 1.5.1 2016-07-07 18:50:45 +02:00
Julien Duponchelle
0f4cac1b76 Try to fix a crash when reseting interface label
Ref #1369
2016-07-07 14:55:08 +02:00
Julien Duponchelle
89fbc537bf Fix At node creation information about the node label formatting is not send
Fix #1366
2016-07-07 10:05:48 +02:00
Jeremy Grossmann
f0ebdf295f Merge pull request #1358 from GNS3/hot_unlink
Stop node before hot unlink
2016-07-07 03:28:01 +00:00
Julien Duponchelle
d396cb911a Fix some issue recently introduce in HTTPClient 2016-07-06 15:43:03 +02:00
Julien Duponchelle
9064487a3e Remove constant that doesn't seem to have an impact
Fix #1345
2016-07-06 15:31:22 +02:00
Julien Duponchelle
8b03f32f95 Fix Open from a project from command line doesn't work bug
Fix #1346
2016-07-06 15:23:56 +02:00
Julien Duponchelle
3295cc514e Merge branch 'master' into 2.0 2016-07-06 14:40:09 +02:00
Julien Duponchelle
c6df492852 Fix a crash with broken file system
Fix #1365
2016-07-06 14:39:34 +02:00
Julien Duponchelle
565c71cb80 Fix UnboundLocalError: local variable 'callback' referenced before assignment
Fix #1364
2016-07-06 10:35:04 +02:00
Julien Duponchelle
30bd710650 Merge branch 'master' into 2.0 2016-07-06 10:33:53 +02:00
Julien Duponchelle
c0dbf95b94 Fix EtherSwitch default name format
Fix #1348
2016-07-06 10:17:20 +02:00
Julien Duponchelle
7f58837111 Fix double call to /version at startup
It's fixe a deeper issue where the http_client open two connection
at the same time

Fix #1363
2016-07-05 18:31:03 +02:00
Julien Duponchelle
53f609c4d7 Make logs less noisy 2016-07-05 18:13:42 +02:00
Julien Duponchelle
26790fd80d Fix When reopen a project the node label could lost his style
Fix #1362
2016-07-05 18:02:47 +02:00
Julien Duponchelle
cfcb24a732 Now the controller take care of deleting links when you delete a node
Fix https://github.com/GNS3/gns3-server/issues/608
2016-07-05 16:29:32 +02:00
Julien Duponchelle
e31746b676 Rebuild server page after merge 2016-07-05 16:29:20 +02:00
Julien Duponchelle
154435d5a5 Merge branch 'master' into 2.0 2016-07-05 15:36:15 +02:00
Julien Duponchelle
d24a0312d8 Fix crash when you have utf-8 char in the README
Fix #1360
2016-07-05 14:54:56 +02:00
Julien Duponchelle
aa5d8b9377 Fix rare crash when creating a link
Fix #1361
2016-07-05 14:51:46 +02:00
Julien Duponchelle
e9703e03cd Stop node before hot unlink
This patch allow to remove any link even if node is already
running by stopping the node before. This solve the issue #1349
until we get a better support in 2.0.

Fix #1349
2016-07-04 19:23:59 +02:00
Julien Duponchelle
13a8d27349 Prevent a crash due to issue in Qt
Fix #1357
2016-07-04 17:30:09 +02:00
Julien Duponchelle
939f8f52c1 Add another security to prevent client to send empty hostname
Fix #1354
2016-07-04 15:10:23 +02:00
Julien Duponchelle
cb1e062f9b Fix rare crash when deleting interface from the cloud
Fix #1352
2016-07-04 14:51:44 +02:00
Julien Duponchelle
a1d1bc5aea Fix rare crash in topology summary view
Fix #1353
2016-07-04 14:49:31 +02:00
Julien Duponchelle
1d81c0521f Ask user to send explanation if they cross a rare error
Fix #1355
2016-07-04 14:37:58 +02:00
Julien Duponchelle
d3ef916b23 Fix rare crash when deleting a node
Fix #1351
2016-07-04 14:15:36 +02:00
Julien Duponchelle
c9b7259cd7 Hotlink support for Docker
Ref https://github.com/GNS3/gns3-server/issues/596
2016-07-04 11:16:17 +02:00
Julien Duponchelle
fa8c135b22 Sync the link between gui 2016-07-01 21:50:05 +02:00
Julien Duponchelle
9d53d806fd Correct center the node label the first time and beginning of interface
label support
2016-07-01 20:14:08 +02:00
Julien Duponchelle
6f499e6c56 Support rotation for labels 2016-07-01 16:54:41 +02:00
Julien Duponchelle
e66bdc936a Use SVG style for labels 2016-07-01 15:26:53 +02:00
Julien Duponchelle
be34e062e7 Bold & italic support in text item 2016-07-01 15:10:09 +02:00
Julien Duponchelle
5664b32cc5 Start to use a svg style property for label and send node witdh and
height
2016-07-01 14:39:51 +02:00
Julien Duponchelle
6bf0ea63d4 Restore label position
Fix #1344
2016-07-01 12:15:23 +02:00
Julien Duponchelle
628970e588 Sync link creation & removal 2016-07-01 11:37:43 +02:00
Julien Duponchelle
fb68ccad15 Fix crash when using two gui 2016-06-30 18:52:19 +02:00
Julien Duponchelle
d6b394500f When updating a node on a GUI change is visible on other GUI 2016-06-30 18:44:57 +02:00
Julien Duponchelle
32508d60b1 Sync node creation and delete
Ref #1250
2016-06-30 16:14:17 +02:00
Julien Duponchelle
0ae23c30c4 Fix Symbol is lost when reloading project
Fix #1342
2016-06-30 15:08:09 +02:00
Julien Duponchelle
e5f18c5e22 Bring back compute node usage
Fix #1261
2016-06-30 10:12:26 +02:00
Julien Duponchelle
df0f25b234 If project creation fail reset the project in the GUI 2016-06-29 17:49:37 +02:00
Julien Duponchelle
dc1d9e59b0 Merge branch '1.5' into 2.0 2016-06-29 17:22:57 +02:00
Julien Duponchelle
266eb77eb5 Fix typo in the a warning dialog
Fix #1338
2016-06-29 17:16:53 +02:00
Julien Duponchelle
c1cac82081 Fix Remote GNS3 VM requires local server
Fix #1319
2016-06-29 17:14:58 +02:00
Julien Duponchelle
323c787d91 Fix AttributeError: 'NoneType' object has no attribute '_server'
Fix #1335
2016-06-29 17:02:30 +02:00
Julien Duponchelle
41070495ba No timeout when importing a .gns3project
Fix #1336
2016-06-29 17:00:23 +02:00
Julien Duponchelle
037e531b22 Send initial config to the controller 2016-06-29 15:17:44 +02:00
Julien Duponchelle
54713b5d68 Support storing list of devices on the remote server
Fix #589
2016-06-29 15:14:18 +02:00
Julien Duponchelle
d94f9a91db Fix a crash in preferences
Fix #1337
2016-06-29 14:41:32 +02:00
Julien Duponchelle
516b8e848f Full symbol on controller support 2016-06-28 22:20:50 +02:00
Julien Duponchelle
6d1d1705b2 Support PNG for symbols 2016-06-28 21:51:54 +02:00
Julien Duponchelle
666a527aa3 Remove symbols not use in interface.
They are available in the controller when you use it
for nodes.
2016-06-28 17:03:35 +02:00
Julien Duponchelle
f296c7fdad Drop ressources not used in the interface 2016-06-28 17:00:48 +02:00
Julien Duponchelle
58e62da913 Script for detecting unused ressources 2016-06-28 16:56:15 +02:00
Julien Duponchelle
ca364d4d56 All place where we display a symbol we use the version from controller 2016-06-28 16:54:32 +02:00
Julien Duponchelle
2232680ded New crash report key 2016-06-27 20:41:07 +02:00
Julien Duponchelle
b662c54a07 Wip symbol from remote 2016-06-27 20:40:34 +02:00
Julien Duponchelle
cd2f897ff2 1.5.1dev1 2016-06-27 20:34:14 +02:00
Julien Duponchelle
c877d4b1d7 1.5.0 2016-06-27 20:30:15 +02:00
Jeremy Grossmann
dc6032aa43 Merge pull request #1333 from GNS3/disallow_export_cloud
Disallow export of project with a cloud
2016-06-27 11:10:21 -06:00
Julien Duponchelle
fec9431ae5 Fix double extension of portable project 2016-06-27 12:47:17 +02:00
Julien Duponchelle
bf1b7e640b Disallow export of project with a cloud
https://github.com/GNS3/gns3-server/issues/590
2016-06-27 12:40:09 +02:00
grossmj
780ab5b14f Docker links are now hot pluggable. 2016-06-24 17:27:35 -06:00
grossmj
7371aebb76 Remove more GNS3VM code from the GUI. Ref #1254. 2016-06-24 15:18:10 -06:00
grossmj
c227f39a03 Allow packet capture on VPCS and Qemu nodes. 2016-06-23 16:52:41 -06:00
Julien Duponchelle
ff794f1578 Use SVG properties instead of style to store info 2016-06-23 18:51:59 +02:00
Julien Duponchelle
f26c342e82 Handle text items in the drawing api 2016-06-23 18:21:20 +02:00
Julien Duponchelle
edacb88ff5 Cleanup topologies test, removed unecessary elments 2016-06-23 13:32:13 +02:00
Julien Duponchelle
4854eac2da Show layer for all drawing items 2016-06-23 13:29:30 +02:00
Julien Duponchelle
60cd105b82 Snap to grid for all drawing items 2016-06-23 13:16:06 +02:00
Julien Duponchelle
184db222c5 Merge branch '1.5' into 2.0 2016-06-23 13:11:07 +02:00
Julien Duponchelle
abcfb9ee12 Handle duplicate of all drawing items 2016-06-23 13:07:45 +02:00
Julien Duponchelle
5f3ba669eb Repare display of symbols 2016-06-23 12:47:29 +02:00
Julien Duponchelle
942d4756c7 Shape => Drawing 2016-06-23 12:26:54 +02:00
Julien Duponchelle
d9b6dfd8d0 Fix test suite 2016-06-23 12:12:11 +02:00
grossmj
ff79e7ad36 Change view grid -> show the grid. 2016-06-22 13:08:20 -06:00
grossmj
ebfdac96ae Check if a link can be removed from a running node. Fixes #1320. 2016-06-22 11:21:13 -06:00
grossmj
e2a85885be Merge remote-tracking branch 'origin/1.5' into 1.5 2016-06-22 10:11:58 -06:00
grossmj
c6b0fb4d65 Hide non implemented console options in general preferences. Ref #1315. 2016-06-22 10:11:42 -06:00
Julien Duponchelle
fb5c4df4db Support sync create of shapes 2016-06-22 18:09:57 +02:00
Julien Duponchelle
9cb4eb775b Send image to the API as SVG element 2016-06-22 17:47:17 +02:00
Julien Duponchelle
8c349e4669 Merge branch '1.5' into 2.0 2016-06-22 14:12:38 +02:00
Bernhard Ehlers
b5d879139a Improve snap to grid
Fix #1327

Signed-off-by: Julien Duponchelle <julien@duponchelle.info>
2016-06-22 13:38:38 +02:00
Bernhard Ehlers
0e05918631 Improve snap to grid
Ref #1327

Signed-off-by: Julien Duponchelle <julien@duponchelle.info>
2016-06-22 11:09:26 +02:00
Julien Duponchelle
c3fee8d323 Change grid color
Ref #1327
2016-06-22 11:09:26 +02:00
Jeremy Grossmann
b5743d9902 Merge pull request #1323 from GNS3/browse_config_directory
A button to open the file browser with the configuration file location
2016-06-21 21:51:46 -06:00
grossmj
44974c04ad Regenerate general preferences Ui. 2016-06-21 21:51:32 -06:00
Julien Duponchelle
336f8d525b Dead code removal 2016-06-21 19:41:26 +02:00
Julien Duponchelle
f76b6afe6a Rotation support for the shapes 2016-06-21 19:39:28 +02:00
Julien Duponchelle
602b58d1df Support z value for shape 2016-06-21 19:23:31 +02:00
Julien Duponchelle
030edccc90 Sync shape delete 2016-06-21 19:16:51 +02:00
Julien Duponchelle
dd3317f4f6 Sync update shape 2016-06-21 19:13:08 +02:00
Julien Duponchelle
f29d0e45b7 Get shapes from the server 2016-06-21 19:03:58 +02:00
Julien Duponchelle
c038ed3db4 Delete shape on remote server 2016-06-21 16:19:00 +02:00
Julien Duponchelle
afcf2a9400 Add a missing email from the crowdfunding 2016-06-21 16:02:20 +02:00
Julien Duponchelle
6bcc4c86e6 Send rectangle and ellipse to the servers 2016-06-21 15:19:29 +02:00
Julien Duponchelle
ded32730bf Fix starting test suites 2016-06-21 09:22:41 +02:00
Julien Duponchelle
2e1b6aef9f Fix a crash 2016-06-20 19:15:25 +02:00
Julien Duponchelle
26d918e218 Avoid a crash with snap to grid and ostinato logo
Fix #1324
2016-06-20 16:22:45 +02:00
Julien Duponchelle
23e1097f89 Add a view grid
Fix #787
2016-06-20 15:19:01 +02:00
Julien Duponchelle
6d1e2d9fab Add Richard Miller to the thanks to 2016-06-20 12:47:27 +02:00
Julien Duponchelle
7c37284901 Merge branch '1.5' into 2.0 2016-06-20 12:45:44 +02:00
Julien Duponchelle
e9384676e1 Fix you can no longer capture if you start stop capture multiple time
Fix #1317
2016-06-20 12:41:22 +02:00
Julien Duponchelle
88bf51c066 Merge branch 'comet0-snap_to_grid' into 1.5 2016-06-20 12:06:24 +02:00
Cometo
fbbe8aff54 Add Snap to Grid to Qt ui file 2016-06-20 10:27:45 +01:00
Julien Duponchelle
e3d441d19f A button to open the file browser with the configuration file location
Fix #1321
2016-06-20 11:16:05 +02:00
Cometo
4f3d20a7c4 Add snap to grid feature 2016-06-20 09:50:24 +01:00
Julien Duponchelle
222ea18bcd Merge branch 'open_project' into 2.0 2016-06-17 15:58:10 +02:00
Julien Duponchelle
df7c91f17f Save as you go
Fix #1243
2016-06-17 15:55:23 +02:00
grossmj
99331fcc54 Try to repair the GNS3 VM support. Ref #1254. 2016-06-16 18:06:51 -06:00
Julien Duponchelle
b59d31855e 1.5.0dev6 2016-06-15 18:57:53 +02:00
Julien Duponchelle
a2211cfa46 1.5.0rc2 2016-06-15 18:54:54 +02:00
Jeremy Grossmann
e9ec42be02 Merge pull request #1307 from GNS3/noplay-patch-1
Add instruction for security issues
2016-06-15 10:45:44 -06:00
Julien Duponchelle
0801d9bf65 Ethernet0 => eth0 for docker
Fix #574
2016-06-15 15:22:37 +02:00
Julien Duponchelle
379b7a56ef Fix tests and a Virtualbox crash 2016-06-15 13:47:59 +02:00
Julien Duponchelle
8e9062c812 Merge branch '1.5' into 2.0 2016-06-15 13:38:31 +02:00
Julien Duponchelle
21e03e8318 Validate appliance schema before loading it
Fix #1311
2016-06-15 12:03:04 +02:00
Julien Duponchelle
fa1b53682c Fix GUI tests 2016-06-15 11:49:32 +02:00
Julien Duponchelle
ec68deb7e4 Drop the commit system
Ref #1243
2016-06-14 10:18:48 +02:00
Julien Duponchelle
1d51f3eed5 Merge branch '1.5' into 2.0 2016-06-14 10:17:42 +02:00
Julien Duponchelle
e8e189d5f3 Drop unused servers 2016-06-13 19:11:00 +02:00
Julien Duponchelle
443e338cc3 Ignore __pycache__ 2016-06-13 17:32:26 +02:00
Julien Duponchelle
9cab049696 Fix a rare crash when loading images
Fix #1299
2016-06-13 16:13:03 +02:00
Julien Duponchelle
e30e869025 Add instruction for security issues 2016-06-13 09:40:23 +02:00
grossmj
b106be2ed5 Removes client side unique node name allocation system. 2016-06-11 16:55:23 -06:00
grossmj
842519d7d0 Merge branch '1.5' into 2.0
Conflicts:
	gns3/main_window.py
	gns3/modules/docker/pages/docker_vm_preferences_page.py
	gns3/modules/dynamips/dialogs/ios_router_wizard.py
	gns3/modules/virtualbox/dialogs/virtualbox_vm_wizard.py
2016-06-10 21:48:57 -06:00
grossmj
d2ff73b579 Fixes doctor failure with 1.5rc1. Fixes #1290. 2016-06-10 21:39:02 -06:00
grossmj
c31d9dfbb2 Check for template name collisions. 2016-06-10 21:36:31 -06:00
grossmj
d7ed734ffb Log GNS3 doctor exceptions. 2016-06-10 21:17:50 -06:00
grossmj
b5a04bfe63 Implements customizable Ethernet hub & switches templates. 2016-06-10 21:02:05 -06:00
grossmj
077e6a110e Implements customizable cloud node templates. Ref #867. 2016-06-10 16:44:53 -06:00
Julien Duponchelle
66d87e8b12 Minor fixes related to IOU
* Fix crash when starting an individual node
* Fix crash when getting project path of the node
2016-06-10 15:34:26 +02:00
Julien Duponchelle
6bf5e7abcc Display HTTP error when no callback is register 2016-06-10 14:47:45 +02:00
Julien Duponchelle
39979a411d Avoid an error when we try to update a node before getting the node id 2016-06-10 14:35:49 +02:00
Julien Duponchelle
fdd5c71711 Fix a crash in IOU wizard 2016-06-10 14:34:26 +02:00
Julien Duponchelle
d6e20fe166 Send changes of label positions to the controller
Fix #1297
2016-06-10 11:24:05 +02:00
Julien Duponchelle
7988b13281 Do not destroy the NodeItem when changing symbol
This allow us to just replace the symbol in place and
notify the server.
2016-06-10 10:57:18 +02:00
Julien Duponchelle
8395865b75 Send X,Y,Z,Label and Symbol to server
We have an issue for the moment to detect change of symbol and
in label
2016-06-10 10:47:55 +02:00
grossmj
c3f33acdb3 Option to hide the new appliance template button. Fixes #1277. 2016-06-09 16:59:47 -06:00
Julien Duponchelle
6d9167c30f Removed the SvgNodeItem because it's was the only sub class of NodeItem 2016-06-09 18:08:22 +02:00
Julien Duponchelle
f8d698aea9 Fix docker VM wizard
Fix #1296
2016-06-08 16:00:36 +02:00
Julien Duponchelle
0cbde5046e Fix GNS3A support
Fix #1274
2016-06-08 15:10:32 +02:00
Julien Duponchelle
7a137a68ae Display human name of compute node in preferences
Fix #1291
2016-06-08 14:33:32 +02:00
Julien Duponchelle
09f7e6ce99 Avoid test side effect on user configuration files 2016-06-08 11:27:14 +02:00
Julien Duponchelle
305cc72485 Fix crash when browsing for local images directory 2016-06-08 11:18:57 +02:00
Julien Duponchelle
9b04901754 Upload missing images is now handled by the controller 2016-06-08 10:13:12 +02:00
Julien Duponchelle
d262f429c4 Fix text when stopping local server 2016-06-08 09:55:13 +02:00
Julien Duponchelle
6bb1223614 Repare IDLE PC in the IOS wizard 2016-06-07 12:04:28 +02:00
Julien Duponchelle
1d97b217cd Repare image upload 2016-06-07 11:39:15 +02:00
Julien Duponchelle
dfe48466e0 Fix list IOS images in the wizard 2016-06-06 16:09:16 +02:00
Julien Duponchelle
6fed45e7a8 Repare local copy for images 2016-06-06 15:56:01 +02:00
Julien Duponchelle
d97b75a3e1 Repare qemu-img create 2016-06-06 15:48:41 +02:00
Julien Duponchelle
87f2e08b3a Merge branch '1.5' into 2.0 2016-06-06 14:30:20 +02:00
Julien Duponchelle
f2c517a4a4 Start fixing qemu wizard 2016-06-02 20:11:36 +02:00
Julien Duponchelle
b8b810cdb1 Repare VMware and VirtualBox support
Fix https://github.com/GNS3/gns3-server/issues/537
2016-06-02 18:43:11 +02:00
Julien Duponchelle
c21900100e Repare Dynamips and IOU preference dialog (without image change) 2016-06-02 17:44:40 +02:00
Julien Duponchelle
50222f5083 Fix save of images search directories
The config file is not a JSON but a INI so we need to export
string.
2016-06-02 14:10:01 +02:00
grossmj
594b596cf9 Revert move "/version" endpoint to "/server/version".
Move "/server/shutdown" endpoint to "/shutdown".
2016-06-01 18:21:07 -06:00
grossmj
3494a4875c Some cleaning + move "/version" endpoint to "/server/version". 2016-06-01 17:50:31 -06:00
Jeremy Grossmann
a5d880e411 Merge pull request #1281 from GNS3/shutdown_server
Shutdown local server via controller
2016-06-01 15:37:52 -06:00
Jeremy Grossmann
e9f445380b Merge pull request #1275 from GNS3/images_directory
UI for settings image directories
2016-06-01 15:32:05 -06:00
grossmj
ea51f15253 Fixes graphical bug when remove interface from the cloud. 2016-06-01 12:48:02 -06:00
Julien Duponchelle
58501c205a 1.5.0dev5 2016-06-01 20:43:16 +02:00
Julien Duponchelle
47f23884b4 1.5.0rc1 2016-06-01 20:39:04 +02:00
grossmj
35ff7fd83e Filter special interfaces in cloud. Fixes #1279. 2016-06-01 11:57:45 -06:00
Julien Duponchelle
1375d7922c Shutdown local server via controller
Fix #1191
2016-06-01 17:22:53 +02:00
Julien Duponchelle
acc0a2ec67 Avoid a segfault when exiting with debug enabled 2016-06-01 16:18:30 +02:00
Julien Duponchelle
eecf1f4a54 Avoid a segfault when exiting with debug enabled 2016-06-01 16:17:53 +02:00
Julien Duponchelle
088d022d5e Fix the GNS3 VM is visible even if deactivated
Fix #1276
2016-06-01 10:58:07 +02:00
grossmj
22fcb14f9a Remove manual console port choice. Fixes #1167. 2016-05-31 21:53:51 -06:00
grossmj
6f2294f9b9 Automatically add ports for the cloud object when creating a new one. 2016-05-31 18:53:38 -06:00
grossmj
d7190b0602 Do not automatically stop the GNS3 VM by default. 2016-05-31 12:34:03 -06:00
grossmj
4cf769e7b6 Block VMnet host traffic by default. Solves the traffic loop issue on Windows. 2016-05-31 11:29:32 -06:00
Julien Duponchelle
3889c8c1fa Fix a crash 2016-05-31 08:34:55 +02:00
grossmj
d122e10703 Small improvements for the packet capture dialog. 2016-05-30 21:51:58 -06:00
grossmj
05f1fa0ecb Drop the host node. 2016-05-30 21:02:03 -06:00
grossmj
3974629e34 Improvements on the cloud interface. Ref #1116.
- Delete multiple interfaces or tunnels at the same time.
- Possibility to filter virtualization interfaces via contextual menu.
2016-05-30 18:56:06 -06:00
grossmj
dfd8147873 Simplify how to count for number of files in a path. 2016-05-30 15:52:26 -06:00
grossmj
bb503d9cc7 Additional checks when adding a binary image path. 2016-05-30 15:41:47 -06:00
Julien Duponchelle
913cb1a3cd UI for settings image directories
Ref https://github.com/GNS3/gns3-server/issues/546
2016-05-30 21:46:41 +02:00
grossmj
7125fb285e Merge remote-tracking branch 'origin/1.5' into 1.5 2016-05-30 11:51:06 -06:00
grossmj
0454868958 Remove tooltip for Qemu VM base mac address. 2016-05-30 11:50:48 -06:00
Julien Duponchelle
8523e3d1a4 Ensure project is not closed twice 2016-05-30 16:06:54 +02:00
Julien Duponchelle
e2415b68d3 Fix a crash when updating local server settings 2016-05-30 14:35:45 +02:00
Julien Duponchelle
0850a3428e Fix Topology Summary view missing link
Fix #1273
2016-05-30 14:33:37 +02:00
Julien Duponchelle
6f44a8b6ee Cleanup dead code around packet capture 2016-05-30 12:33:58 +02:00
Julien Duponchelle
0cc16c232b Fix crash when local server port is already used 2016-05-30 12:06:34 +02:00
Julien Duponchelle
57bd21d346 Merge branch '1.5' into 2.0 2016-05-30 11:41:32 +02:00
Julien Duponchelle
f18e7295bd Fix you cannot select the remote server of your choice in qemu wizard
Fix #1270
2016-05-30 11:12:46 +02:00
Julien Duponchelle
d6a6343aa8 Fix issue when deleting a running container
Fix #1269
2016-05-30 10:27:28 +02:00
grossmj
7397d2da50 Merge branch '1.5' into 2.0
Conflicts:
	gns3/main_window.py
	gns3/modules/builtin/ui/cloud_configuration_page_ui.py
	gns3/modules/vmware/ui/vmware_preferences_page_ui.py
	gns3/modules/vmware/ui/vmware_vm_configuration_page_ui.py
	gns3/node.py
	gns3/version.py
2016-05-29 20:14:08 -06:00
grossmj
f70c457e88 Started to streamline the could. Ref #1116. 2016-05-28 21:49:18 -06:00
grossmj
7750720f4d Allow to block network traffic originating from the host OS for vmnet interfaces (Windows only). 2016-05-28 13:39:21 -06:00
grossmj
950281caa6 Change Qemu VM base mac address tooltip. 2016-05-27 23:00:59 -06:00
grossmj
b5202b5591 Merge remote-tracking branch 'origin/1.5' into 1.5 2016-05-27 22:48:23 -06:00
grossmj
4aa01acce4 Change tooltip for Qemu VM base MAC address. 2016-05-27 22:48:12 -06:00
Julien Duponchelle
c58e788eba Improve image import 2016-05-27 17:49:44 +02:00
Julien Duponchelle
e7b60a1f27 Support dragging an image in the GNS3 topology from the system file
browser
2016-05-27 17:07:22 +02:00
Julien Duponchelle
1e4bbc4ecf Fix an issue with import with no GNS3 VM
Ref #544
2016-05-27 16:04:17 +02:00
Julien Duponchelle
e599da7033 Fix error when using {} in the node name
Fix #1265
2016-05-27 15:42:52 +02:00
Julien Duponchelle
341b5cd947 Display the progress dialog after 250ms
Fix #1262
2016-05-27 15:30:09 +02:00
Julien Duponchelle
fa35f3f9e4 Fix a crash when exporting a project with virtualbox or VMware VM 2016-05-27 10:26:23 +02:00
Julien Duponchelle
1375578b52 Support delete a project from GUI
Fix #822
2016-05-26 11:21:43 +02:00
Julien Duponchelle
1e2326913b Support add a remote compute server 2016-05-26 10:28:17 +02:00
Julien Duponchelle
82c41e09b5 Avoid a crash because VM is not supported in preferences 2016-05-26 10:14:40 +02:00
Julien Duponchelle
16f3b71af4 Support update of computes
Fix #795
2016-05-26 10:09:52 +02:00
grossmj
03373f3cda Add message on GraphicsScene when a project must be created. 2016-05-25 10:04:32 -06:00
Julien Duponchelle
2c9c01b991 Select the correct tab in general preferences 2016-05-25 14:25:33 +02:00
Julien Duponchelle
8a44b6fdb7 Support delete a remote server 2016-05-25 13:40:58 +02:00
Julien Duponchelle
3ceb886ca9 Support all computes informations 2016-05-25 10:34:42 +02:00
Julien Duponchelle
fb3df39263 Remove the auto launch project dialog settings because it's now
always open
2016-05-24 20:04:23 +02:00
Julien Duponchelle
829e8ed745 Drop support for temporary projects
Fix #982
2016-05-24 18:56:56 +02:00
Julien Duponchelle
ed5c52a807 Drop legacy call to /compute/version 2016-05-24 16:32:40 +02:00
Julien Duponchelle
8afc5afadf Less usages of the Servers 2016-05-24 16:31:07 +02:00
Julien Duponchelle
b26401203f VPCS now allow to select the server where the node will run 2016-05-24 15:48:24 +02:00
Julien Duponchelle
c127548dd1 one less Servers references 2016-05-24 15:27:33 +02:00
Julien Duponchelle
f8c1a48350 Tests are green again 2016-05-24 15:23:14 +02:00
Julien Duponchelle
55f634bec3 Remove debug 2016-05-24 11:20:40 +02:00
Julien Duponchelle
8c14e42a09 Merge branch '1.5' into 2.0 2016-05-24 10:16:37 +02:00
grossmj
2e30a96389 Set default VMware VM adapter type to e1000. 2016-05-23 14:14:42 -06:00
Julien Duponchelle
3fc4898904 First step of refactoring Servers 2016-05-23 19:47:52 +02:00
Julien Duponchelle
3561c55174 1.5.0dev4 2016-05-23 15:13:44 +02:00
Julien Duponchelle
5195c647f6 1.5.0 beta 1 2016-05-23 15:05:24 +02:00
Julien Duponchelle
f3a0d1daac Remote server selector not enabled in import appliance wizard
Fix #1258
2016-05-23 15:01:32 +02:00
Julien Duponchelle
dcad6e2d23 New server dialog is now windows modal 2016-05-23 14:57:12 +02:00
grossmj
6a402fe544 First step towards the cloud node re-factoring. 2016-05-22 19:24:14 -06:00
grossmj
310ae5905f More node re-factoring (setup -> create etc.) 2016-05-22 18:23:39 -06:00
grossmj
23aa820cdf Try to reduce node boilerplate code. 2016-05-22 15:57:26 -06:00
grossmj
74f702cea6 Layout change for the capture dialog. 2016-05-22 10:22:43 -06:00
grossmj
52335bddbc Fixes issue when UDPPortAllocatedSlot() is called multiple times. 2016-05-21 19:03:52 -06:00
grossmj
05acf724a8 Private-config is optional. 2016-05-21 18:10:31 -06:00
grossmj
71319a0a7c Fixes alternative IOS image selection when loading a project. 2016-05-21 12:39:36 -06:00
grossmj
c341c55258 Accept fill_color property for rectangle/ellipse objects. Compatibility for old 1.0 projects. 2016-05-21 12:20:01 -06:00
grossmj
cf40e641a6 Fixes check for NPF service and add check for NPCAP service on Windows. 2016-05-20 20:19:28 -06:00
grossmj
7cb6af85a8 Drop VPCS multi host support. Fixes #1252. 2016-05-20 18:18:26 -06:00
grossmj
358ef34918 Fixes base node. 2016-05-20 18:00:46 -06:00
grossmj
a66d194e12 Frame Relay and ATM switches migrated to the new API. 2016-05-20 17:59:59 -06:00
Julien Duponchelle
57b3ce4666 Start to drop Servers class 2016-05-20 13:17:32 +02:00
grossmj
aaa2b6f817 Ethernet hub and Ethernet switch almost fully migrated to the new API. 2016-05-19 22:45:04 -06:00
Julien Duponchelle
97b56e5620 Drop duplicate code already manage by the class VMWizard 2016-05-19 17:47:36 +02:00
Julien Duponchelle
79850176c3 Compute IDLE PC on controller 2016-05-19 16:22:29 +02:00
Julien Duponchelle
8e1896ef5b Support console_host 2016-05-19 14:05:06 +02:00
Julien Duponchelle
8cf911bb15 Merge branch '1.5' into 2.0 2016-05-19 13:34:21 +02:00
Julien Duponchelle
ad0af16fa3 :latest for docker image is managed server side 2016-05-19 13:33:57 +02:00
Julien Duponchelle
2aada61af3 Support update node from another GUI 2016-05-18 20:59:07 +02:00
Julien Duponchelle
66b9b4c68c Fix node not deleted on controller
Fix #1249
2016-05-18 20:45:14 +02:00
Julien Duponchelle
60d6151ce9 Drop unusued code from old cloud servers support 2016-05-18 20:34:24 +02:00
Julien Duponchelle
bfb4b0b9da Merge branch '1.5' into 2.0 2016-05-18 11:38:11 +02:00
Julien Duponchelle
0f00e206bf Remove unbreakable space 2016-05-18 11:27:38 +02:00
grossmj
71536ef9d3 Functional Ethernet hub with new API. 2016-05-17 21:32:57 -06:00
grossmj
354e73b4e7 Fixes project save/load. 2016-05-17 21:32:05 -06:00
Julien Duponchelle
30121e3617 aiohttp_cors 2016-05-17 18:06:19 +02:00
Julien Duponchelle
4d422e716b Support node.updated 2016-05-16 21:50:54 +02:00
Julien Duponchelle
8aa0f8d070 Fix error message for packet capture 2016-05-16 21:50:54 +02:00
grossmj
7c03c0cbcf Fixes #1246. 2016-05-16 10:56:35 -06:00
Julien Duponchelle
c13a4835b2 Test green :) 2016-05-16 17:27:47 +02:00
Julien Duponchelle
412d9b7645 Merge branch '1.5' into 2.0 2016-05-16 16:49:39 +02:00
Julien Duponchelle
27cdaf1ed5 Fix Checkbox and radio button are not readable with charcoal style
Fix #1245
2016-05-16 16:42:42 +02:00
Julien Duponchelle
32e8a45e4e Fix existing remotez server is not recognised
Fix #1240
2016-05-16 15:43:57 +02:00
Julien Duponchelle
34f35aff27 Fix Cannot change docker image adapter number from docker image configuration
Fix #1241
2016-05-16 14:54:48 +02:00
Julien Duponchelle
9b0101321a Fix test 2016-05-16 14:38:39 +02:00
Julien Duponchelle
a4c9487192 Fix got an unexpected keyword argument 'ram_limit'
Fix #1244
2016-05-16 14:37:28 +02:00
Julien Duponchelle
6449973ddc Fix delete node 2016-05-16 14:32:02 +02:00
grossmj
bd9a168667 Base for generic switch nodes. Started to move the Ethernet hub. 2016-05-15 21:02:50 -06:00
grossmj
5c0b03f133 Fixes suspended notification. 2016-05-14 12:24:55 -06:00
grossmj
5708f039c0 Fixes tests. 2016-05-14 12:18:16 -06:00
grossmj
ba0809159c Move most of the project management code its own class. Ref #1224. 2016-05-14 12:15:20 -06:00
grossmj
4aeb4238b2 Move style code to its own class. Ref #1224. 2016-05-14 10:36:30 -06:00
grossmj
119bc8207f Use start/stop/suspend/reload all endpoints. 2016-05-13 20:44:41 -06:00
grossmj
5e7dc27e1f Start, stop, suspend and reload endpoints for all nodes belonging to a project. Fixes #1212. 2016-05-13 19:26:51 -06:00
grossmj
6d3b4db760 Check that both Qt and PyQt version >= 5.6 to enable high DPI scaling. 2016-05-13 18:53:47 -06:00
grossmj
ccba9aa4d5 Update upload endpoints to match with the server. 2016-05-13 18:02:26 -06:00
Julien Duponchelle
47cbc91b02 Fix test 2016-05-13 15:34:06 +02:00
Julien Duponchelle
7a10fa157d Fix show in file manager
Fix #1238
2016-05-12 10:47:58 +02:00
Julien Duponchelle
a27ed4051c Test OK 2016-05-12 09:22:47 +02:00
Julien Duponchelle
dbbde4b098 Rollback some test schema to a previous version of GNS3 2016-05-12 09:00:25 +02:00
grossmj
2f71480849 Check Qt version, not PyQt. Fixes #1232. 2016-05-11 17:46:26 -06:00
grossmj
7e2284e094 Refactoring to use a common node class for all VMs and other (future) objects. 2016-05-11 16:54:55 -06:00
Julien Duponchelle
0ce5c198aa Merge branch '1.5' into 2.0 2016-05-11 10:34:32 +02:00
Julien Duponchelle
c8519188a1 Fix you can not turn off the GNS3VM with remote server
Fix #1235
2016-05-11 10:33:06 +02:00
Julien Duponchelle
bf9f782970 1.5.0dev3 2016-05-11 10:08:36 +02:00
grossmj
72f580efb8 Fixes incomplete merge 2016-05-10 13:31:28 -06:00
Julien Duponchelle
a443e3dcde 1.5.0a2 2016-05-10 19:16:30 +02:00
Julien Duponchelle
5496c6c8af Prepare 1.5.0a2 2016-05-10 19:10:28 +02:00
grossmj
b96d5e765e Minor changes on CHANGELOG 2016-05-10 10:09:47 -06:00
Julien Duponchelle
cee5fb915a Prepare 1.5 alpha 1 2016-05-10 17:58:59 +02:00
Julien Duponchelle
54888ff278 Fix style of table header
Fix #1231
2016-05-10 13:49:57 +02:00
Julien Duponchelle
ab3f3d72ab Removed server from server summary when needed
Fix #1225
2016-05-10 13:42:35 +02:00
Julien Duponchelle
b0eb0d74fb Merge branch '1.5' into 2.0 2016-05-10 10:51:27 +02:00
Julien Duponchelle
8451b4b14e Restore PyQt install from wheel on OSX 2016-05-09 10:40:10 +02:00
Julien Duponchelle
ca85d5e8c0 Merge branch 'master' into 1.5 2016-05-09 10:39:37 +02:00
Julien Duponchelle
9f7cf16335 Change internal timeout never used for clarity 2016-05-09 10:38:23 +02:00
grossmj
e09353b0fe Change some sentences for Docker Ui. 2016-05-08 11:25:16 -06:00
grossmj
56ace4dd31 Improve parse_version 2016-05-07 11:04:09 -06:00
grossmj
3cfd1a0957 Fixes improper use of QThreads for exporting/importing projects.
- Workers cannot have a  parent (moveToThread() will fail if the QObject has a parent and the worker ends up running in the main thread, only a warning message is printed on the console!).
- GUI calls cannot be made from within a thread. It worked before because the worker was running in the main GUI thread.
2016-05-07 10:46:07 -06:00
grossmj
3bd91dc9cb Ignore errors in shutil.rmtree 2016-05-07 10:38:20 -06:00
grossmj
aa805a611a Log aborted requests. 2016-05-06 20:51:39 -06:00
grossmj
b46109a086 Specify "portable project" for .gns3project import/export. 2016-05-06 15:18:12 -06:00
Julien Duponchelle
141b102129 Try to turn off Qt wheel for mac 2016-05-06 12:22:04 +02:00
Julien Duponchelle
2a03953f6c Merge branch 'master' into 1.5 2016-05-06 12:18:44 +02:00
Julien Duponchelle
0ff3bb1a34 Avoid a crash when you send a sigint during final garbage collect
Fix #1217
2016-05-06 12:18:00 +02:00
Julien Duponchelle
45d4c26972 Avoid duplicate in the server list
Fix #1218
2016-05-06 12:14:34 +02:00
grossmj
c05aeffbbb Fixes SetupWizard and NewApplianceDialog calls to PreferencesDialog 2016-05-05 23:35:40 -06:00
Jeremy Grossmann
b37b07bb06 Fixed parse version fail with Qt 5.6.0 string. 2016-05-06 01:11:38 -06:00
grossmj
83bb38b857 Set minimum sizes for spacers in preferences dialog. 2016-05-05 18:56:54 -06:00
grossmj
6ac398f11d Adjustments for the preferences dialog 2016-05-05 17:31:20 -06:00
grossmj
774c210097 Merge branch 'new_appliance_button' into 1.5 2016-05-05 17:01:35 -06:00
grossmj
173aa53cbe Merge branch '1.5' into new_appliance_button
Conflicts:
	gns3/ui/main_window_ui.py
2016-05-05 17:01:16 -06:00
grossmj
be128bc12a Update new appliance dialog for a cleaner interface. 2016-05-05 16:52:29 -06:00
grossmj
305975bb3b Remove pkg_resources.parse_version usage. 2016-05-05 10:11:30 -06:00
grossmj
e6726eb69d Some adjustments for preferences dialog. 2016-05-05 09:45:28 -06:00
Jeremy Grossmann
2988bae855 Merge pull request #1216 from GNS3/gns3vm_init
Always init the GNS3 VM
2016-05-04 16:29:35 -06:00
grossmj
d65e1087f9 .gns3appliance extension is the new default for GNS3 appliance files.
Support .gns3p as an project extension.
2016-05-04 16:22:58 -06:00
Julien Duponchelle
03744a7606 Support HTTP for docker appliances in GNS3A 2016-05-04 18:58:14 +02:00
Julien Duponchelle
65e2a1c8aa Fix crash on custom console 2016-05-04 17:01:54 +02:00
Julien Duponchelle
1e8ef4b208 Always init the GNS3 VM
I'm not sure at 100% but I think we need to
initialize the VM for all cases even we don't need the
autostart

Fix #1215
2016-05-04 10:41:04 +02:00
Julien Duponchelle
2a636481e8 Fix tests 2016-05-04 10:40:47 +02:00
Julien Duponchelle
9efc424462 HTTP support for docker 2016-05-03 16:40:19 +02:00
Julien Duponchelle
ad9db64e8b Mark as stopped a VM if project or VM no longer exists
It's avoid situation where you can not close the client
2016-05-03 11:30:02 +02:00
Julien Duponchelle
0cf04e34c7 Removed right click on docker images in preference list of images
Fix #1209
2016-05-02 16:48:54 +02:00
Julien Duponchelle
f932f96097 Fix name allocation for Docker
Fix #1208
2016-05-02 16:41:42 +02:00
Julien Duponchelle
4c5dac5e13 Merge branch 'master' into 1.5 2016-05-02 15:59:01 +02:00
Julien Duponchelle
abd838de00 Seem to fix crash on fedora 2016-05-02 15:22:47 +02:00
Julien Duponchelle
cd92f69804 Move charcoal CSS to an external file and fix tab color
Fix #1214
2016-05-02 12:19:05 +02:00
Julien Duponchelle
9d4cddb4a0 gns3z => gns3project 2016-05-02 10:25:52 +02:00
grossmj
4f105ced0e Revert "Try to better support HDPI in preferences dialog"
This reverts commit dfaae1df1a.
2016-04-29 18:56:16 -06:00
grossmj
983a69ed5d Revert "Try to scale symbols."
This reverts commit e17b6aa5c0.
2016-04-29 18:55:51 -06:00
grossmj
e17b6aa5c0 Try to scale symbols. 2016-04-29 16:00:42 -06:00
grossmj
c73c302d77 Create Pixmaps for QIcons. 2016-04-29 11:54:25 -06:00
grossmj
bdd40ec59d Drop more PyQt4 related code. Fixes #1203. 2016-04-29 09:05:41 -06:00
Julien Duponchelle
d78064daa6 Drop all PyQt4 code
Fix #1203
2016-04-29 16:40:32 +02:00
Julien Duponchelle
7683f7820f Fix error when checking npf
Fix #1205
2016-04-29 16:17:24 +02:00
Julien Duponchelle
c6b88d1fcd Catch all error in the doctor to avoid one test breaking it 2016-04-29 16:12:16 +02:00
Julien Duponchelle
dfaae1df1a Try to better support HDPI in preferences dialog
Ref #1033
2016-04-29 15:32:48 +02:00
grossmj
58efa8411b Bump version to 1.5.0dev2 2016-04-28 23:47:17 -06:00
grossmj
95f000252b Enabling High Dpi Scaling must be set before creating QApplication. 2016-04-28 23:46:51 -06:00
grossmj
2cf5880940 Enabling High Dpi Scaling is only available in Qt 5.6 and above. 2016-04-28 20:47:40 -06:00
grossmj
88c948f117 Set Fusion style & enable High Dpi Scaling. 2016-04-28 20:42:21 -06:00
Julien Duponchelle
89a369165e 1.4.7dev1 2016-04-28 18:33:52 +02:00
grossmj
9fc53329b5 Merge remote-tracking branch 'origin/1.5' into 1.5 2016-04-28 10:32:42 -06:00
grossmj
8765b7b3bd Tell Qt to generate high-dpi pixmaps. Ref #1033. 2016-04-28 10:32:28 -06:00
Julien Duponchelle
c4710b4bd2 1.4.6 2016-04-28 18:30:47 +02:00
Julien Duponchelle
43bd08a58f PyQt 5.6 is now available as a wheel 2016-04-28 15:20:28 +02:00
Julien Duponchelle
8a78cc2f5e PyWin32 in the requirements 2016-04-28 10:28:26 +02:00
Julien Duponchelle
186429890e Support console_type in GNS3A for docker 2016-04-27 18:00:59 +02:00
Julien Duponchelle
85d9988d79 Fix a typo in qemu preferences
Fix #1200
2016-04-27 15:44:23 +02:00
Julien Duponchelle
25ed2b794d Fix upload of large image to the VM
Fix #1202
2016-04-27 15:42:17 +02:00
Julien Duponchelle
1e3d216961 Capture packet on link instead of port 2016-04-27 11:05:11 +02:00
grossmj
b43a94b3c7 Reduce the number of connection tries from 120 to 40 when connecting the GNS3 server running inside the GNS3 VM. 2016-04-26 20:06:02 -06:00
grossmj
fc5cb3f0ad Update debug messages. 2016-04-26 19:57:34 -06:00
Julien Duponchelle
fc83a9e905 Mac and Win build 2016-04-26 20:46:52 +02:00
grossmj
6635f2f9c1 Include link to the GNS3 academy. Fixes #1178. 2016-04-26 11:42:48 -06:00
Julien Duponchelle
dc054d7e6b New appliance button
Fix #1177
2016-04-26 10:58:36 +02:00
Julien Duponchelle
555d464f8f Regenerate Qt ressources 2016-04-26 10:11:35 +02:00
Julien Duponchelle
c8a8336dc7 Install pyqt via Pypi only for mac & windows 2016-04-26 10:00:17 +02:00
Julien Duponchelle
228c39719d Merge branch 'master' into 1.5 2016-04-26 09:56:41 +02:00
Julien Duponchelle
5207fedd61 Fix NameError: name 'sys' is not defined in VirtualBox preferences
Fix #1197
2016-04-26 09:54:40 +02:00
grossmj
ae9c082cb7 Include environment variables when executing vmrun. Ref #1175. 2016-04-25 18:02:51 -06:00
grossmj
b302f16f65 Snapback feature for port labels. Fixes #1182. 2016-04-25 17:47:45 -06:00
grossmj
bf0bb0519a Prevent users to select VirtualBox.exe instead of VBoxManage.exe. Fixes #1195. 2016-04-25 17:03:46 -06:00
Jeremy Grossmann
c9db57fb7f Merge pull request #1196 from GNS3/improve_vmrun_error
Improve the vmrun error message
2016-04-25 14:10:59 -06:00
Julien Duponchelle
ca0ace0832 Improve the vmrun error message 2016-04-25 21:25:18 +02:00
Julien Duponchelle
32217db357 Merge branch 'master' into 1.5 2016-04-25 17:06:34 +02:00
Julien Duponchelle
a2ddfc5674 Add the server in the list of docker container 2016-04-25 14:05:01 +02:00
Julien Duponchelle
1ae7be4f6a Remove noisy logs 2016-04-21 14:41:41 +02:00
Julien Duponchelle
a418af0aad If we can not read the registry try to guess vmware type from vmrun path 2016-04-21 09:20:58 +02:00
Julien Duponchelle
50a92e9ea0 Merge branch '1.5' into 2.0 2016-04-20 18:02:07 +02:00
Julien Duponchelle
1e63fc14cb Merge branch 'master' into 1.5 2016-04-20 18:01:25 +02:00
Julien Duponchelle
6c00ef65af Ensure that you can not duplicate an interface in a cloud
Fix #1193
2016-04-20 18:00:45 +02:00
Julien Duponchelle
5c29d42d8c Update server summary with server status on controller
Fix #1186
2016-04-20 16:46:18 +02:00
Julien Duponchelle
19055ba004 Try PyQt5.5 has requirement 2016-04-20 14:50:15 +02:00
Julien Duponchelle
0825ae8cb5 Remove .NET from project dialog 2016-04-19 08:50:14 +02:00
Julien Duponchelle
c032c9f458 Update and delete VPCS via controller 2016-04-18 18:56:38 +02:00
Julien Duponchelle
fa5a9621e0 Reload VM on controller 2016-04-18 17:00:53 +02:00
Julien Duponchelle
b2db2cc719 Drop GNS3 converter
Fix #1147
2016-04-18 16:45:05 +02:00
Julien Duponchelle
0f76819936 Drop IOUVM converter
Ref #1147
2016-04-18 16:42:44 +02:00
Julien Duponchelle
66d1597312 Merge branch '1.5' into 2.0 2016-04-18 16:00:28 +02:00
Julien Duponchelle
74f4ae03f3 Disallow docker hot linking 2016-04-18 15:59:17 +02:00
Julien Duponchelle
5894cec3e4 Merge branch 'master' into 1.5 2016-04-18 15:53:07 +02:00
Julien Duponchelle
e66c411989 Dissallow removal of link of running emulator without support of hotlink
Ref https://github.com/GNS3/gns3-server/issues/491
2016-04-18 15:51:44 +02:00
Julien Duponchelle
f74920fd1b Merge branch '1.3' 2016-04-18 10:02:15 +02:00
Julien Duponchelle
c1c98cc7b6 Drop unused modules from 1.3 to avoid build issue on Jenkins 2016-04-18 10:01:22 +02:00
Julien Duponchelle
d217d9a291 Rename hypervisor to compute 2016-04-15 17:56:27 +02:00
Julien Duponchelle
29a73b183c Experimental wheel for PyQt 2016-04-14 14:04:45 +02:00
Julien Duponchelle
79c64f0e38 Start / Stop / Suspend on the controller 2016-04-14 12:23:02 +02:00
Julien Duponchelle
b8a3deeb02 Now each log message with level Error or Warning are display on the
console without the need of using print
2016-04-12 18:54:34 +02:00
Julien Duponchelle
108c774c0f Merge branch '1.5' into 2.0 2016-04-12 17:09:26 +02:00
Julien Duponchelle
830c7556b8 Fix tests 2016-04-12 17:09:06 +02:00
Julien Duponchelle
5470add29a Merge branch '1.5' into 2.0 2016-04-12 17:01:05 +02:00
Julien Duponchelle
f6c9ab0068 Merge branch 'master' into 1.5 2016-04-12 16:27:04 +02:00
Julien Duponchelle
e44b34062c Import / Export images
Fix #1173
2016-04-12 10:31:57 +02:00
Julien Duponchelle
320ae611a1 Check PyQT version support dev version
Signed-off-by: Julien Duponchelle <julien@duponchelle.info>
2016-04-11 15:26:27 +02:00
Julien Duponchelle
e54a87c436 Immedialety use the new GNS3 VM when changing server
Fix #1171
2016-04-08 16:07:35 +02:00
Julien Duponchelle
608cc363a2 Fix issue with aux console and VNC 2016-04-08 14:04:57 +02:00
Jeremy Grossmann
f9609c5871 Merge pull request #1172 from GNS3/readme
Ask for readme at export and menu for editing the readme
2016-04-07 14:43:01 -06:00
grossmj
cc422a6b1d Add edit.svg icon. 2016-04-07 14:41:23 -06:00
grossmj
638d75c388 Small adjustments and icons for each style. 2016-04-07 14:39:15 -06:00
Julien Duponchelle
b02495dd3d Prevent the export of a project not saved
Fix #1169
2016-04-07 18:16:40 +02:00
Julien Duponchelle
90ee8033b0 Add a readme
Fix #1166
2016-04-07 18:00:48 +02:00
Julien Duponchelle
3f5d8fe2a1 Merge branch 'master' into 1.5 2016-04-07 14:44:23 +02:00
Julien Duponchelle
32176d3e2f Show server CPU usage if it's 0
Fix #1168
2016-04-07 14:43:35 +02:00
Julien Duponchelle
c65f55b22a Fix crash when changing docker template name
Fix #1153
2016-04-07 14:40:43 +02:00
Julien Duponchelle
c9d221404b Save AUX port and VNC resolution
Fix #1154, 1165
2016-04-07 14:25:17 +02:00
Julien Duponchelle
ee73961832 Prevent export VMware and VirtualBox VM
Fix #1151
2016-04-07 11:53:36 +02:00
Jeremy Grossmann
ef39c174ed Merge pull request #1160 from GNS3/import_linux
Import improvements
2016-04-06 12:32:52 -06:00
Julien Duponchelle
962d8f77dd Allow to change the symbol on Docker Virtual Machine template
Fix #1161
2016-04-06 17:54:39 +02:00
Julien Duponchelle
bbc7abc50d Fix change number of Docker adapters 2016-04-06 16:10:05 +02:00
Julien Duponchelle
00f1258032 Warn if you try to change the number of adapters of a connected Docker 2016-04-06 16:06:21 +02:00
Julien Duponchelle
beb297967f Remove timeout for docker VM creation since this could be long
Fix #1162
2016-04-06 14:08:03 +02:00
Julien Duponchelle
00c913fd19 Import improvements
* Support import of GNS3Z on Linux https://github.com/GNS3/gns3-server/pull/481
* Warn if GN3VM is require Fix #1158
2016-04-06 12:06:37 +02:00
Julien Duponchelle
a38a8c4ba4 Server make a bigger part of the import
Fix #1156
2016-04-05 18:50:14 +02:00
Julien Duponchelle
56fafba8e9 Hide the text about network config for docker when editing template 2016-04-05 16:29:59 +02:00
grossmj
d0396b3da9 Clear warnings about using linked clones with VMware Player. 2016-04-04 12:10:48 -06:00
grossmj
180eaa2ce5 Add import/export icon files. 2016-04-03 12:16:22 -06:00
grossmj
d8de60afb9 Import/export icons for classic and charcoal styles. 2016-04-03 12:15:13 -06:00
Jeremy Grossmann
d5248e8472 Merge pull request #1150 from GNS3/import_export
Import export
2016-04-02 12:53:10 -06:00
Jeremy Grossmann
a7c199b195 Merge pull request #1152 from GNS3/add_server_dialog
Add server dialog box
2016-04-02 12:33:23 -06:00
grossmj
97a5351a52 Add a checkbox to enable or disable authentication when adding a new remote server. 2016-04-02 12:30:38 -06:00
grossmj
e0b4452007 Fixes local server warning message when settings are changed. 2016-04-02 12:04:03 -06:00
Julien Duponchelle
2e4a532b3c Add server dialog box 2016-04-01 16:21:07 +02:00
Julien Duponchelle
e54266d3a5 Import portable project
Fix #476
2016-04-01 11:17:20 +02:00
Julien Duponchelle
422ed0a5e2 Export portable projects
* Licence for zipstream

Ref #476
2016-04-01 11:16:33 +02:00
grossmj
59e17738cc Warnings about using VirtualBox to run the GNS3 VM. Ref #1044. 2016-03-30 14:00:14 -06:00
grossmj
50644cf3c4 Warning when adding a legacy ASA VM from Qemu Wizard.
Remove other hardcoded templates. Ref #1044.
2016-03-30 13:51:49 -06:00
Jeremy Grossmann
4a3ceb710d Merge pull request #1145 from GNS3/fix_topology_server
Ask user to replace a remote server not found when loading a project.
2016-03-29 15:49:29 -06:00
grossmj
5ab640c380 Minor changes for PR #1145. 2016-03-29 15:42:23 -06:00
grossmj
ba1afca4dd Allow right click on link capture symbol. Fixes #1137. 2016-03-29 13:48:23 -06:00
grossmj
4d4ffdb86c Resize link capture symbol. Ref #1137. 2016-03-29 13:08:40 -06:00
Jeremy Grossmann
0c6002a861 Merge pull request #1146 from GNS3/double_click_topology_view
Double click on an element in topology summary center the view on it
2016-03-29 11:28:47 -06:00
Julien Duponchelle
3ebdd8da14 Do not expand list of link when we double click on a node 2016-03-29 19:17:11 +02:00
Julien Duponchelle
31eb689635 Double click center on link 2016-03-29 19:11:51 +02:00
Julien Duponchelle
c3d66f243a Double click on an element in topology summary center the view on it
Fix #1060
2016-03-29 16:59:59 +02:00
Julien Duponchelle
5c108635d0 If the server doesn't exists in settings we ask to replace it
The user can refuse that and we will continue to create the server
from the topology. It's use the standard server list dialog to keep
code simple.

Fix #1144
2016-03-29 10:03:47 +02:00
Julien Duponchelle
365808eff2 Merge branch 'master' into 1.5 2016-03-29 09:20:18 +02:00
grossmj
5c654e99e4 Hardcoded port for the local GNS3 VM server. Ref #957. 2016-03-28 17:06:10 -06:00
grossmj
709c47d40d Removing old code. 2016-03-28 16:58:39 -06:00
grossmj
8ff8fb9c92 Add warning about using c1700 and c2600 IOS images. Ref #1044.
Modify warning about running Qemu on Windows/OSX.
2016-03-28 12:42:40 -06:00
grossmj
e3cdc5d3ff Merge remote-tracking branch 'origin/1.5' into 1.5 2016-03-28 11:01:35 -06:00
grossmj
69851d1596 Remove old load-balancing code. Fixes #1142. 2016-03-28 11:01:21 -06:00
Julien Duponchelle
c5330246b1 Restore old port in IOUVM converter 2016-03-28 16:58:48 +02:00
Julien Duponchelle
0f2b46b56a Fix a very very rare crash when closing a project
Fix #1141
2016-03-28 16:53:33 +02:00
grossmj
6580ea5891 Improvements for the preferences dialog (splitter layouts, save/restore geometry etc.) 2016-03-27 12:16:05 -06:00
grossmj
1cfd5ae4f0 Allow user/password for HTTP. 2016-03-26 11:43:13 -06:00
grossmj
339beeabaf Fixes bug when switching from a remote GNS3 VM to a VMware local GNS3 VM. 2016-03-25 19:35:31 -06:00
grossmj
3a4b9e2e31 Change layout for GNS3 VM settings in preferences. 2016-03-25 19:16:23 -06:00
grossmj
3055eeaa4f Allow to use a remote server as the GNS3 VM. Ref #957. 2016-03-25 19:02:45 -06:00
grossmj
e517fa6000 Remove load-balancing support. Fixes #1073. 2016-03-25 15:37:20 -06:00
grossmj
3946ebcb92 New console port range 5000 to 10000. 2016-03-25 10:32:04 -06:00
Julien Duponchelle
a34fa04e4f Refresh faster the progress dialog 2016-03-25 15:47:33 +01:00
Julien Duponchelle
2108f3209d Merge branch 'master' into 1.5 2016-03-25 15:45:49 +01:00
Julien Duponchelle
8d2ae5e254 Avoid a small blink of the waiting text 2016-03-25 15:45:22 +01:00
Julien Duponchelle
5092bc571d Change default port to 3080
Ref https://github.com/GNS3/gns3-server/issues/457
2016-03-25 15:37:38 +01:00
Julien Duponchelle
b013e8af50 Edit /etc/network/interfaces 2016-03-25 14:45:00 +01:00
Julien Duponchelle
3af8c4d28f Fix a crash with image item 2016-03-25 12:08:54 +01:00
grossmj
1f1860e53c Show a symbol in the middle of the link when packet capturing is activated. Ref #789. 2016-03-24 19:41:31 -06:00
grossmj
21015bccb5 GNS3 doctor: check if the NPF service is running. Fixes #1124. 2016-03-24 16:44:09 -06:00
grossmj
b27fabea12 Fixes progress dialog is None in accept() 2016-03-24 11:43:53 -06:00
Julien Duponchelle
932c708538 Merge branch 'master' into 1.5 2016-03-24 17:50:16 +01:00
Julien Duponchelle
adf241c146 Fix another race conditions in progress dialog
Fix #1135
2016-03-24 17:44:31 +01:00
Julien Duponchelle
b27a62c625 Fix Aux console lost after merge 2016-03-24 17:13:30 +01:00
Julien Duponchelle
132596a17e Replace the installation instructions by a link to the doc 2016-03-24 13:26:47 +01:00
Julien Duponchelle
f0359dcde9 Add busybox licence
Ref https://github.com/GNS3/gns3-server/pull/460
2016-03-24 13:19:47 +01:00
Julien Duponchelle
08a005b271 Remove libcloud and requests licence since they are not used 2016-03-24 13:15:09 +01:00
Julien Duponchelle
1b873acd72 2.0.0dev1 2016-03-24 10:40:07 +01:00
Julien Duponchelle
a76ac9b5e3 Merge branch '1.5' into 2.0 2016-03-24 10:39:48 +01:00
Julien Duponchelle
f7fa47026c 1.4.6dev1 2016-03-23 18:22:00 +01:00
Julien Duponchelle
36c3fe6a27 1.4.5 2016-03-23 18:17:37 +01:00
grossmj
7c67f08362 Change some sentences. 2016-03-23 10:42:37 -06:00
Jeremy Grossmann
5d71a828c4 Merge pull request #1133 from GNS3/sort_snapshots
Sort snapshots by date
2016-03-23 10:22:38 -06:00
Julien Duponchelle
3e9392b4b7 Sort snapshots by date
Fix #1036
2016-03-23 17:15:43 +01:00
Jeremy Grossmann
02d9d7c22c Merge pull request #1131 from GNS3/block_save_running
Block save and snapshot when a device is running
2016-03-23 10:04:00 -06:00
Jeremy Grossmann
8d60c65e5b Merge pull request #1129 from GNS3/avoid_blink
This should avoid blinking dialog. And display better progress
2016-03-23 10:01:42 -06:00
Jeremy Grossmann
0418cd0a95 Merge pull request #1130 from GNS3/upload_size
Display upload size during progress
2016-03-23 09:52:40 -06:00
Julien Duponchelle
a464295e5b Block save and snapshot when a device is running
Fix #1094
2016-03-23 16:51:02 +01:00
Jeremy Grossmann
95ec16fa92 Merge pull request #1132 from GNS3/enter_new_project
If you hit enter in the new project dialog it's work
2016-03-23 09:38:45 -06:00
Julien Duponchelle
2bd43cdc62 If you hit enter in the new project dialog it's work
Fix #1110
2016-03-23 16:11:34 +01:00
Julien Duponchelle
37e7222371 Display upload size during progress
Fix #1121
2016-03-23 15:27:44 +01:00
Julien Duponchelle
254c766883 This should avoid blinking dialog. And display better progress
Fix #925
2016-03-23 10:55:33 +01:00
Julien Duponchelle
e82a8ad63e Increase default timeout to avoid issue with Idle PC (240 seconds) 2016-03-23 10:54:18 +01:00
grossmj
39b4b233c9 SetupWizard: limit the number of vCPUs for the GNS3 VM to the number of physical cores. 2016-03-22 18:25:18 -06:00
grossmj
3e8208a117 Remove blocking code. Ref #1109. 2016-03-22 15:07:21 -06:00
grossmj
fbc7fd1de3 Bump version to 1.4.5dev2 2016-03-22 14:43:47 -06:00
grossmj
d533733d4b Fixes "QThread: Destroyed while thread is still running", 2016-03-22 14:42:38 -06:00
Jeremy Grossmann
082716e21a Merge pull request #1125 from GNS3/http_timeout
Add a timeout when you are not able to join the remote server
2016-03-22 13:44:51 -06:00
Julien Duponchelle
5ffdecab9e Add a timeout when you are not able to join the remote server
Fix #1119, #1123
2016-03-22 17:53:05 +01:00
Jeremy Grossmann
62c87b4f87 Merge pull request #1122 from GNS3/progress_dialog_improvement
Remove bad smell from progress dialog and handle ESC key
2016-03-22 10:52:59 -06:00
Julien Duponchelle
ab3a50f22f Remove bad smell from progress dialog and handle ESC key
Fix #1120
2016-03-22 17:18:00 +01:00
grossmj
71d3e8dd04 Remove root required messages in cloud node. Ref #608. 2016-03-19 22:32:12 -06:00
grossmj
aa8bbc32c5 Show a warning when the GUI is run with root rights. Fixes #608. 2016-03-19 22:23:08 -06:00
Jeremy Grossmann
05646c03cc Merge pull request #1114 from GNS3/close_running
Ask the user to stop device before closing
2016-03-19 11:27:05 -06:00
grossmj
1453b30e41 Change message when closing GNS3 with running device. 2016-03-19 11:26:15 -06:00
Julien Duponchelle
4f575fda73 Cleanup 2016-03-18 17:04:48 +01:00
Julien Duponchelle
14b6c70f47 Consume the global notification stream 2016-03-18 17:03:41 +01:00
grossmj
07144659b1 Merge remote-tracking branch 'origin/close_running' into close_running
Conflicts:
	gns3/main_window.py
2016-03-15 17:43:05 -06:00
Julien Duponchelle
69b7eb43f6 Fix closing 2016-03-15 21:13:49 +01:00
Julien Duponchelle
2a8b59b79a Ask the user to stop device before closing
This should avoid problem with ghost process remaining.
2016-03-15 21:06:00 +01:00
Julien Duponchelle
8f4e9ac48f Fix duplicate initial VM with network V2 2016-03-15 15:31:39 +01:00
Julien Duponchelle
30069e719b Success to add a dynamips with api V2 2016-03-15 10:45:32 +01:00
Jeremy Grossmann
71fa0dff4b Merge pull request #1115 from GNS3/check_other_gui
At startup display a warning if another GUI is already running
2016-03-14 16:53:38 -06:00
Julien Duponchelle
40f3a78795 Support delete link 2016-03-14 20:52:05 +01:00
Julien Duponchelle
0d11c71bb7 Create a link between two VPCS work 2016-03-14 17:05:16 +01:00
Julien Duponchelle
b58abf2a5c At startup display a warning if another GUI is already running
Fix #1088
2016-03-14 10:11:53 +01:00
Julien Duponchelle
f7911701b1 Ask the user to stop device before closing
This should avoid problem with ghost process remaining.
2016-03-14 10:11:36 +01:00
Julien Duponchelle
f9d4b58588 Fix test on start local servers 2016-03-14 10:11:15 +01:00
grossmj
1269aa273b Fixes #1105. 2016-03-13 12:03:58 -06:00
Julien Duponchelle
758480dd5f Remove /controller from the V2 call 2016-03-11 17:52:06 +01:00
Julien Duponchelle
2ca84501ba Create VPCS VM on controller 2016-03-11 15:06:39 +01:00
Julien Duponchelle
f9756e0977 Close project via controller 2016-03-10 10:57:34 +01:00
Julien Duponchelle
8894c26748 Check if server process correctly start
Fix #1109
2016-03-10 09:45:27 +01:00
Julien Duponchelle
9bb7e3a541 Merge branch 'master' into 1.5 2016-03-10 09:20:41 +01:00
Julien Duponchelle
235cba5ba5 Fix a crash if you delete a file while refreshing the list of appliances
Fix #1108
2016-03-10 09:17:49 +01:00
Julien Duponchelle
6c04b3936a Fix double opening of serial console
Fix #1107
2016-03-10 09:11:10 +01:00
Julien Duponchelle
31ba460553 Create project via controller 2016-03-10 09:07:30 +01:00
Julien Duponchelle
57f519db65 API V2 support 2016-03-08 12:07:11 +01:00
Julien Duponchelle
edf6c65e38 Register server on the controller when added 2016-03-04 08:32:54 +01:00
Julien Duponchelle
349cf1981a Split HTTPClient in two parts
The HTTP client class is responsible to make HTTP calls to
gns3 API server (controller or standard server).

Server is a GNS3 Server. In the transition period the server
will call the HttpClient of the GNS3 controller of the HttpClient
of the server depending of the endpoint.
2016-03-03 15:54:55 +01:00
Julien Duponchelle
a15635d953 Typo 2016-03-02 14:03:02 +01:00
Julien Duponchelle
04d9f3808b Tests for the docker support 2016-03-02 10:03:56 +01:00
Julien Duponchelle
494724c795 Start the local server with --controller
Ref https://github.com/GNS3/gns3-server/issues/417
2016-03-02 09:52:55 +01:00
Julien Duponchelle
71cadad05a Fix a crash when device as no console type
Fix #1096
2016-03-01 18:48:04 +01:00
Julien Duponchelle
30d204dddc Support aux for docker in save 2016-03-01 18:46:43 +01:00
Julien Duponchelle
cc19748fd2 Support aux console for Docker
Fix #1039
2016-03-01 15:17:40 +01:00
Julien Duponchelle
48f197b7ea VNC support for Docker
Fix #947
2016-02-29 23:07:47 +01:00
Julien Duponchelle
99b0ab5f50 Always ask the server for builtin
Fix #1084
2016-02-25 14:38:33 +01:00
Julien Duponchelle
db02b4443b Improve detection of vmrun on OSX
Ref https://github.com/GNS3/gns3-server/issues/435
2016-02-25 11:55:24 +01:00
Julien Duponchelle
8e35500269 Delete image from images dir when no longer need
Fix #1079
2016-02-25 11:21:58 +01:00
Julien Duponchelle
74628642ad Sort node name in topology summary
Fix #1059
2016-02-25 10:07:36 +01:00
Julien Duponchelle
f41edf284c Allow to show a message box for test without starting GNS3
https://gns3.com/discussions/regarding-the-gns3-vm-issues-wit
2016-02-24 09:00:53 +01:00
Julien Duponchelle
f740fde834 Fix crash when editing a Docker node
Fix #1080
2016-02-23 17:43:26 +01:00
Julien Duponchelle
db35c28607 Drop licence for paramiko since we no longer use it 2016-02-23 17:16:55 +01:00
Julien Duponchelle
b1aae4a85a Merge branch 'master' into 1.5 2016-02-23 15:43:29 +01:00
Julien Duponchelle
f4435c255c 1.4.5dev1 2016-02-23 15:41:04 +01:00
Julien Duponchelle
5aaec02af0 1.4.4 2016-02-23 14:36:35 +01:00
Julien Duponchelle
7f4b3edd84 Merge branch 'master' into 1.5 2016-02-23 09:56:52 +01:00
Julien Duponchelle
14cc7fcfeb Fix a conflict 2016-02-23 09:56:22 +01:00
Julien Duponchelle
95c0afd5dd Fix crash when selecting no image in GNS3A but clicking on Download 2016-02-22 21:05:46 +01:00
Julien Duponchelle
306ea31f0b Fix crash when you have a file size None (testing a new gns3a)
Fix #1074
2016-02-22 17:30:00 +01:00
Julien Duponchelle
18b7989e03 1.4.4dev4 2016-02-22 13:06:32 +01:00
Julien Duponchelle
559eef594e Restore the code split between vmware and vbox
Since it doesn't seem to be the problem I split again the code
2016-02-22 13:05:41 +01:00
Julien Duponchelle
7e6d2c6586 Prevent the progress dialog to cancel the GNS3VM when it's finish 2016-02-22 12:53:20 +01:00
Julien Duponchelle
9fd22a92ac Add a command show gns3vm to get the GNS3 VM statusM 2016-02-22 12:52:40 +01:00
Julien Duponchelle
e9470f4c94 Prevent setup wizard to appear if VM is running 2016-02-22 12:45:06 +01:00
Julien Duponchelle
cceb4bb324 Display error dialog if a custom console is invalid
Fix #1072
2016-02-22 11:26:35 +01:00
Julien Duponchelle
f14b4f4429 Crash when you import GNS3A just after installing gns3 Fix #1063 2016-02-22 11:23:11 +01:00
Julien Duponchelle
23db719c36 Change the way we check is setup wizard has been turned off Fix #1071 2016-02-22 11:20:55 +01:00
Julien Duponchelle
8b88a17836 1.4.4dev3 2016-02-22 10:43:28 +01:00
Julien Duponchelle
f1599d6e69 Do not failed if GNS3 VM server has an incorrect version
It's incorrect because we check it later in the HTTP code
and this can lead to half configured VM.
2016-02-21 20:57:05 +01:00
grossmj
df0c72ab0a Include the output from vmrun or VBoxManage when they return an error code. 2016-02-20 20:23:40 -07:00
grossmj
c68395549f Bump version to 1.4.4dev2 2016-02-20 18:41:38 -07:00
grossmj
d69addc3af Fixes bug that forced the GNS3 VM running in VirtualBox to restart even if no preferences had been changed. 2016-02-20 18:41:05 -07:00
grossmj
d96e67e850 Restore some of the changes made to WaitForVMWorker after 1.4.1 to debug an issue. 2016-02-20 18:39:15 -07:00
grossmj
321d9f376e Merge remote-tracking branch 'origin/master' 2016-02-20 11:29:14 -07:00
grossmj
e3450352c5 Restore WaitForVMWorker to the 1.4.1 state to debug an issue. 2016-02-20 11:28:45 -07:00
Jeremy Grossmann
4ba8be67fe Merge pull request #1062 from GNS3/ask_upgrade
Ask user to upgrade via the VM menu
2016-02-20 00:38:53 -07:00
grossmj
abff997179 Allows to cancel the progress dialog when GNS3 tries to contact the server running in the GNS3 VM. 2016-02-20 00:26:32 -07:00
grossmj
55216e1de7 1.4.4dev1 2016-02-19 16:02:51 -07:00
Julien Duponchelle
194f3352a1 1.4.3 2016-02-19 22:16:16 +01:00
Julien Duponchelle
9e0ae5dc96 Merge branch 'master' into 1.5 2016-02-19 19:59:44 +01:00
Julien Duponchelle
ba88fd5306 Allow to configure the type of device for docker container
Fix #1052
2016-02-19 16:41:15 +01:00
Julien Duponchelle
179529214b Ask user to upgrade via the VM menu
Fix #1053
2016-02-19 15:59:45 +01:00
Julien Duponchelle
b27a7a1c31 Allow idlepc 0x0 in topology
Also improve the json schema error reporting
2016-02-19 15:53:21 +01:00
grossmj
1a5b5327dc Show an explicit error message when status code 0 is returned. Fixes #1034. 2016-02-18 16:52:57 -07:00
grossmj
d30ac79a77 Fixes minor bug when dropping a VirtualBox VM on the scene. Fixes #748. 2016-02-18 16:30:13 -07:00
Julien Duponchelle
a1461d9ea6 Correctly check local server if only local is available in vm wizard 2016-02-18 19:09:24 +01:00
Julien Duponchelle
783248d58b Try make the GNS3 VM server running value more reliable
Ref #1049
2016-02-18 16:30:00 +01:00
Julien Duponchelle
d13d77e39a Make VM configuration dialog modal
Fix #1048
2016-02-18 10:26:27 +01:00
grossmj
bf333e1964 Cannot take GIF screenshots (write is not supported by Qt). 2016-02-17 16:02:32 -07:00
Julien Duponchelle
1833e8683b 1.4.3dev1 2016-02-17 19:36:57 +01:00
Julien Duponchelle
e4a336cd67 1.4.2 2016-02-17 19:31:28 +01:00
Jeremy Grossmann
1810956185 Merge pull request #1047 from GNS3/gif
Allow GIF images (not animated) since patent expired in 2004.
2016-02-17 11:25:12 -07:00
Julien Duponchelle
af7f0f49d1 Allow gif image (not animated) since pattent expire in 2004 2016-02-17 18:54:27 +01:00
Jeremy Grossmann
d6ebf8ea04 Merge pull request #1046 from GNS3/countdown
Countdown before starting the GNS3 VM
2016-02-17 10:25:58 -07:00
Julien Duponchelle
13721c9811 Countdown before starting the GNS3 VM
Fix #912
2016-02-17 18:24:34 +01:00
Julien Duponchelle
eafde17259 Merge branch 'master' into 1.5 2016-02-17 10:34:28 +01:00
Julien Duponchelle
02810e84a9 Prevent IOU GNS3A install on Windows 2016-02-17 10:33:57 +01:00
Julien Duponchelle
ac3214fedc Fix refresh of device list when importing docker container
Ref #945
2016-02-17 10:19:31 +01:00
Julien Duponchelle
c376689ad4 Add GNS3A support for docker
Beware it's rename the settings for saving the list of the
containers in the GUI.

Fix #945
2016-02-17 10:01:24 +01:00
grossmj
a12a686a68 Customizable name for VirtualBox VM templates. Fixes #748. 2016-02-16 22:22:13 -07:00
grossmj
16ec69bb8c Set timeout from 1 to 3 seconds when waiting for GNS3 VM server. Ref #1034. 2016-02-16 18:19:25 -07:00
grossmj
82cb95aff7 Redirect stderr to stdout when executing VBoxManage or vmrun. Ref #1027. 2016-02-16 17:24:41 -07:00
Jeremy Grossmann
1eb3693f0a Merge pull request #1031 from GNS3/cancel_vm_start
Allow to cancel the start of the GNS3 VM.
2016-02-16 16:58:18 -07:00
Julien Duponchelle
50925536d1 Merge branch 'master' into 1.5 2016-02-16 19:05:38 +01:00
Julien Duponchelle
bfd9c654aa Apply the correct name to the appliance imported 2016-02-16 19:04:18 +01:00
Julien Duponchelle
1104ce3176 Correctly save the environnement for docker container 2016-02-16 18:31:23 +01:00
Julien Duponchelle
19ef5b7e1d Merge branch 'master' into 1.5 2016-02-16 18:12:51 +01:00
Julien Duponchelle
b1477f5fb5 Update VMware banners
Fix #1032
2016-02-16 18:10:32 +01:00
Julien Duponchelle
8613a89264 Keep the correct vm_id between reload of topology with container
Fix #1043
2016-02-16 17:00:55 +01:00
Julien Duponchelle
6a90bac196 Fix container save
Fix #1038
2016-02-16 15:29:00 +01:00
Julien Duponchelle
cda6398010 Fix crash when loading a SVG image in topology
Fix #1035
2016-02-16 11:52:40 +01:00
Julien Duponchelle
e502f1dcc4 Merge branch 'master' into 1.5 2016-02-16 11:46:48 +01:00
Julien Duponchelle
13b699a183 Prevent a crash in progress dialog
Fix #1037
2016-02-16 11:46:12 +01:00
Julien Duponchelle
0cd1f314f6 Update for 4K monitor
Ref #1033
2016-02-16 09:56:33 +01:00
grossmj
0c894ee48a Do not use the appliance version for create its VM template name. 2016-02-12 21:17:02 -07:00
Julien Duponchelle
f6f1d4a97c Allow to change the docker console port
Fix #1026
2016-02-12 16:37:31 +01:00
Julien Duponchelle
c85820e685 Allow to cancel the start of the GNS3 VM
Fix #912
2016-02-12 16:05:38 +01:00
Jeremy Grossmann
445f721ceb Merge pull request #1024 from GNS3/svg_only_node_item
All node are now SVG items
2016-02-11 18:42:32 -08:00
Jeremy Grossmann
5fa24247c6 Merge pull request #1011 from GNS3/allow_to_import_unknow
Allow to import unknow files via GNS3A
2016-02-11 17:20:38 -08:00
Julien Duponchelle
7ee76fdd2b Merge branch 'master' into 1.5 2016-02-11 15:47:07 +01:00
Julien Duponchelle
2acfe7f1bf Recompute file size during import and add a column with the MD5 size 2016-02-11 12:11:38 +01:00
Julien Duponchelle
b33f660f90 Fix setup.py is not installing gns3-net-converter
Fix #1025
2016-02-11 10:11:08 +01:00
grossmj
91509888af Launch custom console command only if a node is initialized and started. 2016-02-10 15:11:40 -07:00
Jeremy Grossmann
fa3657f736 Merge pull request #1022 from GNS3/custom_console_without_save
Allow to open a custom console on any node
2016-02-10 13:22:51 -08:00
Julien Duponchelle
09638633c1 gns3-net-converter 2016-02-10 19:30:15 +01:00
Julien Duponchelle
11a6f1124f gns3-net-converter 2016-02-10 19:23:33 +01:00
Jeremy Grossmann
98ba58f39b Merge pull request #1013 from GNS3/detect_corrupt_port_name
Detect corrupt port name
2016-02-10 10:06:27 -08:00
Julien Duponchelle
b6fa4f3242 Merge branch 'master' into 1.5 2016-02-10 18:47:56 +01:00
Julien Duponchelle
baa7436e43 Detect and fix duplicate port name in topology
Try to track #992.
2016-02-10 17:45:07 +01:00
Julien Duponchelle
4a9b649e9f Allow to open a custom console on any node
Without saving the console anywhere

Fix #675
2016-02-10 17:39:44 +01:00
Julien Duponchelle
42143f77c5 All node are now SVG items
This create a generic renderer outputing always an SVG item.

Fix #1017
2016-02-10 15:47:27 +01:00
Julien Duponchelle
e2bdd216bb Move Qt code to a module so we can add new code in differents files 2016-02-10 13:53:03 +01:00
Julien Duponchelle
856fde79ec Fix rare crash when updating node
Fix #1018
2016-02-10 11:33:23 +01:00
Julien Duponchelle
91987b2e06 Prevent duplicate server in server summary
Fix #1020
2016-02-10 11:29:18 +01:00
Julien Duponchelle
36c6eeabc9 Fix crash if you create a new version and click on next without file 2016-02-10 11:25:22 +01:00
Julien Duponchelle
549e364da3 Use _updateCallback instead of _setupCallback
Fix #992, #1015
2016-02-10 11:13:55 +01:00
grossmj
1cc2d6c6b7 User configurable default name format for Docker. Fixes #748. 2016-02-09 19:33:13 -07:00
grossmj
d0321ce0fa Change text description in create a new version dialog. 2016-02-09 18:28:34 -07:00
Jeremy Grossmann
0d4cca3aa7 Merge pull request #1010 from GNS3/doctor_double_gns3
Check if GNS3 is not installed twice in doctor
2016-02-09 17:08:08 -08:00
Jeremy Grossmann
d77177a98f Merge pull request #1008 from GNS3/custom_console
Allow to set a custom console per node & refactor common code for save and load topology
2016-02-09 16:55:52 -08:00
Jeremy Grossmann
13bcac7e22 Merge pull request #1000 from GNS3/edit_console_dialog
Create a dialog for choosing the console command.
2016-02-09 16:49:22 -08:00
Julien Duponchelle
0046d8ba90 Merge branch 'master' into 1.5 2016-02-09 18:15:25 +01:00
Julien Duponchelle
4475a93fc5 Fix a regression in Host and Cloud
Fix #1014
2016-02-09 18:13:30 +01:00
Julien Duponchelle
041b609f99 Check if GNS3 is not installed twice in doctor
Fix #1007
2016-02-09 16:10:00 +01:00
Julien Duponchelle
bb6653cecb Docker capture and refactor common capture code
Fix https://github.com/GNS3/gns3-gui/issues/891
2016-02-09 16:06:25 +01:00
Julien Duponchelle
d84ce07038 Allow to add custom command to the list
https://www.youtube.com/watch?v=sEXbQmHJ1uM&feature=em-upload_owner
2016-02-09 11:18:16 +01:00
Julien Duponchelle
c9fec9ad51 Update Readme Python 3.4 is require 2016-02-09 10:04:01 +01:00
Julien Duponchelle
e953ea7212 Allow to import unknow files via GNS3A
Fix #980
2016-02-08 20:27:09 +01:00
Julien Duponchelle
d1d7cd8186 Fix a problem with gns3 running in background after exit
Fix #971
2016-02-08 17:41:46 +01:00
Julien Duponchelle
d3e4f17dab Move common code for ports dump to vm.py 2016-02-08 16:24:14 +01:00
Julien Duponchelle
344fde0d6f Move common code _updatePortSettings to vm.py 2016-02-08 16:16:38 +01:00
Julien Duponchelle
e27c8955c5 Fix a crash when searching for alternative images 2016-02-08 15:24:04 +01:00
Julien Duponchelle
27fa234888 Fix tests
Fix #1009
2016-02-08 14:20:27 +01:00
Julien Duponchelle
59ae047359 Fix a crash with corrupted topology from 1.0
Fix #1005
2016-02-08 14:01:55 +01:00
Julien Duponchelle
a847a2ff91 Merge branch 'master' into 1.5 2016-02-08 13:36:15 +01:00
Julien Duponchelle
8445637dd1 Remove all the docker code from 1.4 gui to avoid confusion 2016-02-08 13:33:27 +01:00
Julien Duponchelle
7f339ede4e Merge commit '19f1b969eae02b062d262994a83cc03af47b5586' into 1.5 2016-02-08 13:23:30 +01:00
grossmj
e54faa3079 User configurable default name format for Docker. Fixes #748. 2016-02-05 12:15:30 -07:00
Julien Duponchelle
4d2a4f3433 Allow to set a custom console per node
This require some refactoring:
* all VM inherit of the same dump and load common code
* move some code for opening a console from graphic views to the VM

Fix #675
2016-02-05 19:00:53 +01:00
Julien Duponchelle
ddd6de24ce Create a dialog for choosing the console command.
This extract all the code for selecting a console command
to a Dialog. With the following improvements:
* detect if a command exists and select it in the combo box
* help about custom variables that can be used in the command

Demonstration here:
https://www.youtube.com/watch?v=fw9XhRtFJuY&feature=em-upload_owner

It's part 1 of the #675 for supporting console application by node.
2016-02-05 16:10:59 +01:00
Julien Duponchelle
19f1b969ea Catch error if dynamips is disabled for local and no remote available
Fix #999
2016-02-05 14:54:46 +01:00
Julien Duponchelle
48beb69103 Merge pull request #993 from GNS3/download_vm_link
Put a link for the GNS3 VM in the setup wizard
2016-02-05 10:18:09 +01:00
Julien Duponchelle
a0be08d62a Put a link for the GNS3 VM in the setup wizard
It's smart the link change with the version and emulator

Fix #978
2016-02-05 10:17:48 +01:00
Julien Duponchelle
a750c7df2a Merge pull request #994 from GNS3/gray_vm
When importing appliance explain why options is gray
2016-02-05 10:11:36 +01:00
Julien Duponchelle
950986c69e When importing appliance explain why options is gray
Fix #979
2016-02-05 10:11:15 +01:00
grossmj
cc7bddefa1 User configurable default name format for VMware and VirtualBox. Ref #748 2016-02-04 23:47:34 -07:00
grossmj
1c4b735880 Changes "base name prefix" to "default name format". Ref #748. 2016-02-04 21:20:42 -07:00
grossmj
0862c135d0 User configurable base name support for Dynamips, IOU and VPCS. Ref #748. 2016-02-04 19:57:53 -07:00
grossmj
01e3cf1b1c Refactor "Import config" router dialog. Fixes #752. 2016-02-04 18:17:20 -07:00
grossmj
519bd389f6 Fixes ValueError: cannot mmap an empty file. Fixes #723. 2016-02-04 17:45:09 -07:00
grossmj
ee6aac2614 Merge remote-tracking branch 'origin/master' 2016-02-04 17:31:17 -07:00
grossmj
fa319b6529 Saves the "show port names" state in topology files. Fixes #778. 2016-02-04 17:31:01 -07:00
Julien Duponchelle
905be4130e Fix KeyError: 'midplane' when loading 7200 in some cases
Perhaps something when importing old config.

Fix #996
2016-02-04 18:40:17 +01:00
Julien Duponchelle
814e973f9a Hide the server select box for builtin switch if dynamips local is off
Fix #872
2016-02-04 17:49:46 +01:00
Julien Duponchelle
d84596860c Right click support for docker 2016-02-04 17:15:54 +01:00
Julien Duponchelle
5d9414e728 Merge branch 'master' into 1.5 2016-02-04 17:13:03 +01:00
Julien Duponchelle
016e279d43 IOU right click on devices 2016-02-04 17:12:14 +01:00
Julien Duponchelle
d432047ac1 Right click edit for VirtualBox 2016-02-04 16:53:14 +01:00
Julien Duponchelle
9938e60e05 Support right click on VMware vms templates 2016-02-04 16:27:36 +01:00
Julien Duponchelle
6e751bbfaf Support right click on dynamips templates 2016-02-04 16:24:17 +01:00
Julien Duponchelle
8bdc07185b Fix an issue where the Existing image button can disapear from wizard
If you select a server with no image and after a server with image.
The existing image button will not be visible.
2016-02-04 11:31:20 +01:00
Julien Duponchelle
8872aceb0b Fix a race condition when you ask for image list but close the windows
Fix #990
2016-02-04 11:13:43 +01:00
Julien Duponchelle
f7b14c7da7 Fix QWidget::setWindowModified: The window title does not contain a
'[*]' placeholder

Fix #991
2016-02-04 11:10:06 +01:00
Julien Duponchelle
86cd732453 Fix alignements of VMware and VirtualBox in VM choice type 2016-02-04 11:07:08 +01:00
Julien Duponchelle
ae6571b18b Better explanation of server type for Docker 2016-02-04 11:05:03 +01:00
Julien Duponchelle
0faf773f71 Merge branch 'master' into 1.5 2016-02-04 11:03:41 +01:00
Julien Duponchelle
3178fb1a46 Better explanation during server choice
Fix #977
2016-02-04 11:03:03 +01:00
Julien Duponchelle
a917e80774 Disabled remote button when we have no remote in server wizard 2016-02-04 11:03:02 +01:00
grossmj
9bde5fcad6 Improved lookup for VMware host type. Fixes #970. 2016-02-03 19:13:10 -07:00
Jeremy Grossmann
e33f423733 Merge pull request #986 from GNS3/righ_edit
Allow to edit a node via a right click in the node
2016-02-03 11:30:26 -08:00
grossmj
cc35408607 Change some text in nodes view. 2016-02-03 12:28:09 -07:00
Jeremy Grossmann
10d91b50ec Merge pull request #976 from GNS3/command_line
Allow to show the command line used to start a VM
2016-02-03 11:10:10 -08:00
Julien Duponchelle
7dd06b5659 Allow to edit a node via a right click in the node
At this time only Qemu is OK. If the change are OK
I can patch VMware, VirtualBox, Dynamips and IOU.

Fix #670
2016-02-03 18:09:20 +01:00
Julien Duponchelle
86087bf505 Show error if a problem occur when getting remote server KVM status
Fix #983
2016-02-03 16:27:21 +01:00
Julien Duponchelle
cb4923815a Display a clean error when an appliance has an invalid JSON
Fix #984
2016-02-03 16:11:42 +01:00
Julien Duponchelle
43258d64d2 MobaXterm integration
Fix #985
2016-02-03 16:08:26 +01:00
Julien Duponchelle
6d3109be67 Allow to show the command line used to start a VM 2016-02-02 18:24:51 +01:00
Julien Duponchelle
a25e0cc23f Add - GNS3 at the end of the windows name
Ref #578
2016-02-02 10:37:59 +01:00
Julien Duponchelle
026a78b1b6 Fix a crash with doctor on windows
Fix #974
2016-02-02 09:44:24 +01:00
Julien Duponchelle
380a4a0395 Fix crash in doctor if ubridge path is empty
Fix #975
2016-02-02 09:42:04 +01:00
Julien Duponchelle
f6c2a6387f 1.4.2dev1 2016-02-01 17:54:58 +01:00
Julien Duponchelle
27f65a92e9 1.4.1 2016-02-01 17:51:30 +01:00
Julien Duponchelle
858f33f782 Fix reload a docker topology with two adapter lead to corrupted topology
Fix #973
2016-02-01 17:30:08 +01:00
Julien Duponchelle
fa072bf387 By default use latest image for Docker 2016-02-01 16:50:28 +01:00
Julien Duponchelle
154ea7354d Merge branch 'master' into 1.5 2016-02-01 15:46:46 +01:00
grossmj
53dbac1d5c Improvement to detect VMware Player on Linux. Ref #970. 2016-01-31 11:32:40 -07:00
Julien Duponchelle
a780866cd8 You can move Dock widgets everywhere 2016-01-28 14:49:15 +01:00
Julien Duponchelle
bf6f1af217 Link to download VIX api 2016-01-28 14:12:40 +01:00
Julien Duponchelle
29c85f3c65 Fix SSH present in the server preferences
Fix also a scaling issue

Fix #968
2016-01-27 16:57:42 +01:00
Julien Duponchelle
ba51d3ebf5 Apply diff from @elhers 2016-01-27 15:46:03 +01:00
Julien Duponchelle
e4f3ea1da9 Pach for linux 2016-01-27 15:25:45 +01:00
Julien Duponchelle
f037452188 Fix doctor for linux 2016-01-27 14:35:47 +01:00
Julien Duponchelle
3d35601d47 Check dynamips and ubridge permission.
Not tested on linux for the moment

Ref #944
2016-01-27 11:49:43 +01:00
Julien Duponchelle
146e642097 Check if processor is 64 bit in Doctor 2016-01-27 11:03:51 +01:00
Julien Duponchelle
e2c53443e3 Merge pull request #929 from GNS3/doctor
Show a dialog for checking some common issues
2016-01-27 10:57:45 +01:00
grossmj
965a98d5a7 Adjustments for PR #929. 2016-01-27 10:52:32 +01:00
Julien Duponchelle
41a68e7b0e Warn if vmrun not accessible 2016-01-27 10:51:36 +01:00
Julien Duponchelle
20e62b824c Show a dialog for checking some common issues
Warn user about issues with AVG

Fix #928, #744
2016-01-27 10:51:36 +01:00
Julien Duponchelle
36e9fcbddf Add Servers Summary in "View / Docks"
Fix #965
2016-01-27 10:44:02 +01:00
Julien Duponchelle
bd3d33d67b Add an unknwon status icon when the server has never been connected
Fix #966
2016-01-27 10:40:03 +01:00
grossmj
caf77a24f1 Some cleaning in MainWindow. 2016-01-26 13:24:40 -07:00
Jeremy Grossmann
729f9e103d Merge pull request #964 from GNS3/server_usage
Show a summary with server usages
2016-01-26 10:36:48 -08:00
grossmj
7261debb79 Revert "Remove unused code."
This reverts commit b4d0deddfc.
2016-01-26 11:30:36 -07:00
grossmj
b4d0deddfc Remove unused code. 2016-01-26 10:58:15 -07:00
Julien Duponchelle
d62a32c7d7 Show a summary with server usages
Fix #963
2016-01-26 18:52:53 +01:00
Julien Duponchelle
cb94fc4d1e Fix a typo 2016-01-26 17:03:51 +01:00
Julien Duponchelle
554888b21d Close project on VM when closing the project on all servers 2016-01-26 17:02:13 +01:00
Julien Duponchelle
4ae01282d7 Avoid a crash during test 2016-01-26 17:01:08 +01:00
Julien Duponchelle
020e62ddf5 Allow to not rotate the text when changing all text colors
Fix #805
2016-01-26 14:10:32 +01:00
Julien Duponchelle
c1dce98595 Fix topology summary view 2016-01-26 11:34:28 +01:00
Julien Duponchelle
676187061c Raise an error when psutil is too old
Also in crash report we include the version of psutil

Fix #960
2016-01-26 11:03:25 +01:00
Julien Duponchelle
14f4f26791 Fix a race condition when closing the server
Fix #959
2016-01-26 10:47:55 +01:00
Julien Duponchelle
57cf10c251 Fix a very very rare crash in topology summary view
Fix #961
2016-01-26 10:44:07 +01:00
Julien Duponchelle
70b4fae62c Code cleanup from @elhers 2016-01-26 10:40:16 +01:00
Julien Duponchelle
5c3b9e7fae Merge pull request #955 from GNS3/fix_label_invert
Fix inversion of port label when loading a topology
2016-01-26 10:37:29 +01:00
Julien Duponchelle
9ea39a78db Code cleanup for label inversion
Following @grossmj and and @ehlers advices
2016-01-26 10:31:56 +01:00
grossmj
8f77697482 Reset port label positions. Fixes #811. 2016-01-25 20:41:38 -07:00
grossmj
1b5e53ddc6 Tentative to fix #951. 2016-01-25 14:42:00 -07:00
Jeremy Grossmann
86ee9595f4 Merge pull request #943 from GNS3/fix_terminal_command
Reset the telnet command on Mac
2016-01-25 12:02:15 -08:00
Jeremy Grossmann
dd7937dba4 Merge pull request #956 from GNS3/drop_ssh
Drop SSH support
2016-01-25 11:37:49 -08:00
Julien Duponchelle
a4c646152e Drop SSH support
Since we introduce the SSH support we got bug and bug
due to the complexity introduce by the tunnels. Even
in the 1.4.0 after long testing nobody notice that
the feature was broke.

And in his actual implementation we have limitation
preventing you to connect a node running on your PC
to a node running on the remote server.

After thinking about that it's better to drop it before
this feature is used by a lot of people. It's better to
use a VPN and less ninja.

Also we know that embeding paramiko require us to distribute
an encryption library creating legal trouble with US embargo
on various country.

Bonus point for the future: SSH support is probalby hard, or impossible for
a web interface and complicate the move to an architecture
with GNS3 server running as controller managing all the servers.

Fix #930
2016-01-25 19:21:36 +01:00
Julien Duponchelle
3d7db9a9c7 Fix inversion of port label when loading a topology
This PR rewrite the way multi link are created and avoid
to invert their directions.

Fix #954
2016-01-25 18:30:15 +01:00
Julien Duponchelle
06ed266278 Fix select an existing container image 2016-01-22 10:02:35 +01:00
Julien Duponchelle
5df16db823 Fix docker wizard bug when you have no container image on the host
Fix #946
2016-01-21 18:04:46 +01:00
Julien Duponchelle
4f23706b19 Merge branch 'master' into 1.5 2016-01-20 17:09:32 +01:00
Julien Duponchelle
e9ceadfc34 Fix error when importing Windows XP OVA
Fix #932
2016-01-20 17:06:46 +01:00
Julien Duponchelle
267cdc365d Warn if configuration file contain invalid unicode characters
Fix #933
2016-01-20 13:43:29 +01:00
Julien Duponchelle
6dfbaccee1 Fix a crash when importing some OVA
Fix #936
2016-01-20 13:41:03 +01:00
Julien Duponchelle
f97f48d428 Fix travis build 2016-01-20 13:09:02 +01:00
Julien Duponchelle
70b3bc680e Reset the telnet command on Mac
Following the issue #942

It's the easiest way to do it. But we can not interact
with the user at this step because the Qt is not yet started.
This mean during the upgrade the command is reset to the standard.

Even if some users could be disapointed it's positive for most user.
Because for most user the current settings is broke. And if someone
has change something he know how to configure it again (for example
switching to iTerm). If we don't do that I think the bug will remain
for years.
2016-01-20 11:50:33 +01:00
Jeremy Grossmann
c125579a38 Merge pull request #942 from GNS3/console_osx
Fix only one console work for OSX
2016-01-19 18:25:42 -08:00
Julien Duponchelle
9bc2a7e7bc Fix only one console work for OSX
In previous releases we got race conditions issues with
the OSX console due to the usage of Apple Script.

Problem. How to fix this situation for all users. Should
we reset terminal preferences for all OSX users coming from version
older than 1.4.1 ?

Fix #941
2016-01-19 20:17:32 +01:00
Julien Duponchelle
a5358dec14 Fix a rare crash when loading topology with missing image 2016-01-19 16:29:51 +01:00
Julien Duponchelle
c84f554f36 Fix a rare race condition when inserting an image
Fix #934
2016-01-19 16:23:33 +01:00
Julien Duponchelle
0dd9803f74 Fix a crash when pid file is empty
Fix #935
2016-01-19 16:12:36 +01:00
Julien Duponchelle
2baaa26a42 Fix a rare crash in progress dialogs
Fix #938
2016-01-19 16:10:45 +01:00
Julien Duponchelle
3fd62f906e Fix a crash if you don't have vms when importing a gns3a 2016-01-19 14:30:11 +01:00
Julien Duponchelle
41e8b44dde Warn user during appliance install if server is not avaible 2016-01-18 17:23:18 +01:00
Julien Duponchelle
09cbd9b606 Fix merge error after adding KVM requirements checks 2016-01-18 16:43:39 +01:00
Julien Duponchelle
3ab8d79ff7 Improve text when KVM is ok 2016-01-18 14:18:56 +01:00
Julien Duponchelle
97eaed6d2c Fix error when you stop the GNS3 VM but break the config before
Fix #924
2016-01-18 11:30:45 +01:00
Jeremy Grossmann
805aa23948 Merge pull request #920 from GNS3/fix_asa_wizard
Fix select of image broken if you need to select multiple images
2016-01-17 09:42:05 -08:00
Jeremy Grossmann
a25c45a502 Merge pull request #916 from GNS3/kvm_check
Add a step in the wizard checking KVM support
2016-01-17 09:41:04 -08:00
Julien Duponchelle
6ebda209ac startup_config is not mandatory inside .gns3 file 2016-01-15 20:57:13 +01:00
Julien Duponchelle
d226b31fab Fix wrong host on SSH connection
Fix #919
2016-01-15 19:33:10 +01:00
Julien Duponchelle
27a3009ce1 Fix select of image broken if you need to select multiple images
In the case of ASA you need to select multiple image
on multiple screen. The problem is we refresh the list
of the VM on each step.

This patch refresh only the VM list when the widget is visible.

Fix #886
2016-01-14 18:42:23 +01:00
Julien Duponchelle
654ad61105 Fix a crash when changing qemu cluster size to more than 512
Fix #915
2016-01-13 17:30:02 +01:00
Julien Duponchelle
31a461195f Fix a crash when closing SSH connections
Fix #917
2016-01-13 17:16:13 +01:00
Julien Duponchelle
331eef3164 Fix IOU support in gns3a
Fix #918
2016-01-13 17:05:47 +01:00
Julien Duponchelle
cb0d576ade 1.4.1dev1 2016-01-13 09:22:00 +01:00
Julien Duponchelle
32978381b2 Add urxvt support
https://gns3.com/qa/trying-to-get-gns3-to-work-with-
2016-01-13 09:21:07 +01:00
Julien Duponchelle
a7f7a688d3 1.4.0 release 2016-01-12 17:38:45 +01:00
Julien Duponchelle
5d87726397 Add a step in the wizard checking KVM support
It's mostly code from PR #904 but less error prone due to the usage
of a step in the wizard. Also it's check the capacities for all servers.
2016-01-11 17:53:36 +01:00
Julien Duponchelle
b9601cb54a Merge branch '1.4' into 1.5 2016-01-07 18:09:43 +01:00
Julien Duponchelle
bb66555896 Merge branch 'master' into 1.4 2016-01-07 18:09:28 +01:00
Julien Duponchelle
37726630ce Fix rare crash when showing the progress dialog
Fix #909
2016-01-07 09:16:42 +01:00
Julien Duponchelle
3d12f85f66 Merge branch '1.4' into 1.5 2016-01-06 14:34:57 +01:00
Julien Duponchelle
e26762fce3 1.4.0dev14 2016-01-06 14:34:08 +01:00
Julien Duponchelle
32e59fcce4 Fix crash on Windows when a gui is already running
Fix #908
2016-01-06 14:24:49 +01:00
grossmj
9b43330e95 Add default idle-pc value for c7200-adventerprisek9-mz.155-2.XB. Fixes #389. 2016-01-05 13:00:39 -07:00
Julien Duponchelle
b3b94243b4 1.4.0rc3 2016-01-05 18:30:48 +01:00
Julien Duponchelle
fba1032388 Fix config tests 2016-01-05 18:27:16 +01:00
Julien Duponchelle
ccc0803c5b Add information about antivirus and firewall in case of connection fail 2016-01-05 17:08:19 +01:00
Julien Duponchelle
f0340bcc98 Change link to doc for missing router image 2016-01-05 16:43:17 +01:00
Julien Duponchelle
8d19b8fcbf On windows and OSX experimental Qemu GNS3A support 2016-01-04 21:53:10 +01:00
Vasil Rangelov
dbf66d5a9a Allow appliances to be installed on a local Windows or OSX server, while also allowing them to instead require KVM be supported on the target server, or to disable it even if supported. Also resolve Qemu binary at appliance install time. 2016-01-04 21:53:10 +01:00
Julien Duponchelle
0fa8d61b19 Wait server in thread 2016-01-04 21:50:42 +01:00
Julien Duponchelle
02d326419b Fix local server non avaible in appliance wizard when local server
started by hand.

Ref #904
2016-01-04 14:12:08 +01:00
Julien Duponchelle
79b8baac9f Fix docker tests 2016-01-04 10:36:51 +01:00
Julien Duponchelle
8a6df8abc7 Fix build 2016-01-04 09:30:53 +01:00
grossmj
8b8d763fb7 Dependencies are listed in one location now. 2016-01-03 14:09:01 -07:00
Julien Duponchelle
608e80a80b Improve pid checks
Fix #900
2016-01-03 20:45:58 +01:00
Julien Duponchelle
d90f11eb86 Add a comment about tests run in a container 2016-01-03 19:54:57 +01:00
Jeremy Grossmann
dc39187091 Merge pull request #894 from boenrobot/port1names
Port names with numbers starting from 1
2015-12-27 20:08:21 -08:00
Jeremy Grossmann
e4cd418533 Merge pull request #898 from boenrobot/diskInterfaceOnAppliance
Disk interfaces on Qemu appliances
2015-12-25 11:09:06 -08:00
Vasil Rangelov
8559469c73 Allow Qemu appliances to optionally specify desired disk interfaces in their configuration (defaults to "ide"). 2015-12-25 04:00:48 +02:00
Jeremy Grossmann
ac8d2beb80 Merge pull request #892 from GNS3/docker_cleanup
Docker support cleanup and improvements
2015-12-24 14:54:31 -08:00
Julien Duponchelle
5e6384074e Merge branch '1.4' into 1.5 2015-12-22 18:10:03 +01:00
Julien Duponchelle
e6ba7bdd98 Fix project non closing when you have only remote servers
Fix #895
2015-12-22 16:21:41 +01:00
Julien Duponchelle
784055689f Fix Windows layout not saved in some scenario
Fix #884
2015-12-22 16:11:50 +01:00
Julien Duponchelle
c937811f45 Force gns3 converter >= 1.2.4 2015-12-22 10:45:16 +01:00
Vasil Rangelov
79c8021faa Added the ability to name Qemu/VirtualBox/VMware interfaces with numbers starting from 1, along with named aliases for numbers starting from 0, and a tooltip explaining the possible name format variables. 2015-12-22 00:41:12 +02:00
Julien Duponchelle
a428730f59 Merge pull request #893 from boenrobot/schemaFix1
Added missing Qemu adapters to the topology schema.
2015-12-21 21:12:44 +01:00
Julien Duponchelle
2522bd44d6 New crash report key 2015-12-21 20:48:51 +01:00
Vasil Rangelov
3cad8ea046 Added missing Qemu adapters to the topology schema. 2015-12-21 20:50:27 +02:00
Julien Duponchelle
76131f1cc7 Enable docker 2015-12-18 18:19:06 +01:00
Julien Duponchelle
54fb5dc765 Docker support cleanup and improvements 2015-12-18 18:13:44 +01:00
Julien Duponchelle
4110af56e7 1.5.0dev1 2015-12-18 18:06:46 +01:00
Julien Duponchelle
ab1775e44b Fix Cannot save my topology getting an error message for temporary
topology

Fix #885
2015-12-18 10:10:26 +01:00
Julien Duponchelle
9c3facb07a Fix creation of ASA devices
Fix #890
2015-12-18 10:08:41 +01:00
Julien Duponchelle
e5ae7b2d25 Turn off Docker until 1.5 2015-12-18 09:49:50 +01:00
Julien Duponchelle
60462ff986 Fix display of server preferences on small screen
Fix #882
2015-12-14 16:37:55 +01:00
Julien Duponchelle
39443cd676 Fix If you turn off the local server and close the gui and reopen
preferences you have an issue

Fix #881
2015-12-14 16:28:50 +01:00
Julien Duponchelle
25ab8249ae Zoc 7 support
Fix #879
2015-12-14 16:19:38 +01:00
Julien Duponchelle
6e86c606cc Fix test on windows
Fix #877
2015-12-14 15:07:45 +01:00
Julien Duponchelle
8878b96e74 Merge branch 'master' into unstable 2015-12-11 14:32:32 +01:00
Julien Duponchelle
c3ef2edbab 1.4.0dev13 2015-12-11 14:27:20 +01:00
Julien Duponchelle
f7e398edc3 1.3.14dev1 2015-12-11 14:26:13 +01:00
Julien Duponchelle
8d4fc9585e 1.3.13 2015-12-11 09:22:46 +01:00
Julien Duponchelle
5fe65e26ce 1.3.12 2015-12-11 08:53:14 +01:00
Julien Duponchelle
daaebe7f96 Fix warning when closing GUI
Fix #875
2015-12-11 08:51:12 +01:00
grossmj
f9f6a52e8b Update links for new website. 2015-12-10 15:00:16 -07:00
grossmj
601c0217b9 Update VMware links. 2015-12-10 14:05:39 -07:00
Julien Duponchelle
b0971b4ba3 1.4.0rc2 2015-12-10 19:36:41 +01:00
Julien Duponchelle
5a4549c36c Merge pull request #874 from GNS3/iou_dynamips_gns3a
IOU and dynamips support for gns3a
2015-12-10 19:32:11 +01:00
Julien Duponchelle
fe2cc362f8 Dynamips GNS3A support 2015-12-10 18:17:51 +01:00
Julien Duponchelle
dd0220fd59 Prevent user turning off the Local server when using the GNS3 VM
Fix #873
2015-12-10 13:57:09 +01:00
Julien Duponchelle
26fdd9ef6f Force VM wizard to be modal
Fix #868
2015-12-10 10:31:03 +01:00
Julien Duponchelle
733ee259e5 Fix unicode error when exporting debug informations
Fix #869
2015-12-10 10:25:19 +01:00
Julien Duponchelle
762fecbcff Fix Debug can't be deactivated for current session
Fix #871
2015-12-10 10:19:13 +01:00
Julien Duponchelle
5e85dfe5fd Ignore missing file when reading config
Fix #870
2015-12-10 10:08:29 +01:00
Jeremy Grossmann
e01632d60a Merge pull request #864 from GNS3/drop_webkit
Drop Webkit from 1.3.X
2015-12-09 19:34:15 -08:00
Julien Duponchelle
60916e8b80 IOU gns3a support 2015-12-09 19:49:23 +01:00
Julien Duponchelle
4fe55634ae Support relative path for configuration file.
It's allow futur GNS3A support for IOU and Dynamips
2015-12-09 18:06:07 +01:00
Julien Duponchelle
b1b861c99d Don't kill the server if two gui are running
Fix #865
2015-12-09 15:26:37 +01:00
Julien Duponchelle
07c0474386 Ask user to send bug reports to GNS3.com 2015-12-09 12:17:32 +01:00
Julien Duponchelle
755fb5c8f3 Report bug to GNS3.com 2015-12-09 12:16:49 +01:00
Julien Duponchelle
fdb382874d Avoid crash when cancel connection to a server
Ref #865
2015-12-09 12:04:18 +01:00
Julien Duponchelle
471b3e1009 Fix travis dependencies installation 2015-12-09 09:11:19 +01:00
Julien Duponchelle
f64a226336 1.4.0dev12 2015-12-08 16:27:54 +01:00
Julien Duponchelle
dec257bb6b Fix version number display twice when installing appliance 2015-12-08 16:05:48 +01:00
Julien Duponchelle
e736fbbb87 Drop Webkit from 1.3.X 2015-12-08 11:44:21 +01:00
Julien Duponchelle
aeb42b3ffe Show a warning when you try to save as a remote topology
Ref #831
2015-12-08 11:34:37 +01:00
Julien Duponchelle
1694a57ed9 Fix application restart after self upgrade
Fix #863
2015-12-07 15:39:13 +01:00
Julien Duponchelle
26001463a0 Cleanup server autostart
Fix #862
2015-12-07 11:30:17 +01:00
grossmj
36c1197f1f Merge remote-tracking branch 'origin/unstable' into unstable 2015-12-05 17:26:52 -07:00
grossmj
1fa16936fe Have default console port start from 2000. 2015-12-05 17:26:33 -07:00
Jeremy Grossmann
fca65784ee Merge pull request #852 from GNS3/vnc
Allow to use the VNC port range for console
2015-12-05 16:03:44 -08:00
Julien Duponchelle
8983e6c5a9 Fix crash when opening a new topologies after gns3 converter failure
Fix #858
2015-12-04 15:18:38 +01:00
Julien Duponchelle
c6e06f3941 Fix crash when opening a new topologies after gns3 converter failure
Fix #858
2015-12-04 15:13:03 +01:00
Julien Duponchelle
b7e32a60ce Fix SSH support
Fix #857
2015-12-04 14:16:14 +01:00
Julien Duponchelle
da100e494b Fix bus error when writting on console
Fix #371
2015-12-04 11:37:42 +01:00
Julien Duponchelle
9d7b5bccb8 Fix Ok & Cancel button in preferences are broken
Fix #855
2015-12-03 16:57:15 +01:00
Julien Duponchelle
112b05c3dd Fix After a project load failure you can't open new project
Fix #851
2015-12-03 16:53:41 +01:00
Julien Duponchelle
987e85cce8 More fix around closing the GUI
Fix #854
2015-12-03 16:37:33 +01:00
Julien Duponchelle
8142d0baa7 Fix crash in progress dialog on OSX
Fix #828
2015-12-03 15:45:55 +01:00
Julien Duponchelle
cc32b2661c Kill already running zombie server
Fix #838
2015-12-03 11:14:16 +01:00
Julien Duponchelle
781857f598 Store the pid of the server when started
Refe #838
2015-12-03 10:33:03 +01:00
Jeremy Grossmann
69179dcb63 Merge pull request #849 from GNS3/resize_preferences
Preferences dialog resize
2015-12-02 11:11:32 -08:00
Julien Duponchelle
8017838d60 Fix a crash in rare case after a PyQT garbage collect
Fix #842
2015-12-02 16:13:59 +01:00
Julien Duponchelle
81946493ec Allow to use the VNC port range for console
This PR allow user to have VNC port in the
console port range. It's not a problem because server
can share the range (we have a common list for all tcp ports).

And we add an informations in the settings in order to allow user
to know that 5900 => 6000 will be used.

Fix #846, #839
2015-12-02 16:08:34 +01:00
Julien Duponchelle
a7f40c3d50 Preferences dialog resize
* add a scrollbar if preferences height is too big
* set a dynamics max size depending of the screen

Fix #844
2015-12-02 12:22:28 +01:00
Julien Duponchelle
c28723287f Fix a race condition when opening telnet from apple script
Prevent closing ssh tunnel on OSX when using apple script
this leak port...

Fix #841, #848
2015-12-02 11:21:16 +01:00
Julien Duponchelle
c7a8588647 Experimental support for tabbed terminal on OSX
Fix #841
2015-12-02 11:05:24 +01:00
Julien Duponchelle
4a64261c5d Fix validation error when saving topology with an usage
Fix #829
2015-12-01 18:50:17 +01:00
Julien Duponchelle
5f4365542c Fix another case of not closing windows
Fix #833
2015-12-01 18:47:42 +01:00
Julien Duponchelle
2e2c951ffc Fix GUI doesn't close after connection error to remote server
Fix #833
2015-12-01 16:12:41 +01:00
Julien Duponchelle
2ba7dde326 Add usage text to device template and on hover
Fix #829
2015-12-01 11:04:05 +01:00
Julien Duponchelle
a1579ca86b Fix a rare crash in progress dialog
Fix #835
2015-12-01 09:49:18 +01:00
Julien Duponchelle
81c4ddb85f Fix crash when displaying an error from the update
Fix #836
2015-11-30 21:35:36 +01:00
Julien Duponchelle
285a8d413a Url encode royal tx url 2015-11-30 17:09:43 +01:00
Julien Duponchelle
672c86b38d Use Royal TX URI scheme thanks to @lemonmojo
Fix #832
2015-11-30 16:49:02 +01:00
Julien Duponchelle
905611d2a8 OSX support for Royal TSX
Can't test because I don't have a Royal TSX licence

Ref #832
2015-11-30 15:13:45 +01:00
Julien Duponchelle
339fb22217 Merge branch 'master' into unstable 2015-11-30 14:46:10 +01:00
Julien Duponchelle
a8f5fa5dd5 Set Wireshark 2.0 as default OSX version
Fix #830
2015-11-30 14:37:39 +01:00
Julien Duponchelle
bd365dd6eb iTerm 2.9 support
Fix #817
2015-11-30 14:27:54 +01:00
Jeremy Grossmann
8e4a6169e0 Merge pull request #809 from GNS3/contributing
Contributing guidelines
2015-11-14 20:20:13 -08:00
Jeremy Grossmann
b1790844f3 Update CONTRIBUTING.md 2015-11-14 19:59:15 -07:00
grossmj
4b0050d26c Update debug information dialog. 2015-11-14 18:33:03 -07:00
grossmj
19bf40dc89 Change text for export debug information. 2015-11-14 18:31:46 -07:00
Julien Duponchelle
23cda61d17 1.4.0rc1 2015-11-12 17:48:51 +01:00
Julien Duponchelle
c74ffde65a Rename an appliance if the default name is already taken 2015-11-12 17:34:50 +01:00
Julien Duponchelle
0a9c10e748 Existing image option should be hidden when none is available
Fix #819
2015-11-12 17:02:05 +01:00
Julien Duponchelle
6973eaaa02 Warn users about the need to uncompress the image
Fix #826
2015-11-12 16:18:49 +01:00
Julien Duponchelle
9ce483398b Fix crash when you have no qemu vms and use gns3a
Fix #824
2015-11-12 15:40:23 +01:00
Julien Duponchelle
55744ab129 Change sentry key
Fix #825
2015-11-12 11:20:17 +01:00
Julien Duponchelle
0e1cb47aa1 Merge branch 'master' into unstable 2015-11-12 10:52:31 +01:00
Julien Duponchelle
3bf12753df Fix format_exception() missing 2 required positional arguments: 'value'
and 'tb' in topologyFile

Fix #823
2015-11-12 10:43:04 +01:00
Julien Duponchelle
8907659220 Fix dialog box not returning their result
Fix #818
2015-11-12 09:34:45 +01:00
Julien Duponchelle
a4ccb0b620 Log to console the Qt Message Boxes 2015-11-11 11:58:31 +01:00
Julien Duponchelle
7d845c0ef8 Add informations about GNS3 VM 2015-11-10 12:45:22 +01:00
Julien Duponchelle
8282ec1da6 Contributing file 2015-11-10 12:43:11 +01:00
Julien Duponchelle
edfe2c7f47 Fix upload images from a non default images path
Fix #797
2015-11-09 17:24:46 +01:00
Julien Duponchelle
ca69673439 Fix error when set cluster size using qemu-img
Fix #798
2015-11-09 15:35:04 +01:00
Julien Duponchelle
8677707a9a Improve export debug informations
* Force adding .zip at the end
* Prevent crash for temporary directory

Fix #408
2015-11-09 14:30:43 +01:00
Julien Duponchelle
f3abbe5d58 Fixes unused import and variables 2015-11-09 12:52:57 +01:00
Julien Duponchelle
c0f36590be Auto pep8 2015-11-09 12:39:14 +01:00
grossmj
bdb097a173 Sets console end port to 7000. 2015-11-08 18:15:14 -07:00
grossmj
510491e26d Merge remote-tracking branch 'origin/unstable' into unstable 2015-11-08 17:23:56 -07:00
grossmj
6f0015a678 Fixes #342. Qemu master image is modified instead of the linked image. 2015-11-08 17:23:43 -07:00
Jeremy Grossmann
690e1d5ea0 Merge pull request #777 from GNS3/export_debug_informations
Allow to export a zip with debug informations
2015-11-07 21:17:48 -08:00
Julien Duponchelle
19734e0bd3 Fix invalid log screen when dumping a topology 2015-11-06 16:29:23 +01:00
Julien Duponchelle
5172c0b19e Warn the user to save the project before exporting debug infos 2015-11-06 10:38:54 +01:00
Julien Duponchelle
d74898c8a3 Allow to export a zip with debug informations
The zip contains:
* informations about the system, network and processus
* configuration
* log
* current .gns3 and screenshoot

Hope it will help to solve issues with can't connect to
http://127.0.0.1:8000

Fix #408
2015-11-05 15:43:11 +01:00
Julien Duponchelle
eb10f10988 Add more safety to HTTP callback to Qt
Fix #757
2015-11-05 11:36:05 +01:00
Julien Duponchelle
eb2e504acc Fix crash on Windows exit
Fix #749
2015-11-05 11:21:54 +01:00
Julien Duponchelle
6c502e1213 Correclty enable faulthandler for dev version 2015-11-05 10:51:08 +01:00
Julien Duponchelle
462c00b358 Fix support of remote servers for VPCS
Fix #756
2015-11-04 15:07:22 +01:00
Julien Duponchelle
b83eb61a42 Drop shellConsole docker will support telnet 2015-11-04 11:53:00 +01:00
Julien Duponchelle
96c35c49ff Drop some references to QtWebkit 2015-11-04 10:20:02 +01:00
Julien Duponchelle
36b48f24dc Prevent call to a destroyed callback in http client connection
Fix #754
2015-11-03 09:55:25 +01:00
Julien Duponchelle
efb21665f0 Avoid crash due to deleted thread
Ref #749
2015-11-03 09:41:14 +01:00
Julien Duponchelle
9ab77cfe20 1.4.0dev11 2015-11-02 21:28:34 +01:00
Julien Duponchelle
6031a349be 1.4.0b5 2015-11-02 18:51:44 +01:00
Julien Duponchelle
7163daf480 Fix crash when loading invalid appliance file
Fix #743
2015-11-02 18:01:46 +01:00
Julien Duponchelle
f662c39df0 Show a message is starting or is stopping in progress dialog
This change the text of the progress dialog when node start
or stop.
2015-11-02 15:34:34 +01:00
Julien Duponchelle
d7caba76c4 Drop duplicate code 2015-11-02 15:34:34 +01:00
grossmj
36ff527cc0 Changes some references for "GNS3 VM" to "Local GNS3 VM". Ref #506. 2015-11-01 18:19:59 -07:00
grossmj
d96ab77a67 Fixes progress dialog remains #741. 2015-10-31 15:34:23 -06:00
Julien Duponchelle
b4ade1982e Add more check to prevent progress dialog crash 2015-10-30 14:34:27 +01:00
Julien Duponchelle
4c9ef92c2d Support more boot order for Qemu
Fix #738
2015-10-30 10:28:10 +01:00
Jeremy Grossmann
078fc0f5ed Merge pull request #740 from GNS3/qpartial
Add a Qt compatible version of partial
2015-10-29 12:03:22 -07:00
Julien Duponchelle
40cc73c4f1 Add Royal TS 2015-10-29 18:18:48 +01:00
Julien Duponchelle
07c1443a8d Fix tests 2015-10-29 16:42:53 +01:00
Julien Duponchelle
dc592e0d4f Wording 2015-10-29 16:38:35 +01:00
Julien Duponchelle
c873b6c603 Fix text not aligned in the appliance wizard 2015-10-29 16:04:32 +01:00
Julien Duponchelle
c7d0a7a504 Add a Qt compatible version of partial
This function detect is the QObject is deleted and
doesn't call the callback.

Fix #596, #735
2015-10-29 15:51:12 +01:00
Julien Duponchelle
e7eddf0a7e Rename Open Appliance to Import appliance 2015-10-29 13:41:50 +01:00
Julien Duponchelle
579e382971 Show Upload filename instead of waiting for 2015-10-29 13:40:55 +01:00
Julien Duponchelle
95ecb05434 Fix error where ISO is detected as an OVA during gns3a import
Fix #737
2015-10-29 11:20:42 +01:00
grossmj
a2353f32e4 Appliance wizard tweaking. 2015-10-28 17:38:43 -06:00
grossmj
793181d208 Removes News Dock Widget. 2015-10-28 14:49:12 -06:00
Julien Duponchelle
932ff53190 Support cdrom image in missing images detections
Fix #737
2015-10-28 17:58:38 +01:00
Julien Duponchelle
e92e23a8be Try to avoid a crash with GUI
Fix #736
2015-10-28 16:42:15 +01:00
Julien Duponchelle
a16adb2b46 Fix crash when appliance is missing 2015-10-28 15:55:41 +01:00
grossmj
f579ebf5a0 Support for capture description in Wireshark window title. 2015-10-26 17:48:57 -06:00
Julien Duponchelle
67593c97ab Move description in the GNS3 appliance 2015-10-23 17:30:05 +02:00
Julien Duponchelle
fe185283a0 Remove a debug 2015-10-22 17:47:26 +02:00
Julien Duponchelle
d2f8214a52 Fix crash with appliance wizard on Linux 2015-10-21 21:15:12 +02:00
Julien Duponchelle
a2293b21ce Set the name of the VM in OSX Terminal application 2015-10-21 17:16:59 +02:00
Julien Duponchelle
57872c38b3 Fix crash of symbol selector if the first file is a non builtin symbol
Fix #734
2015-10-21 13:55:41 +02:00
Julien Duponchelle
51f998c177 Ask for installing appliance
Fix #731
2015-10-21 12:03:36 +02:00
Julien Duponchelle
7abbc630c3 Install appliance from wizard instead of web app
Ref #731
2015-10-21 11:49:44 +02:00
Julien Duponchelle
a0dee6cb42 Fix version number 2015-10-20 16:20:29 +02:00
Julien Duponchelle
d38143ae1c Fix images import
Fix #729
2015-10-20 12:29:07 +02:00
Julien Duponchelle
1db36dfb3e Fix crash when using an old version of 1.4
Fix #733
2015-10-20 12:10:08 +02:00
Julien Duponchelle
a347de96ed Ensure default settings are saved when starting the app
Fix #732
2015-10-20 12:00:58 +02:00
Julien Duponchelle
31c76bf56d Cleanup docker test 2015-10-19 22:15:18 +02:00
Julien Duponchelle
8abf321d9a Use docker for travis build 2015-10-19 22:10:40 +02:00
Julien Duponchelle
3f7b6e7be4 1.4.0dev10 2015-10-19 19:11:45 +02:00
Julien Duponchelle
7b1337cd83 1.4.0b4 2015-10-19 19:04:44 +02:00
Julien Duponchelle
7f63a221af Mokcup of appliances wizard 2015-10-19 18:58:13 +02:00
Julien Duponchelle
cfeb5c9495 Fix tests 2015-10-19 17:04:24 +02:00
Julien Duponchelle
17655cd855 Fix Crash when opening an appliance #728 2015-10-19 17:00:16 +02:00
grossmj
ab071cd989 Mock up for appliance wizard. 2015-10-18 21:54:27 -06:00
grossmj
c73dd10783 Registry: add -nographic to Qemu options by default. Fixes #730. 2015-10-18 21:05:46 -06:00
grossmj
6a5584ae41 Registry: support for initrd, cpu throttling and process priority. 2015-10-18 21:02:42 -06:00
grossmj
16e82592a6 Support for modifications to a base Qemu VM (not a linked clone). 2015-10-18 19:19:27 -06:00
grossmj
842e771eef Registry: adds support for switch category, first_port_name and port_segment_size. 2015-10-18 14:59:35 -06:00
Julien Duponchelle
d31f9c49f5 Fix traceback when exiting the GUI
Ref #726
2015-10-17 21:28:01 +02:00
Julien Duponchelle
8b61c7ddc3 Show a download button
Fix #727
2015-10-17 21:20:19 +02:00
grossmj
af247e2dd6 Corrects some typos. 2015-10-17 11:52:26 -06:00
grossmj
990cb49854 Merge remote-tracking branch 'origin/master' 2015-10-16 15:43:46 -06:00
grossmj
c530924d8a Drops securecrt.vbs 2015-10-16 15:43:31 -06:00
grossmj
35360ae196 Drops securecrt.vbs 2015-10-16 15:42:46 -06:00
grossmj
f37117ed09 Display an error message if QtWebkit is not installed. 2015-10-16 12:51:44 -06:00
Julien Duponchelle
9d2d80db25 Fix console port lost when applying settings
Fix #721
2015-10-16 18:47:20 +02:00
Julien Duponchelle
364d8db5b2 Remove unused code 2015-10-16 17:54:29 +02:00
Julien Duponchelle
0ac5215d4b Merge branch 'master' into unstable 2015-10-16 17:28:50 +02:00
Julien Duponchelle
493d81c519 Fix analytics report on OSX
Fix #724
2015-10-16 17:28:17 +02:00
Julien Duponchelle
c5ab0c8d02 Fix invalid path with frozen application
Fix #722
2015-10-16 11:22:31 +02:00
Julien Duponchelle
03323e5df8 When raising an appliance not found error show full path
Ref #722
2015-10-16 10:43:46 +02:00
grossmj
a8c429b77e Remove unnecessary checks to know if the local server is running. 2015-10-15 18:35:37 -06:00
Julien Duponchelle
52095c8ed9 Merge branch 'master' into unstable 2015-10-15 09:32:43 +02:00
Julien Duponchelle
b13855a062 Analytics send windows 2015-10-15 09:29:37 +02:00
grossmj
0be67907ba Fixes issue when loading a project using VMware vmnet interfaces. Fixes #319. 2015-10-14 21:39:17 -06:00
Julien Duponchelle
cf7285a179 Fix the progress dialog freeze bug 2015-10-14 17:56:18 +02:00
Julien Duponchelle
ba564869a0 Revert "Try to solve Scanning for Appliance images doesn't end"
This reverts commit 07610e7556.
2015-10-14 15:44:26 +02:00
Julien Duponchelle
a6ddddea99 Try to fix the progress dialog freeze bug 2015-10-14 15:32:05 +02:00
Julien Duponchelle
a686a18d56 Drop dead code from getting started dialog
Fix #719
2015-10-14 10:50:14 +02:00
Julien Duponchelle
a98bd132e1 Fix Appliance installs image without adapting the filename
Fix #714
2015-10-14 10:44:02 +02:00
Julien Duponchelle
a100ca33b9 Raise error if reference in GNS3a is invalid 2015-10-13 17:51:54 +02:00
Julien Duponchelle
d2f75262d8 Merge branch 'master' into unstable 2015-10-13 16:56:25 +02:00
Julien Duponchelle
c65fd1683d Fix typo in analytics 2015-10-13 16:55:59 +02:00
Julien Duponchelle
76a8735133 Add information on how to debug 2015-10-13 16:36:47 +02:00
Julien Duponchelle
da3c1334da Merge branch 'master' into unstable 2015-10-13 09:42:15 +02:00
Julien Duponchelle
0c370ec45e Send stats to GNS3 team
Ref #694

* Generate an ID for user and craft a user agent for correct os report
* Track all dialog allowing stats on features
2015-10-13 09:26:45 +02:00
grossmj
ec27e418fc Licenses compliance. 2015-10-12 22:10:43 -06:00
grossmj
92500e96d4 Merge remote-tracking branch 'origin/unstable' into unstable 2015-10-12 15:54:55 -06:00
grossmj
c2ba6f5cb3 Handles warning notifications. 2015-10-12 15:54:32 -06:00
Julien Duponchelle
07610e7556 Try to solve Scanning for Appliance images doesn't end
Ref #713
2015-10-12 19:31:13 +02:00
Julien Duponchelle
741749dffb Fix TypeError: 'NoneType' object is not iterable in isLocalServerRunning
Fix #689
2015-10-12 17:13:23 +02:00
Julien Duponchelle
593c777ff0 Fix crash AttributeError: 'NoneType' object has no attribute
getNewProjectSettings

Fix #711
2015-10-12 17:11:07 +02:00
Julien Duponchelle
8a616fa0c5 Merge branch 'master' into unstable 2015-10-12 15:41:27 +02:00
Julien Duponchelle
a191ec7326 Fix error when importing dynamips config from non existent directory
Fix #710
2015-10-12 15:39:44 +02:00
Julien Duponchelle
f842812745 Merge branch 'master' into unstable 2015-10-12 15:34:00 +02:00
Julien Duponchelle
3cc43aa11f Fix crash when url is invalid
Fix #709
2015-10-12 15:32:04 +02:00
Julien Duponchelle
1d9839ed23 Merge branch 'master' into unstable 2015-10-12 10:25:16 +02:00
Julien Duponchelle
32a64f1259 Add a debug level 2 in the console
Allow to display everything including HTTP queries.
2015-10-12 10:24:38 +02:00
Julien Duponchelle
3c4fc4c1bd Fix a crash when loading appliance 2015-10-08 16:16:17 +02:00
Julien Duponchelle
1013cf527d Merge branch 'master' into unstable 2015-10-08 11:28:38 +02:00
Julien Duponchelle
1684ee3074 Support upload of multiple vmdk file
Fix #702
2015-10-08 11:27:02 +02:00
Julien Duponchelle
f50e08207c 1.3.12dev1 2015-10-07 18:34:39 +02:00
Julien Duponchelle
d3973d4a7b 1.3.11 2015-10-07 18:28:04 +02:00
Julien Duponchelle
7170e58551 Support PNG in the custom symbol selection dialog
Fix #699
2015-10-07 17:53:07 +02:00
grossmj
02968f1ece Add custom messages when computing Idle-PC values. Fixes #704. 2015-10-07 08:41:14 -06:00
Julien Duponchelle
eb94ba8b93 Display the version of Qt in the console 2015-10-07 14:28:47 +02:00
Julien Duponchelle
67c6e03f3b Qt 4.3 is no longer supported 2015-10-07 14:26:16 +02:00
Julien Duponchelle
faa3b519b6 Do not crash when parsing a Qt version with a snapshot notation
Fix #697
2015-10-07 10:39:50 +02:00
Julien Duponchelle
3b4dca7545 Merge branch 'master' into unstable 2015-10-07 10:35:12 +02:00
Julien Duponchelle
66495cbf83 Force nc path to /usr/bin/nc on Apple
Homebrew or macport can break it. Because they install the GNU
verison which doesn't support socket unix.

Fix #664
2015-10-07 10:32:53 +02:00
Julien Duponchelle
95fea87b29 Revert "Drop netcat for unix socket it's not supported by OSX"
This reverts commit a0271926e6.
2015-10-07 10:32:09 +02:00
Julien Duponchelle
4b0cea36d0 Catch errors when we have an infinite recursion when copying a folder
Fix #696
2015-10-07 10:16:21 +02:00
Julien Duponchelle
ec27683f0e Fix crash in recent files when changing locale
Fix #690
2015-10-07 10:12:12 +02:00
Julien Duponchelle
a4d7aaf0a1 Merge branch 'master' into unstable 2015-10-07 10:05:00 +02:00
Julien Duponchelle
e2bcd1fdd1 Catch error when we can't extract egg
Fix #693
2015-10-07 10:04:01 +02:00
Julien Duponchelle
d7fd04de03 Fix securecrt command line (backported from master) 2015-10-07 10:01:20 +02:00
Julien Duponchelle
f447cd9be6 Merge branch 'master' into unstable 2015-10-06 19:17:26 +02:00
grossmj
a080b65615 Updates SecureCRT command line. 2015-10-06 11:10:50 -06:00
Julien Duponchelle
bd034237c0 When it's an ova explain to user he need to download the ova 2015-10-06 18:00:10 +02:00
Julien Duponchelle
66aff0d9a2 OVA file support 2015-10-06 17:49:55 +02:00
Julien Duponchelle
04a4142128 Ignore .cache directory 2015-10-06 10:57:50 +02:00
Julien Duponchelle
ec71da4062 Fix update manager crash on Windows 2015-10-06 10:57:33 +02:00
Julien Duponchelle
0ae97aa933 Support for image in local subdirectory
Ref #700
2015-10-05 11:38:57 +02:00
Julien Duponchelle
580e19de0c Fix duplicate code 2015-10-05 08:51:47 +02:00
grossmj
e41e95b0e6 Fixes issue when saving Idle-PC into template. Fixes #674. 2015-10-04 14:56:34 -06:00
Julien Duponchelle
1adeee9ba1 Add link for downloading VMware 2015-10-02 18:17:09 +02:00
Julien Duponchelle
b598339e55 Cache md5sum in memory when loading a gns3a
Fix #681
2015-10-02 18:12:47 +02:00
Julien Duponchelle
c65e5d8795 Support symbol import from GNS3A
Fix #692
2015-10-02 17:57:49 +02:00
Julien Duponchelle
b8597bc196 Allow user to select symbol from his library
Fix #691
2015-10-02 17:19:45 +02:00
Julien Duponchelle
be75a8e2b8 Merge branch 'master' into unstable 2015-10-02 13:21:28 +02:00
Julien Duponchelle
2352840c3b Improve HTTP progress reliability 2015-10-02 11:21:44 +02:00
Julien Duponchelle
98f9f59af3 Support ubuntu default VNC client (Vinagre)
Fix #687
2015-10-02 11:11:05 +02:00
grossmj
00ba2f1046 Merge remote-tracking branch 'origin/master' 2015-10-02 03:07:39 -06:00
grossmj
0389245cb7 Adds the COPYING file. 2015-10-02 03:06:52 -06:00
Julien Duponchelle
2f746ff791 Fix error when receiving an HTTP error during HTTP progress
Fix #686
2015-10-02 11:05:47 +02:00
Julien Duponchelle
8b881dfd20 Support port_name_format in GNS3 a files
Fix #684
2015-10-01 15:59:50 +02:00
Julien Duponchelle
cfece32185 options is not mandatory in a .gns3 file 2015-10-01 15:12:24 +02:00
Julien Duponchelle
d09ce859aa Merge branch 'master' into unstable 2015-09-30 09:41:52 +02:00
Julien Duponchelle
227a8a0c9e Xshell 5 support
Source: http://www.packetctrl.com/xshell-5-and-gns3-integration/
2015-09-30 09:38:48 +02:00
Julien Duponchelle
1b0da301e3 Add missing gns3-converter to requirements.txt 2015-09-30 08:21:54 +02:00
Julien Duponchelle
0f3efaa3fe Add missing gns3-converter in requirements.txt 2015-09-25 20:08:54 +02:00
grossmj
55b5f49c79 Fixes Qemu binaries not listed in the node configuration dialog. Fixes #683. 2015-09-25 06:06:22 -06:00
grossmj
3601acf66e Fixes SecureCRT command line. 2015-09-24 15:15:43 -06:00
Julien Duponchelle
383306c0ab Speedup directory scan for images when loading a gns3a file
Fix #682
2015-09-23 14:58:04 +02:00
Julien Duponchelle
5f87be16d7 Show a progress bar during directory scan when searching for appliances
Fix #680
2015-09-23 14:37:37 +02:00
Julien Duponchelle
63ab01d364 Search image by default also in the download directory 2015-09-23 14:22:59 +02:00
grossmj
4252f19819 Fixes issue when Telnet doesn't let you to login to an appliance on Linux. 2015-09-22 16:11:35 -06:00
grossmj
1095ed1663 Bump version to 1.4.0.dev9 2015-09-22 16:07:21 -06:00
grossmj
c5557e45c4 Fixes issue when Telnet doesn't let you to login to an appliance on Linux. 2015-09-22 16:06:35 -06:00
Julien Duponchelle
f5159a93f3 Prepare 1.4.0b3 2015-09-22 17:20:24 +02:00
Julien Duponchelle
b00d39e531 Add a warning if you don't select VMware or VBox in Setup Wizard
Fix #677
2015-09-22 15:13:56 +02:00
Julien Duponchelle
0c077b5647 Fix Configuration not always saved in client
Fix #678
2015-09-22 13:38:34 +02:00
grossmj
98aed2a8b6 Fixes file path reference issue. 2015-09-22 03:46:50 -06:00
Julien Duponchelle
0523873e5e Fix Appliance doesn't work on local Server #669 2015-09-22 11:16:40 +02:00
Julien Duponchelle
ed5ce93df6 Merge remote-tracking branch 'origin/master' into unstable 2015-09-22 11:01:44 +02:00
Julien Duponchelle
ab4f85b862 Merge branch 'master' into unstable 2015-09-22 11:01:18 +02:00
grossmj
67912a918f Allows Qemu VM template editing if the server is not running. Fixes #671. 2015-09-20 11:39:36 -06:00
grossmj
0af939bd37 Fixes NIO_VMNET != NIO_VMnet. 2015-09-19 03:34:10 -06:00
grossmj
b712b54786 Bump version to 1.4.0dev8 2015-09-18 15:41:34 -06:00
grossmj
19bf52661e Automatically add the -no-kvm option if -icount is detected to help with the migration of ASA VMs created before version 1.4 2015-09-18 15:38:55 -06:00
grossmj
c0c0261c68 Some improvements. 2015-09-18 09:46:51 -06:00
Julien Duponchelle
1eea941b55 Try to fix the Runtime error
Fix #668
2015-09-18 09:04:31 +02:00
Julien Duponchelle
547a8fb6c4 1.4.0 beta2 2015-09-17 16:41:08 +02:00
Julien Duponchelle
a0271926e6 Drop netcat for unix socket it's not supported by OSX
Fix #664
2015-09-17 16:08:56 +02:00
Julien Duponchelle
7e796fc3f1 Drop a debug 2015-09-17 16:01:49 +02:00
Julien Duponchelle
ba17b9d789 Fix for fusion 2015-09-17 15:22:45 +02:00
Julien Duponchelle
a4c17562ad VMware fusion is supported
Fix #661
2015-09-16 22:04:13 +02:00
Julien Duponchelle
ca173fb491 Fix a crash when a process return an error in sudo 2015-09-16 17:26:44 +02:00
Julien Duponchelle
9330689641 Last 1.3.X is 1.3.10. 2015-09-16 16:12:45 +02:00
Julien Duponchelle
ca67553e66 Fix race conditions in http_client
Fix #660
2015-09-16 15:57:59 +02:00
grossmj
dabcb6d4f4 Merge remote-tracking branch 'origin/unstable' into unstable 2015-09-16 05:26:18 -06:00
grossmj
753eb79a15 Fixes output issue when trying to run gns3vmnet.exe 2015-09-16 05:25:08 -06:00
Julien Duponchelle
034c9e8ad5 Forgot to remove this code 2015-09-16 13:19:29 +02:00
Julien Duponchelle
ba04783e8f Drop the licence POC 2015-09-16 13:16:40 +02:00
grossmj
a8ba51cdee Merge remote-tracking branch 'origin/unstable' into unstable 2015-09-16 05:11:36 -06:00
grossmj
24997c39f5 Fixes issues when trying to run gns3vmnet.exe 2015-09-16 05:11:11 -06:00
Julien Duponchelle
919311e2ab Dissalow gns3a import on local server for win and mac 2015-09-16 12:11:46 +02:00
Julien Duponchelle
61c3b0bfff Cleanup and test server select box 2015-09-16 11:54:50 +02:00
Julien Duponchelle
8024738400 Fix http_client tests 2015-09-16 11:04:03 +02:00
Julien Duponchelle
ac58bc677f On OSX show a warning when using an old Qemu
Fix #658
2015-09-16 10:13:48 +02:00
Julien Duponchelle
3b887f7f1b Refactor select code to use the same for appliance and graphics 2015-09-15 22:36:25 +02:00
Julien Duponchelle
8ea24a156e Disallow to install an appliance when an appliance twice 2015-09-15 22:11:01 +02:00
Julien Duponchelle
264fe8f0c8 Show a progress dialog when importing appliances 2015-09-15 16:11:14 +02:00
Julien Duponchelle
3f67cd4a99 Install gns3a from current directory
Fix #652
2015-09-15 15:36:26 +02:00
Julien Duponchelle
5d9e9dfc4a Tab support for xfce4-terminal 2015-09-15 11:13:30 +02:00
grossmj
95bec70e27 Improve alignments. Fixes #215. 2015-09-14 15:43:26 -06:00
grossmj
c1c6c812c8 Improve alignments. Fixes #215. 2015-09-14 15:41:37 -06:00
grossmj
0a8d947375 Fixes ethertype validation error. 2015-09-14 15:32:49 -06:00
grossmj
c9a699fc30 Bump version to 1.4.0dev7. 2015-09-14 15:19:57 -06:00
grossmj
8bf350a7dd Improve check for uBridge permissions. 2015-09-14 14:58:35 -06:00
Julien Duponchelle
bbc468db0f Fix an uuid is display instead of the server url
Fix #657
2015-09-14 18:10:16 +02:00
Julien Duponchelle
2353f074ab Set root permission to ubridge on OSX
Fix #655
2015-09-14 17:49:23 +02:00
Julien Duponchelle
79b7174a83 Show GNS3 version at startup 2015-09-14 17:49:23 +02:00
grossmj
82e1c088c7 Allows to select a remote server to run a switch. Fixes #653. 2015-09-13 11:11:14 -06:00
grossmj
1d13a3de3c Support for packet capture on VMware VM links. 2015-09-13 09:40:09 -06:00
Julien Duponchelle
0fb0bafc14 VMware OSx use local server by default 2015-09-11 16:33:31 +02:00
Julien Duponchelle
6cc5547509 Always use ubridge with VMware by default
Fix #648
2015-09-11 16:32:36 +02:00
Julien Duponchelle
a72df53b69 Another fix for docker module missing on frozen OSX application
Fix #649
2015-09-11 16:13:20 +02:00
Julien Duponchelle
f0802038db Fix docker module missing on frozen OSX application
Fix #649
2015-09-11 15:49:25 +02:00
Julien Duponchelle
631b4b7a61 Fix appliance error display when opening invalid gns3a 2015-09-11 14:37:58 +02:00
Julien Duponchelle
d9436520af Split the open menu between Open project & Open appliance
Fix #651
2015-09-11 14:33:59 +02:00
Julien Duponchelle
d805cfbd6a Fix PermissionError: [Errno 1] Operation not permitted when kill process
Fix #626
2015-09-11 14:19:54 +02:00
Julien Duponchelle
078d5023c4 VMware fusion support is no longer experimental
Fix #656
2015-09-11 14:13:33 +02:00
Julien Duponchelle
bc053da538 Support drag & drop gns3a
Fix #650
2015-09-11 12:13:02 +02:00
Julien Duponchelle
5d79bbce39 Fix crash when opening gns3a from double click 2015-09-11 09:57:21 +02:00
Julien Duponchelle
98c8d56dc5 Fix an error when loading IOU schema with private_config 2015-09-11 09:15:28 +02:00
Julien Duponchelle
1acaa18c3c UTF-8 support for appliance 2015-09-10 14:08:27 +02:00
Julien Duponchelle
8325fe0cee Try to support open a file via double click on OSX
Ref #646
2015-09-10 13:44:42 +02:00
Julien Duponchelle
eedd12207c Move HTML templates to static 2015-09-10 10:39:01 +02:00
Julien Duponchelle
64ed8c3de0 Fix open project via file menu 2015-09-10 10:24:46 +02:00
Julien Duponchelle
ab4f2f3922 Add templates as resources 2015-09-09 22:11:51 +02:00
Julien Duponchelle
fc5bf2dc4b Initial version of an appliance file format 2015-09-09 21:24:28 +02:00
Julien Duponchelle
bd0fabd1f6 Fix Missing configChangedSlot in Docker
Fix #645
2015-09-09 21:24:28 +02:00
grossmj
a4a2963bc3 Add white background for Docker symbol. 2015-09-09 10:37:03 -06:00
grossmj
310f47b52a Turn off local Docker support for Windows and OSX. Fixes #641. 2015-09-09 05:01:11 -06:00
grossmj
b4a187dd02 Adds docker symbols. Fixes #643. 2015-09-09 04:43:45 -06:00
grossmj
f4afdca576 Call the vmnet management script from the GUI (with admin rights). Implements #639. 2015-09-09 02:46:30 -06:00
Julien Duponchelle
28bebff7b0 Add a scary warning for the experimental mode 2015-09-08 21:34:53 +02:00
Julien Duponchelle
c3a4daef87 Allow to use vmware fusion with experimental support 2015-09-08 21:31:42 +02:00
Julien Duponchelle
18a5a28283 Fix crash at gui startup
Fix #642
2015-09-08 15:10:49 +02:00
Julien Duponchelle
36d08d2dca Fix Docker wizard when used with a remote server 2015-09-08 15:05:01 +02:00
Julien Duponchelle
91bf6e667d Use self update only if experimental features are allowed 2015-09-08 13:30:35 +02:00
Julien Duponchelle
a88a47e223 Fix default page in general preferences 2015-09-08 13:22:43 +02:00
Julien Duponchelle
8ede0f2089 Rename docker VMs to Docker Containers 2015-09-08 13:19:32 +02:00
Julien Duponchelle
576f6c81a1 Add an option for enabling experimental features 2015-09-08 11:50:55 +02:00
Goran Cetusic
1666fc4aa0 Backport docker support from Google Summer Of Code 2015-09-08 11:06:49 +02:00
grossmj
1216882e89 Merge branch 'Bevaz-qinq_ethertype' into unstable 2015-09-08 02:47:58 -06:00
grossmj
3f825a163b Merge branch 'qinq_ethertype' of https://github.com/Bevaz/gns3-gui into Bevaz-qinq_ethertype
Conflicts:
	gns3/modules/dynamips/ui/ethernet_switch_configuration_page_ui.py
2015-09-08 02:45:08 -06:00
Julien Duponchelle
2fcfa10573 Add a run with sudo class for OSX and Linux
Ref #639
2015-09-07 22:01:56 +02:00
Jeremy Grossmann
dd95b24d32 Merge pull request #640 from ryanchapman/master
Spelling correction
2015-09-05 15:40:40 -06:00
Ryan A. Chapman
bb2777ed5b Spelling correction 2015-09-05 15:26:22 -06:00
grossmj
e0f03ec582 Allows VMware VMs to use vmnet interfaces for connections without using uBridge. 2015-09-05 14:38:44 -06:00
Julien Duponchelle
51e844559e Prepare next release 2015-09-04 21:34:20 +02:00
Julien Duponchelle
dc4a984c41 Prepare version 1.3.10 2015-09-04 18:13:18 +02:00
Julien Duponchelle
54139845ac Add a firewall symbol
Fix #631
2015-09-04 10:41:54 +02:00
grossmj
8f9672d9e2 Updates kernel command line of ASA. 2015-09-03 16:52:36 -06:00
Julien Duponchelle
b007aea2f5 Detect broken link in topologies
Ref #635
2015-09-03 18:26:59 +02:00
Julien Duponchelle
3900645d1f Fix project not closing
https://github.com/GNS3/gns3-server/issues/305
2015-09-03 16:54:48 +02:00
Julien Duponchelle
5d644467fc Fix autostart
Fix #633
2015-09-03 15:16:23 +02:00
Julien Duponchelle
29fcd07b1c Merge branch 'master' into unstable 2015-09-03 10:20:37 +02:00
Julien Duponchelle
22c2ee31c4 Fix file not found exception in vpcs list dir
Fix #632
2015-09-03 10:19:55 +02:00
Julien Duponchelle
69f99742a8 Add missing virtio-net-pci to the json schema 2015-09-02 11:03:23 +02:00
Julien Duponchelle
e7dc901d5e Fix the all devices views
Fix #630
2015-08-28 20:55:59 +02:00
Julien Duponchelle
4dba7fa7fc Fix double click event on Note Item
Fix #629
2015-08-28 15:44:10 +02:00
Julien Duponchelle
55d4201aaf Fix Accepting insecure https connections creates additional server entry
And fix server password is regenerated

Fix #605, #627
2015-08-27 15:40:31 +02:00
Julien Duponchelle
74a4e464c8 Allow developer to debug packet capture on Windows 2015-08-26 18:25:10 +02:00
Julien Duponchelle
329c196047 Merge branch 'master' into unstable 2015-08-26 14:36:40 +02:00
Julien Duponchelle
85e74b482e Fix saveAs error unsupported operand type(s) for +=: 'NoneType' and
'str'

Fix #615
2015-08-26 14:16:04 +02:00
Julien Duponchelle
dc12fdd1c9 Drop unused test 2015-08-26 13:54:29 +02:00
Julien Duponchelle
0ee64ecbb8 Catch error when antivirus corrupt our own JSON errors
Fix #611
2015-08-26 13:53:04 +02:00
Julien Duponchelle
2946e931aa Add a note about VIX API require for VMware player 2015-08-26 13:21:33 +02:00
Julien Duponchelle
30871f0cd1 Return original path in case of error when moving image 2015-08-26 10:06:07 +02:00
Julien Duponchelle
70aa165444 Create image directory if not exists 2015-08-26 10:04:41 +02:00
Julien Duponchelle
beb35c6108 Allow GUI to be start with python -m gns3 2015-08-25 18:45:16 +02:00
Julien Duponchelle
90d1cb9a7f Avoid errors in qemu configuration if server has been deleted
Fix #610
2015-08-25 10:20:48 +02:00
Julien Duponchelle
5754d66560 Fix error when the IOS image directory is not writable
Fix #614
2015-08-25 10:05:28 +02:00
Julien Duponchelle
77ba02f0ae Do not crash if something intercept the call to the update server
Fix #620
2015-08-25 10:02:24 +02:00
Julien Duponchelle
effdc862a2 Fix super(): no arguments in SSH client
Fix #622
2015-08-25 09:54:02 +02:00
Julien Duponchelle
59c4736f41 Catch error when configuration file contain invalid UTF-8 chars
Fix #613
2015-08-25 09:50:10 +02:00
grossmj
dff831eafe Merge remote-tracking branch 'origin/unstable' into unstable 2015-08-24 20:18:55 -06:00
grossmj
4765640dc7 Fixes #621. 2015-08-24 20:16:59 -06:00
Julien Duponchelle
b8799a91b4 1.4.0dev6 2015-08-24 17:15:30 +02:00
Julien Duponchelle
17aaa90fb1 Fix JSON schema for dynamips power supply and sensors 2015-08-24 15:35:13 +02:00
Julien Duponchelle
40b8969d44 Fix tests conflict between request fixture and our http_request fixture
Also turn on stdout capture.
2015-08-24 15:09:30 +02:00
Julien Duponchelle
73454d97e1 Fix missing boot_priority in JSON schema 2015-08-24 14:40:05 +02:00
Julien Duponchelle
7cf39aac5a Complete the error message about corrupted topologies
I hope users will understand it better and send
us the .gns3 file with the error.
2015-08-24 14:06:12 +02:00
grossmj
2880168566 Removes ASAv warning in Qemu Wizard. 2015-08-22 17:20:37 -06:00
Anton Fedotov
615d9240ad EthernetSwitch: Allow to choose ethertype for QinQ outer tag. 2015-08-20 10:06:59 +03:00
grossmj
76f8aa4f60 Adds missing properties for rectangle and ellipse in schema validation. 2015-08-17 21:46:32 -06:00
grossmj
0172dd0b53 It is not necessary to catch the FileExistsError exception. 2015-08-13 20:16:41 -06:00
grossmj
ccb6a5cf0f Use Qemu 0.11.0 instead of version 0.13.0 on Windows. 2015-08-11 17:03:12 -06:00
grossmj
7dc37c9dca Removes "resources_type" references. Fixes #493. 2015-08-10 22:21:10 -06:00
grossmj
69f13621ca A thread is not needed to check for local config file changes. Fixes #607. 2015-08-10 18:33:59 -06:00
grossmj
92b9efea12 Merge remote-tracking branch 'origin/unstable' into unstable 2015-08-07 10:42:43 -06:00
grossmj
d1af92942d Fixes bug when validating VMware wizard page. 2015-08-07 10:42:26 -06:00
Julien Duponchelle
b47b5e2dc0 1.4.0beta1 2015-08-07 18:37:35 +02:00
Julien Duponchelle
3265a94d26 Show an error id you try to use a local server not started 2015-08-07 18:30:43 +02:00
Julien Duponchelle
e9d9dc2748 CLear the list before asking for VM list for Vbox and Vmware 2015-08-07 18:09:38 +02:00
Julien Duponchelle
8b38d4967c Fix bugs report by elhers 2015-08-07 17:35:26 +02:00
Julien Duponchelle
3729070e33 Fix password lost for remote servers
Fix #603
2015-08-07 15:31:07 +02:00
Julien Duponchelle
d415c20446 Unused import 2015-08-07 15:19:51 +02:00
Julien Duponchelle
efb5931be3 Fix schema for virtualbox 1.3.2 topologies
https://community.gns3.com/message/40214
2015-08-07 15:17:44 +02:00
Julien Duponchelle
4867a5510a Refactor all VM wizards
* All the wizards inherit of vm_wizard even VMware and VirtualBox
* Code for managing images is in vm_wizard_with_images (Qemu, Dynamips,
IOU)
* If GNS3VM is not running you can't select it at first step

Fix #604
2015-08-07 14:30:56 +02:00
Julien Duponchelle
932dd79ac1 Fix Apply not enabled when removing a remote server
Fix #602
2015-08-07 11:42:48 +02:00
Julien Duponchelle
dc5957dd0a Fix remote server list display when use_local_server for Qemu 2015-08-07 09:53:03 +02:00
grossmj
bb131b4ff5 Keep the "use local server" settings to select the default radio button in VM wizards. Ref #598. 2015-08-06 23:43:12 -06:00
grossmj
76e3d3523e Fixes #601 (spelling error). 2015-08-06 15:11:48 -06:00
Julien Duponchelle
2bc9dd2802 Store the url of server in gns3_gui for third party apps 2015-08-06 17:23:04 +02:00
Julien Duponchelle
0950c3d80d Correctly handle remote server in qemu wizard
Fix #599
2015-08-06 16:35:03 +02:00
Julien Duponchelle
808ea00787 Fix error when editing a qemu device with a relative path
Fix #594
2015-08-06 14:48:50 +02:00
grossmj
c4400f8a64 Fixes issue in VirtualBox wizard when no local server is enabled in the VirtualBox general settings. 2015-08-05 22:42:16 -06:00
grossmj
4a78cfe00a Catch exception when starting packet capture reader for a remote packet capture. Fixes #597. 2015-08-05 19:07:54 -06:00
grossmj
a10f8939e2 Fixes bug when opening Node properties dialog via a double click. 2015-08-05 18:53:56 -06:00
grossmj
4b681a5e55 SecureCRT (installed on personal profile) command line. 2015-08-05 18:45:59 -06:00
grossmj
4e073b4681 Fixes KeyError: 'vmx_path'. Fixes #595. 2015-08-05 17:38:28 -06:00
grossmj
e9548b2e03 Support for CPUs setting for Qemu VMs. 2015-08-05 17:17:55 -06:00
Julien Duponchelle
05820e973b Fix chicken of VNC command and add a warning about bugs in OSX VNC
Fix #593
2015-08-05 14:57:43 +02:00
grossmj
f779b6fe7d Bump version to 1.4.0dev5. 2015-08-04 15:29:03 -06:00
Julien Duponchelle
210c46f49d Fix issue whith auto update when we release a new build 2015-08-04 20:11:48 +02:00
Julien Duponchelle
e746ddc525 1.4.0alpha4 2015-08-04 19:48:09 +02:00
grossmj
d186d4ce1e Use half the available physical memory for the GNS3 VM in the Setup Wizard. 2015-08-04 11:32:40 -06:00
Jeremy Grossmann
cee80cc579 Merge pull request #585 from GNS3/wizard_step_1
Show the server choice in wizard if you have a VM or a remote server
2015-08-04 11:31:13 -06:00
Jeremy Grossmann
1c0232cf96 Merge pull request #591 from GNS3/drop_resource_type
Drop useless notion of resource_type
2015-08-04 11:20:23 -06:00
Julien Duponchelle
77ff7a8aba Fix tests 2015-08-04 18:03:47 +02:00
Julien Duponchelle
fed48de0d5 Drop useless notion of resource_type 2015-08-04 17:58:47 +02:00
Julien Duponchelle
95c1df229f Fix When you modify config from outside router list is not refresh
Fix #590
2015-08-04 17:51:31 +02:00
Julien Duponchelle
78b2cb8a32 Sync auth settings between 1.3 and 1.4
Fix #589
2015-08-04 15:25:15 +02:00
Julien Duponchelle
e1ba7a0ad6 Fix merge error 2015-08-04 15:24:18 +02:00
Julien Duponchelle
e64597eaf0 Group bad request by path
Fix #587
2015-08-04 14:57:03 +02:00
Julien Duponchelle
f1b7ea13ef Fix behavior of wizard for vmware and virtualbox 2015-08-04 12:46:31 +02:00
Julien Duponchelle
25d6a0a160 Disallow connection to a different major version in all cases
And test all cases

Fix #586
2015-08-04 12:35:58 +02:00
Julien Duponchelle
5be13a645e Merge branch 'master' into unstable 2015-08-03 19:24:30 +02:00
Julien Duponchelle
dfa85e9886 Prepare version 1.3.10 2015-08-03 19:21:48 +02:00
Julien Duponchelle
8a612970e6 1.3.9 2015-08-03 18:56:10 +02:00
Julien Duponchelle
f18a9fe7f5 Show the server choice in wizard if you have a VM or a remote server
It's easier for using instead of searching the screen with use
local server options.

But I think it's not complete because we still have the checkbox
in the preferences.

When I read the code I found this:
cd9bb16f79/gns3/modules/builtin/__init__.py (L72)

And I'm not sure in which case it's call. I think it's only for
VPCS and things like Dynamips switch. Is it right? If it's the case
we can
drop the checkbox from IOU, Qemu, VMware, VirtualBox
2015-08-03 15:53:59 +02:00
Julien Duponchelle
a5d0fe5b8b Fix tests 2015-08-03 12:00:55 +02:00
Julien Duponchelle
3ef70a1213 Fix local server settings erased at each launch
Fix #580
2015-08-03 11:44:55 +02:00
grossmj
3bd2136450 Support for Qemu disk interfaces, cd/dvd-rom image and boot priority. 2015-08-02 23:02:17 -06:00
grossmj
c165146d7c Prevents progress dialog to stay displayed (fixes graphical bug). 2015-08-01 15:19:57 -06:00
grossmj
adfdae3a8e Check that DHCP is enabled on the VirtualBox host-only network associated with the VirtualBox GNS3 VM. Fixes #287. 2015-08-01 14:48:41 -06:00
grossmj
f92aae4e6e Fixes Qt5 incompatibility. 2015-08-01 11:58:32 -06:00
grossmj
bed867cf7b Catch exception when trying to launch Wireshark. 2015-08-01 11:55:26 -06:00
grossmj
81aaeaf25f Adds traceback information when there is an assertion error with topologyFile. 2015-08-01 11:54:06 -06:00
grossmj
3cc62563df Catch exception when trying to launch Wireshark. 2015-08-01 11:49:40 -06:00
grossmj
aaa21be642 Backport: fixes migration of cloud interfaces. 2015-08-01 11:28:12 -06:00
grossmj
aa87cb0064 Fixes migration of cloud interfaces. Fixes #582. 2015-08-01 11:19:12 -06:00
grossmj
1e6e2d32e3 Wait for the server to be fully started in the GNS3 VM. Fixes #581. 2015-07-31 15:42:47 -06:00
Julien Duponchelle
a95805bc04 1.4.0dev4 2015-07-31 15:34:10 +02:00
Julien Duponchelle
a5ccce30d6 Fix issue with file upload and Qt 5.5
For an unknow reason it's stop working with Qt 5.5
the fix is to use QtCore.Qt.QueuedConnection on the slot
in order to avoid blocking the HTTP thread.

Fix #584
2015-07-31 12:21:50 +02:00
grossmj
f6fdd79d0f Fixes version. 2015-07-30 19:07:25 -06:00
grossmj
3f9c1af8e8 Improves and fixes a bug with the Symbol dialog. 2015-07-29 21:58:54 -06:00
grossmj
be9a88029b Improves the symbol dialog. Implements #514. 2015-07-29 18:21:14 -06:00
Julien Duponchelle
de53581826 1.4.0alpha3 2015-07-29 18:16:08 +02:00
Julien Duponchelle
d8db54d8eb Clarify informations in the IOUVM converter wizard 2015-07-29 14:19:53 +02:00
Julien Duponchelle
64aa8e9190 Hide the browse button for remote servers in qemu wizard 2015-07-29 12:00:39 +02:00
Julien Duponchelle
7719fb5fed Ask for app restart during in app upgrade
Ref #578
2015-07-29 11:46:26 +02:00
Julien Duponchelle
e5d8fac004 When you turn off crash report has developer no warning about .git
Fix #580
2015-07-29 11:07:10 +02:00
grossmj
c8ce6e0dc1 Ensure proper naming for Qemu disk images. 2015-07-28 22:15:37 -06:00
grossmj
7523ff50ff Show the disk image create button in the Qemu VM wizard for remote server and the GNS3 VM. 2015-07-28 21:21:47 -06:00
grossmj
74cd7f07a0 Adds psutil dependency. 2015-07-28 19:34:13 -06:00
grossmj
1edfcc2c42 Configure vCPU/RAM from setup wizard. Implements #565. 2015-07-28 19:31:54 -06:00
grossmj
631f283cba Should fix KeyError: 'vmx_path'. Fixes #574 . 2015-07-28 17:34:58 -06:00
grossmj
a33609b144 Restart the local server from the setup wizard if necessary. Fixes #577. 2015-07-28 17:27:03 -06:00
grossmj
572e028917 Start the GNS3 VM first before the local server. Fixes #577. 2015-07-28 17:26:36 -06:00
Julien Duponchelle
31262f9f7f Fix tests PyQT 5.5 compatibility 2015-07-28 17:30:34 +02:00
Julien Duponchelle
e5af0e778f Changelog 1.4.0alpha3 2015-07-28 17:24:04 +02:00
Julien Duponchelle
97a6d23d36 Merge branch 'master' into unstable 2015-07-28 16:55:05 +02:00
Julien Duponchelle
773d680e42 New crash report key 2015-07-28 16:53:28 +02:00
Julien Duponchelle
a43236dfc3 Merge pull request #566 from GNS3/iouvm_converter
IOUVM converter
2015-07-28 15:52:38 +02:00
Julien Duponchelle
12e65994ae Manage errors 2015-07-28 15:52:12 +02:00
Julien Duponchelle
d7b43ef5cf IOUVM converter 2015-07-28 15:52:11 +02:00
Julien Duponchelle
97a7496854 Update configuration file for replacing GNS3VM by IOUVM 2015-07-28 15:51:28 +02:00
Julien Duponchelle
e6e24ef953 Create qemu disk image on remote server
Fix #558
2015-07-28 14:37:14 +02:00
Julien Duponchelle
1903fc2a6f Create qemu image on the server
Fix #569, #562
Ref #558
2015-07-28 14:20:33 +02:00
Jeremy Grossmann
94613f0458 Merge pull request #567 from GNS3/apply
Inform user before exiting preferences dialog with changes
2015-07-27 12:28:42 -07:00
Jeremy
2072fee01a Merge remote-tracking branch 'origin/master'
Conflicts:
	CHANGELOG
	gns3/version.py
2015-07-27 12:03:57 -06:00
Jeremy
b1658f3799 1.3.8 2015-07-27 12:03:07 -06:00
Julien Duponchelle
115654fa1d 1.3.9dev1 2015-07-27 20:02:49 +02:00
Julien Duponchelle
8c3179f0fe 1.3.8 2015-07-27 19:58:51 +02:00
Julien Duponchelle
4313aed9f0 Yet another PyQT 5.5 bug fix 2015-07-27 17:27:14 +02:00
Julien Duponchelle
1cbc3a0063 Fix Error with qemu-create when changing refcount bits
Fix #576
2015-07-27 14:42:24 +02:00
Julien Duponchelle
102e5cba6b More PyQT 5.5 compatibility
Fix #568
2015-07-27 11:48:31 +02:00
Julien Duponchelle
e932780f02 Fix _addRemoteServer() got an unexpected keyword argument 'local'
Fix https://github.com/GNS3/gns3-server/issues/281
2015-07-27 11:43:08 +02:00
Julien Duponchelle
1b0415f81d Do not crash if configuration file is removed
Fix #572
2015-07-27 11:29:28 +02:00
Julien Duponchelle
aa82383d2c Fix PyQT 5.5 compatibility
Fix #568
2015-07-27 11:26:32 +02:00
Jeremy
57d1c2a81a Fixes rare issue when adding a link. Fixes #573. 2015-07-26 16:10:12 -06:00
Jeremy
606ddb7b38 Fixes rare issue when adding a link. Fixes #573. 2015-07-26 16:08:55 -06:00
Jeremy
f3f7829bbe Fixes crash with PyQt 5.5. Fixes #568. 2015-07-25 15:03:22 -06:00
Jeremy
ae9a009f1f Changes how to look for the vmrun.exe location. 2015-07-24 16:50:36 -06:00
Julien Duponchelle
6c6bf7870d Inform user before exiting preferences dialog with changes
This Gray out the apply button by default. If something change
the button apply is enabled.

If you try to exit the windows without saving you got a warning.

The change detection is made by binding to various signal of the
preferences dialog childrens.

This work also when coming from the setup wizard.

Fix #515
2015-07-24 16:30:18 +02:00
Julien Duponchelle
6cff9d6fb5 Write GNS3 upgrade to appdata
Fix #564
2015-07-24 15:37:20 +02:00
Julien Duponchelle
0a71be1205 Fix windows asking for upgrade to the wrong version
Also replace the parse version of setup tools because it's
display a warning when comparing tuples.

Fix #563
2015-07-24 15:03:24 +02:00
Julien Duponchelle
3736c3380c Drop unused code 2015-07-24 10:57:28 +02:00
Julien Duponchelle
1beb25a820 Merge branch 'master' into unstable 2015-07-23 11:27:21 +02:00
Jeremy
202eb95eb3 Merge remote-tracking branch 'origin/unstable' into unstable
Conflicts:
	gns3/version.py
2015-07-22 20:56:48 -06:00
Jeremy
eaa5a326fe Bump version to 1.4.0dev3 2015-07-22 20:55:54 -06:00
Jeremy
409d3de69c Backport: option to drop nvram & disk files for IOS routers in order to save disk space. 2015-07-22 16:02:08 -06:00
Julien Duponchelle
e05ee6bba0 1.4.0alpha2 2015-07-22 20:42:47 +02:00
Jeremy
111ed742ec Change default timeout for VBoxManage and vmrun from 10 to 60 seconds. 2015-07-22 11:41:46 -06:00
grossmj
8fd5743d75 Fixes VPCS "" does not exist message box. 2015-07-22 09:39:39 -06:00
Jeremy
63b79ccf3b Cloud support with the GNS3 VM. 2015-07-21 19:20:07 -06:00
Jeremy
45f4265c03 Display an error message when Qemu binaries cannot be retrieved in the Qemu VM configuration page. 2015-07-21 17:10:43 -06:00
Jeremy
b7b13ea2cb Remove default FLASH when no hda disk for Qemu VMs. Fixes #535. 2015-07-21 16:46:27 -06:00
Jeremy
1f660b180e Fixes indentation mistakes. 2015-07-21 16:04:55 -06:00
Jeremy
3b2ccf75ec Use the registry to find vmrun if the default VMware install path doesn't exist. Fixes #546. 2015-07-21 15:58:42 -06:00
Julien Duponchelle
734fc65c29 Merge branch 'master' into unstable 2015-07-21 18:49:40 +02:00
Julien Duponchelle
5252ed16ca New crash report key 2015-07-21 18:49:09 +02:00
Jeremy
cec6fcf81a Avoid the creation of a NIO when one has been cancelled. 2015-07-20 19:31:35 -06:00
Jeremy
a812796bdc Avoid the creation of a NIO when one has been cancelled. 2015-07-20 19:28:51 -06:00
Julien Duponchelle
9abb4fe692 Fix Crash with chinese characters
Fix #553
2015-07-17 17:26:02 +02:00
Julien Duponchelle
42b86c6b18 Display an error if terminal command is invalid
Fix #550
2015-07-17 17:14:57 +02:00
Julien Duponchelle
8aec2275fd Fix TypeError: _addRemoteServer() got an unexpected keyword argument
'cloud'

Fix #551
2015-07-16 19:03:21 +02:00
Julien Duponchelle
61f03d734b Fix TypeError: _addRemoteServer() got multiple values for keyword argument 'user'
Fix #547
2015-07-16 11:02:14 +02:00
Julien Duponchelle
907e20d0ec Fix AttributeError: 'UUID' object has no attribute 'connected'
Fix #543
2015-07-16 10:44:36 +02:00
Julien Duponchelle
f84c759e8d Fix AttributeError: 'LocalConfig' object has no attribute '_last_config_changed'
Ref #545
2015-07-16 10:38:23 +02:00
grossmj
f6fb4695c1 Fixes missing return in isLocalServerRunning() 2015-07-15 17:47:00 -06:00
grossmj
3a1ccb5ba0 Prevents "Show in File Manager" to be used with generic switches. 2015-07-15 16:18:01 -06:00
grossmj
7b8ab4ac2c Fixes code indentation issue with auto idle-pc feature. 2015-07-15 16:11:39 -06:00
grossmj
53504f1c3d Removes reference to cloud server in VirtualBox VM wizard. 2015-07-15 16:02:36 -06:00
Julien Duponchelle
d5408165f9 If GUI exit due to a signal do not warn user
This avoid issue for user trying to automate GNS3

Fix #542
2015-07-15 18:56:32 +02:00
Julien Duponchelle
9bf8c115c1 Fix typo in variable name 2015-07-15 18:11:56 +02:00
Julien Duponchelle
a06ac4cbb6 Fix some schema validation errors 2015-07-15 14:59:32 +02:00
Julien Duponchelle
6406b7412d Log error about why gns3 converter can't be used
Ref #540
2015-07-15 13:27:08 +02:00
Julien Duponchelle
41aca47f92 Remove unused dependencies 2015-07-15 13:14:47 +02:00
Julien Duponchelle
a170e1cfb5 Cleanup UI after QT4 drop 2015-07-15 12:25:46 +02:00
Julien Duponchelle
b2429a6a1b Drop PyQt4 support and show an error for users
Fix #533, #532
2015-07-15 12:17:54 +02:00
Julien Duponchelle
23e1baf92f First bugs discover by gns3-qa :)
* The dot1q was not supported in JSON schema validation
* border_style is not always mandatory
* border_width propery for ellipse
2015-07-13 14:52:15 +02:00
Julien Duponchelle
278c94b7df Log corrupted topology 2015-07-13 14:52:14 +02:00
Julien Duponchelle
256fc5a222 Log missing IOS images 2015-07-13 14:52:14 +02:00
Julien Duponchelle
a0fa28b3fd Call AutoStart even if the topology is empty. 2015-07-13 14:52:14 +02:00
grossmj
09d8212225 Fixes symbol for VM template gone after restart. Fixes #538. 2015-07-12 16:51:43 -06:00
Julien Duponchelle
e658786e88 Wait for VirtualBox vm start
Fix #530
2015-07-11 14:56:28 +02:00
Julien Duponchelle
4a1e6eba8c Fix VirtualBox GNS3 VM
Fix #530
2015-07-10 22:51:27 +02:00
Julien Duponchelle
ce5e209681 Fix QComboBox broken with PyQT4
Fix #526
2015-07-10 20:29:47 +02:00
Julien Duponchelle
40178b5277 Do not send error to the notification feed
Fix #528
2015-07-10 20:15:07 +02:00
Julien Duponchelle
631c487233 Fix issue with remote server not saved/migrated
Fix #521
2015-07-10 18:48:04 +02:00
Julien Duponchelle
5e47afe3a4 Remove ram as a mandatory dynamips settings
Fix #523
2015-07-10 17:33:32 +02:00
Julien Duponchelle
942bf9094d Force UTF-8 when reading server configuration file
Fix #525
2015-07-10 17:28:20 +02:00
Julien Duponchelle
985200b6d9 Fix setup wizard PyQT4 compatibility
clicked as default argument False with Qt5 but not with Qt4

Fix #527
2015-07-10 17:20:41 +02:00
Julien Duponchelle
35b61bc891 1.4.0dev2 2015-07-10 15:50:19 +02:00
Julien Duponchelle
b149abbb23 1.4.0alpha1 2015-07-09 19:06:17 +02:00
Julien Duponchelle
536387ad8c Turn off Travis notification 2015-07-09 18:43:03 +02:00
grossmj
1628edbb8b Merge remote-tracking branch 'origin/unstable' into unstable 2015-07-09 10:30:43 -06:00
grossmj
39adbbdb27 Use os.path.abspath() for path returned by shutil.which(). 2015-07-09 10:30:14 -06:00
Julien Duponchelle
be49fa9b54 Reupload a clean iourc at each IOU start
Fix #485
2015-07-09 17:41:48 +02:00
Julien Duponchelle
aaed8435d1 Add 1.4.0alpha1 Changelog
Fix #519
2015-07-09 17:41:48 +02:00
Julien Duponchelle
c5bd406351 Fix test download project 2015-07-09 17:41:48 +02:00
Jeremy
4004caadc7 Fixes error in setup wizard if VMware isn't installed. Fixes #517. 2015-07-08 15:50:35 -06:00
Julien Duponchelle
1ac2a782c4 Fix Preferences menu always open the wizard on OSX
Fix #516
2015-07-08 19:17:36 +02:00
Julien Duponchelle
6887928bba Remove unused cloud code from the 1.4
I hope it will avoid strange bugs
2015-07-08 17:40:59 +02:00
Julien Duponchelle
1401537796 Fix File -> Download remote project doesn't seem to work.
Fix #512
2015-07-08 17:13:46 +02:00
Julien Duponchelle
e53f5ca175 Remove unused code 2015-07-08 16:54:55 +02:00
Julien Duponchelle
463f49586c Monitor config file in a dedicated thread.
This avoid warning in the console at startup

Fix #504
2015-07-08 11:49:07 +02:00
Julien Duponchelle
5a87098f95 Fix PyQT4 compatibility
Fix #505
2015-07-08 11:11:34 +02:00
Julien Duponchelle
da44ff05aa Add missing border_style property to json schema
Fix #510
2015-07-08 11:01:42 +02:00
grossmj
3839171d42 Use GNS3 VM if local server is not enabled for VPCS module. Fixes #511. 2015-07-07 23:06:09 -06:00
grossmj
8d9a009f89 Missing return when trying to download a remote project while using a temporary project. 2015-07-07 22:42:22 -06:00
grossmj
2c0a4cf7a7 Use the GNS3 VM by default in the VM wizards if local server is not activated in the module preferences and the VM is running. 2015-07-07 22:22:13 -06:00
grossmj
4b2269b668 Do not start the GNS3 VM if local server is chosen in the Setup wizard. 2015-07-07 21:48:27 -06:00
grossmj
3bfff093f8 Setup Wizard (to be tweaked). Implements #402. 2015-07-07 12:59:16 -06:00
grossmj
6d835a2068 Add timeouts to vmrun and VBoxManage commands. 2015-07-07 12:55:47 -06:00
grossmj
36398c54e0 Fixes exception when untick the VirtualBox Preference "Use the local server". Fixes #509. 2015-07-07 08:01:07 -06:00
grossmj
2a2777b22d Fixes GUI crash on unset vmrun_path variable. Fixes #507. 2015-07-07 07:58:48 -06:00
Jeremy
11dc69334d Merge remote-tracking branch 'origin/unstable' into unstable 2015-07-06 11:34:58 -06:00
Jeremy
c4c17aa115 Do not use default paths for vmrun and vboxmanage if they don't exist. 2015-07-06 11:34:52 -06:00
Julien Duponchelle
4b41c06dc4 Since travis didn't support Qt5 do not send alert 2015-07-06 17:00:53 +02:00
Julien Duponchelle
a9e27cd63f Fix Mac OS X: cx_Freeze app crashes on first start
Fix #495
2015-07-06 14:47:38 +02:00
Julien Duponchelle
0f6b4f2b32 Fix VMware remote server support on OSX 2015-07-06 14:38:25 +02:00
Julien Duponchelle
08877155e2 Dissallow VMware for local server on all Wizard page
Fix #501
2015-07-06 12:17:20 +02:00
Jeremy
7007f3ea44 Make sure a path is set before checking if it exists in preferences. 2015-07-05 20:13:11 -06:00
Jeremy
9419cce747 Warn users they cannot create VMware Fusion VMs on OSX. See #501. 2015-07-05 18:55:41 -06:00
Julien Duponchelle
033c884059 Revert "Add temporary debug for #495"
This reverts commit 99b0b65e89.
2015-07-05 23:38:31 +02:00
Julien Duponchelle
99b0b65e89 Add temporary debug for #495 2015-07-05 23:22:03 +02:00
Julien Duponchelle
67042470f3 Fix server not log on OSX not written in ~/.config/gns3.net
Fix #497
2015-07-05 21:21:51 +02:00
Jeremy
7c5388ee71 More checks on local paths in the preferences. 2015-07-04 12:18:12 -06:00
Julien Duponchelle
96634ece3f Fix getting started setting not migrate from 1.3
Fix #494
2015-07-04 11:24:57 +02:00
Jeremy
ee9ea92a11 Adds -no-kvm to the ASA template and ignore -no-kvm on platforms other than Linux. Should resolve #472. 2015-07-03 23:35:42 -06:00
Jeremy
246e9f7e3f Do not save the GNS3 VM host since it is retrieved every time we start. 2015-07-03 23:27:56 -06:00
Jeremy
fc43f89d9e Explicitly set the acceleration method to tcg for ASA templates. Should resolve #472. 2015-07-03 16:10:07 -06:00
Jeremy
be75dc95a3 Show an error if the console port range overlaps the default VNC port range (5900 to 6000) in the server preferences. 2015-07-03 16:07:19 -06:00
Julien Duponchelle
6bb0f7b902 Fix tests 2015-07-03 22:57:14 +02:00
Julien Duponchelle
6178c56606 Migrate 1.3 configuration file
Fix #492
2015-07-03 22:54:48 +02:00
Jeremy
0a2ca923ee Remove running VBoxManage as another user option (root for instance). 2015-07-03 14:37:17 -06:00
Jeremy
5adc4cb437 Merge remote-tracking branch 'origin/unstable' into unstable 2015-07-03 13:09:16 -06:00
Jeremy
28d4371f4d Fixes #481. 2015-07-03 13:08:47 -06:00
Julien Duponchelle
d343bbe1ac Fix an issue with configuration migration on OSX 2015-07-03 20:49:13 +02:00
Julien Duponchelle
c6a6163aec Add chicken VNC for OSX 2015-07-03 20:48:48 +02:00
Julien Duponchelle
be60a37a29 Check if an insecure HTTPS certificate has not changed
Fix #488
2015-07-03 15:51:45 +02:00
Julien Duponchelle
b3d42866b7 Fix error message when you can't bind to the local ip 2015-07-03 15:20:25 +02:00
Julien Duponchelle
9633fb659a Fix tests when you play wih your local ip 2015-07-03 15:14:30 +02:00
Julien Duponchelle
fab637f5ae Minor fix for error loggings when port conflict 2015-07-03 15:07:07 +02:00
Julien Duponchelle
edcd991659 Allow user to change the location of the config file 2015-07-03 11:22:41 +02:00
Julien Duponchelle
84f41b9c2f Always store exception with the config 2015-07-03 11:15:06 +02:00
grossmj
e7a61f07a2 GNS3 VM not headless by default. 2015-07-02 17:16:34 -06:00
Julien Duponchelle
57616ffd83 Fix crash at Windows launch 2015-07-02 16:38:56 +02:00
Julien Duponchelle
ea002e6634 Fix error at GNS3 VM launch about the missing version
Fix #484, https://github.com/GNS3/gns3-server/issues/250
2015-07-02 16:29:26 +02:00
Julien Duponchelle
24574360a0 Path fixing 2015-07-02 15:35:32 +02:00
Julien Duponchelle
e4dff4916b Fix A gns3.net folder is created in config on MacOS with the logs
Fix #480
2015-07-02 11:18:28 +02:00
grossmj
bd1ff4c954 Restore missing debug level. 2015-07-01 16:16:08 -06:00
Julien Duponchelle
563c762756 Add the frozen path to the binary lookup path.
This avoid issue when the current working directory is different.
And avoid special case in the code for searching the binary.

Fix #479
2015-07-01 15:55:54 +02:00
Julien Duponchelle
6c6bd65969 Fix resources path lookup 2015-07-01 15:05:29 +02:00
Julien Duponchelle
e2dbd5216d Merge branch 'master' into unstable 2015-07-01 14:32:04 +02:00
Julien Duponchelle
959a05643f Fix crash when the vmware command is not available 2015-07-01 14:28:02 +02:00
Julien Duponchelle
3e0f33859a Support self update of the application
Fix #456
2015-07-01 11:54:30 +02:00
Julien Duponchelle
b70615c19c Due to the migration to cx_freeze darwin and windows share
the same path for resources
2015-07-01 11:54:30 +02:00
Julien Duponchelle
f6956baf89 Use the same location for the server config on GUI and server
Fix https://github.com/GNS3/gns3-server/issues/249
2015-07-01 09:55:40 +02:00
Julien Duponchelle
47cd7cf2a2 Catch invalid reply from the remote server
Fix #477
2015-07-01 09:30:25 +02:00
grossmj
a1d6d17685 Option to adjust the local server IP address to be in the same subnet as the GNS3 VM. 2015-06-30 22:58:36 -06:00
grossmj
fe768a650d Automatically determine the VMware host type. 2015-06-30 22:56:19 -06:00
grossmj
d9ba282024 Adjust layout in Qemu VM wizard. 2015-06-30 17:21:03 -06:00
grossmj
1b48cc99e5 Adjust spacing in Qemu image wizard. 2015-06-30 17:17:16 -06:00
Jeremy
8740e20c90 Support to insert SVG images. 2015-06-29 17:55:05 -06:00
Julien Duponchelle
93a2cdf4bf Warning about deprecated ASA on Qemu
Fix #327
2015-06-29 15:23:14 +02:00
Julien Duponchelle
0faa4e62f0 Fix segfault at exit on OSX
The fix as two part
1) We restore the IO at exit, because otherwise a print on console
crash due to the fact the console as already disapear
2) We force a Garbage Collect it seem to clean the pyqt
references and allow QT to properly exit

Fix #475
2015-06-29 12:23:09 +02:00
Julien Duponchelle
78e97e9731 Create Qemu image from the Qemu new VM wizard
Fix #389
2015-06-29 11:11:43 +02:00
Julien Duponchelle
d59be759bd Support relative path for Default IDLE PC
I also move the code to the Dynamips module and add test for it.

Fix #471
2015-06-26 16:00:06 +02:00
Julien Duponchelle
2df78eb436 Display crash event from qemu in the console
Fix #473
2015-06-26 15:11:16 +02:00
Julien Duponchelle
3f132a759f Drop the slider from Qemu Wizard because he was buggy
Fix #470
2015-06-25 16:03:10 +02:00
Julien Duponchelle
b87244bf9a Bug fix and graphical improvement of qemu_image_wizard
The look & feel is more the look & feel of other wizards.
Resize is correctly supported.

Fix #470
2015-06-25 15:09:32 +02:00
Julien Duponchelle
6d826001cc Allow user to open the file manager
Fix #260
2015-06-25 10:02:45 +02:00
grossmj
2de4d36c9f Restart the GNS3VM if required in preferences. 2015-06-24 23:27:27 -06:00
grossmj
ef01212ce8 Moves KVM setting to Qemu preferences. 2015-06-24 22:46:21 -06:00
grossmj
9fa8c36b5f Start the GNS3 VM if enabled in the preferences. Fixes #468. 2015-06-24 21:51:37 -06:00
grossmj
a4973616b4 Adds console_type to topology.json 2015-06-24 19:10:57 -06:00
grossmj
a8dd2ed2da VNC console support for Qemu VMs. Implements #447. 2015-06-24 19:09:03 -06:00
Julien Duponchelle
2766667d16 Move common code of the setupCallback to the base class VM
This will allow to add common initialization code more easily.
2015-06-24 18:35:07 +02:00
Julien Duponchelle
a7e7b9a3ca If VMWware host type exist we use it.
Related to #467
2015-06-24 17:01:46 +02:00
Julien Duponchelle
7df272fd4a Support auth for the GNS3 VM
Move all the synchronous HTTP code to HTTP Client

Fix #461
2015-06-24 16:33:40 +02:00
Julien Duponchelle
cd694366ed Refresh the list of VM when I click on the GNS3 VM tab
Fix #466
2015-06-24 15:02:28 +02:00
Julien Duponchelle
4a9fb62663 Fix startup of the GNS3VM
Fix #467
2015-06-24 14:49:39 +02:00
Julien Duponchelle
8c7144205b Hide auto generated user name in url 2015-06-24 12:11:51 +02:00
Julien Duponchelle
f4057d4c2c Keep the old gns3.net directory on Mac for user testing 1.3/1.4
Fix #451
2015-06-24 12:02:46 +02:00
Julien Duponchelle
ad5de8c84c Change the location of the config file on OSX
Fix #451
2015-06-24 11:55:36 +02:00
grossmj
15f414cae3 Adds first port name option (for management interfaces). Completes #309. 2015-06-23 22:18:39 -06:00
Jeremy
54d01d2ffd Support for custom port names. #309. 2015-06-23 19:18:09 -06:00
Julien Duponchelle
f8e87c5aa1 Add a force quit button when closing the app
Fix #438
2015-06-23 21:58:08 +02:00
Julien Duponchelle
090a85bdd5 Fix Crash report sending errors when no reliable Internet connection
Fix #403
2015-06-23 19:26:30 +02:00
grossmj
403611443f Merge remote-tracking branch 'origin/unstable' into unstable 2015-06-23 10:53:01 -06:00
grossmj
82b14a14e0 Force item children to redraw because of a problem with QGraphicsEffect. 2015-06-23 10:52:50 -06:00
Julien Duponchelle
a0789b45e4 Test for 12975b1ecf
Fix #462
2015-06-23 18:42:44 +02:00
Jeremy
12975b1ecf Preserve settings we don't use. 2015-06-23 10:20:28 -06:00
Julien Duponchelle
59de1212cb Basic auth support for remote servers
Fix #391
2015-06-23 16:54:09 +02:00
grossmj
cc8246b474 Merge remote-tracking branch 'origin/unstable' into unstable 2015-06-23 07:34:38 -06:00
grossmj
f13a91e83e Fixes versions. 2015-06-23 07:34:25 -06:00
Julien Duponchelle
598aae8ef1 PEP 8 2015-06-23 15:27:46 +02:00
Julien Duponchelle
fe5414bdf4 Ensure password is written to disk 2015-06-23 10:29:23 +02:00
Julien Duponchelle
fd40289887 Fix version number 2015-06-23 10:14:40 +02:00
Julien Duponchelle
225b8aa63a Merge branch 'master' into unstable 2015-06-23 09:46:08 +02:00
Julien Duponchelle
e63bbe734c Fix topology schema for old topologies 2015-06-23 09:17:32 +02:00
grossmj
8c76fb6f7c Symbol selection dialog supports pixmap node items. 2015-06-22 23:17:22 -06:00
grossmj
617ed0a3cd Fixes #449 (cannot turn off the local server). 2015-06-22 21:45:17 -06:00
grossmj
e32e7dd828 Save custom symbols in the project-files directory for projects. 2015-06-22 21:28:13 -06:00
grossmj
d6ba027ae7 Adds symbol overview in tooltips for all symbol text fields. 2015-06-22 20:54:54 -06:00
grossmj
1ea4a7c113 Symbol and category can be changed for VPCS VM template. 2015-06-22 17:56:31 -06:00
grossmj
8d7e161662 Rename symbols: *.normal.svg to *.svg 2015-06-22 17:30:23 -06:00
grossmj
332b04d640 Remove "hover symbol" references. 2015-06-22 16:23:18 -06:00
grossmj
e7af8305c2 Remove SVG icons used in hover events. 2015-06-22 16:04:13 -06:00
grossmj
edffba3496 Support for custom symbols. Still some work to do on the QGraphicsEffect. Implements #388. 2015-06-22 15:56:29 -06:00
Julien Duponchelle
88834250c5 1.3.8dev1 2015-06-22 20:22:31 +02:00
Julien Duponchelle
0da15c21e6 Update changelog 2015-06-22 19:50:21 +02:00
grossmj
3076f98127 Merge remote-tracking branch 'origin/master' 2015-06-22 11:42:40 -06:00
grossmj
5a7f52b41f Makes sure Hub Ethernet port names are string. 2015-06-22 11:42:24 -06:00
grossmj
f403ff7776 Makes sure Hub Ethernet port names are string. 2015-06-22 11:39:35 -06:00
Julien Duponchelle
57998195f6 1.3.7 2015-06-22 19:04:10 +02:00
Julien Duponchelle
e873150542 Repare generation of password for local server
More generally this support dictonnary in dictionnary in
the config.

Fix #452
2015-06-22 17:22:29 +02:00
Julien Duponchelle
73440be270 Upgrade Travis to the last pyqt build 2015-06-22 15:11:56 +02:00
Julien Duponchelle
e8caa8853e Fix SSH support broken when adding the ram_limit
Test suite is Green again
2015-06-22 15:02:36 +02:00
Julien Duponchelle
4d63643fbf Fix Zoom reset is broken
Fix #448
2015-06-22 12:24:43 +02:00
Julien Duponchelle
c632303fd6 Add progressText argurment to HTTP query
When you load the VirtualBox VMs instead of
Waiting for local server you see:
List VirtualBox VMs

Related to #359
2015-06-22 12:13:34 +02:00
Julien Duponchelle
06596d8626 Hide the Load Balance settings when choosing GNS3VM
Fix #441
2015-06-22 11:24:20 +02:00
grossmj
e0a47b050a Avoid reload config loops. 2015-06-21 12:19:07 -06:00
grossmj
55bd9bbc7e RAM usage based load balancing. #419. 2015-06-21 11:49:49 -06:00
grossmj
a4c47b920c Creates a new "Servers" config section and moves "LocalServer", "RemoteServers" and "GNS3VM" under it. 2015-06-20 19:25:11 -06:00
grossmj
25355596bb Move "RecentFiles" and "GUI" settings under MainWindow settings. 2015-06-20 16:10:33 -06:00
grossmj
a40d128704 Fixes cosmetic issue: QSettings().fileName() returns paths containing slashes on Windows. 2015-06-20 15:15:16 -06:00
grossmj
2f0ab09250 Change the default configs directory to the new default location. 2015-06-20 15:13:51 -06:00
Julien Duponchelle
6be425de4d Avoid configuration reload loops
This avoid false detection of configuration file
changed.

And avoid to write partial settings to the configuration
file.

Fix #406
2015-06-20 23:08:19 +02:00
grossmj
aa55b984a2 Backport: support spaces in the local server log path. 2015-06-20 14:51:39 -06:00
grossmj
35725b2324 Support spaces in the local server log path. 2015-06-20 14:48:07 -06:00
grossmj
bb4a3487a2 Backport: fixes issue when setting the local server settings. 2015-06-20 11:42:39 -06:00
grossmj
2f51f985d8 Round-Robin load balancing support. #419. 2015-06-20 11:40:47 -06:00
Jeremy Grossmann
bacdca038e Merge pull request #446 from GNS3/progress_dialog_refactor
Refactor of the progress dialog.
2015-06-19 12:18:56 -07:00
grossmj
f80e190e22 Moves base configs to a dedicated directory (default is ~/GNS3/configs). Fixes #420. 2015-06-19 13:09:50 -06:00
grossmj
024aec1891 Fixes local server restart from the preferences. 2015-06-19 12:16:25 -06:00
Julien Duponchelle
b80f6cc507 Auto upload image if missing on remote server
Fix #378
2015-06-19 18:16:57 +02:00
Julien Duponchelle
be11046cfc Refactor of the progress dialog
setWindowModality(Qt.Qt.ApplicationModal) allow to have the progress
dialog modal for the app

Creation of a context block where you can temporary change the
behavior of the progress dialog.

Fix #359
2015-06-19 12:26:29 +02:00
Julien Duponchelle
0a0522d92d Fix a crash when uploading images 2015-06-19 12:17:01 +02:00
Jeremy
f436a34474 Fixes issue when looking vmrun on Windows. 2015-06-18 18:43:43 -06:00
Jeremy
7ab3884cb9 ACPI shutdown support for VMware VMs. Fixes #436. 2015-06-18 15:02:31 -06:00
Jeremy
b616be8c0e Fixes #442. 2015-06-18 14:45:00 -06:00
Julien Duponchelle
65431c462f Fix a typo in GNS3VM preferences
Fix #440
2015-06-18 14:44:28 +02:00
Julien Duponchelle
bc6ae0e773 Fix update issues with the configuration
Previoulsy we used a reference to settings instead a new one
this mean you can modify the settings and when writting the
settings we can't detect the configuration has changed.

Fix #431
2015-06-18 12:50:46 +02:00
Julien Duponchelle
5698b2eab9 Add timestamps to gns3_gui.log
Fix #426
2015-06-18 12:08:21 +02:00
Julien Duponchelle
4b1ff7deb5 Fix TypeError: 'NoneType' object is not callable in http_client
Fix #439
2015-06-18 11:59:14 +02:00
Julien Duponchelle
327c0d7a2e Fix NameError: name 'QtGui' is not defined
Fix #433
2015-06-18 11:57:50 +02:00
Julien Duponchelle
90522914c0 Fix a crash about server_name not a module 2015-06-18 11:34:29 +02:00
Julien Duponchelle
cf44a36153 Fix topology test 2015-06-18 11:30:01 +02:00
Julien Duponchelle
ba23cfdaca Store MD5 of images in topology
Fix #390
2015-06-18 11:26:29 +02:00
Julien Duponchelle
a85888bcbd Update crash report key for 1.3.7 2015-06-18 11:26:29 +02:00
grossmj
3d8c25159d Do not load settings that the GUI doesn't use. 2015-06-18 11:25:56 +02:00
grossmj
543f73bf7a Bump version to 1.3.7.dev1 2015-06-18 11:25:37 +02:00
Julien Duponchelle
4130082a8d 1.3.6 2015-06-18 11:24:47 +02:00
grossmj
692815713b Ubridge is not in 1.3.x 2015-06-18 11:24:35 +02:00
Julien Duponchelle
14bef07d25 1.3.6dev1 2015-06-18 11:24:03 +02:00
Julien Duponchelle
e9c69a118c 1.3.5 2015-06-18 11:23:39 +02:00
grossmj
275faea616 Prevent the local server to restart in Preferences if no settings have been changed. 2015-06-18 11:23:11 +02:00
Julien Duponchelle
f4268bb447 Do not crash in a very rare case on Windows when stoping local server
Fix #430
2015-06-18 11:21:39 +02:00
grossmj
35eeae7c58 Support to open projects that use the GNS3 VM. 2015-06-17 23:01:18 -06:00
Jeremy
ed04df26f8 Auto start and stop for VirtualBox GNS3 VM completed. Completes #387. 2015-06-17 19:23:19 -06:00
Jeremy
79efaad817 Fixes #427. 2015-06-17 18:43:23 -06:00
Jeremy
1075745439 GNS3 VM works from the GUI. 2015-06-17 18:38:22 -06:00
Jeremy
2f7255301d VMware topology validation. 2015-06-17 17:42:49 -06:00
Jeremy
fc60d50560 Comments code preventing to load projects. 2015-06-17 17:35:56 -06:00
Jeremy
488d32974f Find vmrun on Windows. 2015-06-17 17:05:58 -06:00
Jeremy
bdd12b262e Revert: do not load settings that the GUI doesn't use since it breaks something. 2015-06-17 15:06:39 -06:00
grossmj
ec8e645679 Merge remote-tracking branch 'origin/master' 2015-06-17 15:06:32 -06:00
grossmj
a239c923a3 Revert: do not load settings that GUI doesn't use since it breaks something. 2015-06-17 15:06:21 -06:00
Jeremy
e2fa8b3199 Port from 1.3.7: do not load settings that the GUI doesn't use. 2015-06-17 14:25:37 -06:00
Jeremy
2128f46165 Port from 1.3.7: fixes WICs are not displayed correctly. 2015-06-17 14:23:55 -06:00
Julien Duponchelle
1378cab008 Update crash report key for 1.3.7 2015-06-17 09:29:04 +02:00
Julien Duponchelle
65aca8ab76 Fix a crash with Python 3.3
Fix #435
2015-06-17 09:21:23 +02:00
grossmj
9db42c9783 Fixes WICs are not displayed correctly. Fixes #434. 2015-06-16 21:17:08 -06:00
grossmj
d9e551031d Do not load settings that the GUI doesn't use. 2015-06-16 21:09:44 -06:00
grossmj
554a163d7d Bump version to 1.3.7.dev1 2015-06-16 14:39:20 -06:00
Julien Duponchelle
858a59568e 1.3.6 2015-06-16 21:55:25 +02:00
grossmj
e0eabbebd1 Merge remote-tracking branch 'origin/master' 2015-06-16 12:39:47 -06:00
grossmj
1b5c675711 Ubridge is not in 1.3.x 2015-06-16 12:39:35 -06:00
Julien Duponchelle
bf4daff685 1.3.6dev1 2015-06-16 19:12:22 +02:00
Julien Duponchelle
d669b19906 1.3.5 2015-06-16 19:04:01 +02:00
grossmj
95e665a917 Prevent the local server to restart in Preferences if no settings have been changed. 2015-06-16 11:00:04 -06:00
grossmj
4557094716 Merge remote-tracking branch 'origin/master' 2015-06-16 10:49:11 -06:00
grossmj
eb8e585c8c Save server logs to a file. 2015-06-16 10:48:38 -06:00
Julien Duponchelle
5052d1263b Do not crash in a very rare case on Windows when stoping local server
Fix #430
2015-06-16 16:38:43 +02:00
grossmj
14bd2c6a3b Support to shutdown the GNS3 VM when closing GNS3. 2015-06-14 17:11:39 -06:00
grossmj
109ee591c1 Save local server logs to a logfile. 2015-06-14 16:02:50 -06:00
grossmj
c67cf56dc5 Prepare the GNS3 VM to be used in projects. 2015-06-14 16:01:34 -06:00
grossmj
727dcc149d Support to automatically start the GNS3 VM and retrieve the guest IP address. 2015-06-14 14:24:18 -06:00
grossmj
b450178444 Fixes issue with socket not properly closed. 2015-06-14 14:21:01 -06:00
grossmj
23e281689a Restore missing IPv6 support code. 2015-06-13 19:54:40 -06:00
Julien Duponchelle
f96eb630d1 Use the native glob.escape function
Fix #424
2015-06-12 15:12:37 +02:00
Julien Duponchelle
7cd16c7063 Merge branch 'master' into unstable 2015-06-12 15:11:24 +02:00
Julien Duponchelle
4734d2645f Escape usage to glob
Fix #424
2015-06-12 15:09:13 +02:00
Julien Duponchelle
87a04193f9 Fix QIODevice::read: device not open
Fix #360
2015-06-12 14:22:52 +02:00
Julien Duponchelle
ea8326ca24 Fix QMessageBox.NoButton): argument 1 has unexpected type 'Servers'
Fix #423
2015-06-12 13:43:39 +02:00
Julien Duponchelle
5c196d7e47 Fix QMessageBox.NoButton): argument 1 has unexpected type 'Servers'
Fix #423
2015-06-12 13:40:44 +02:00
grossmj
8db1b230d4 Merge remote-tracking branch 'origin/unstable' into unstable 2015-06-11 22:55:54 -06:00
grossmj
f92e98d587 Remove duplicate entries in node dictionaries. 2015-06-11 22:55:42 -06:00
Julien Duponchelle
9b3ed76fb0 SSL support
Fix #385
2015-06-11 21:16:57 +02:00
Julien Duponchelle
91780f0b9c Merge branch 'master' into unstable 2015-06-11 19:50:25 +02:00
Julien Duponchelle
0f7f7946cd More topology corruption check thanks again to Bernhard Ehlers 2015-06-11 18:37:14 +02:00
Julien Duponchelle
c4a0037956 Catch the sigint and sigterm signal and do a clean exit
Fix #374
2015-06-11 16:22:28 +02:00
Julien Duponchelle
586492fc92 Support saving qemu arch in topologies
Fix #401
2015-06-11 16:12:28 +02:00
Julien Duponchelle
cfe34628fa Support more topologies in JSON schema 2015-06-11 15:52:41 +02:00
Julien Duponchelle
1e2b7c7e02 Try to install Qt5 on Travis 2015-06-11 11:23:15 +02:00
Julien Duponchelle
c12a91ee5f Fix crash when you drag nodes with the shift key
Fix #421
2015-06-11 11:20:15 +02:00
Julien Duponchelle
c93a2dcb1c Fix ugly text when connecting to local GNS3 server
Fix #398
2015-06-11 11:13:50 +02:00
Julien Duponchelle
9baa529200 Use the correct qmake binary for travis 2015-06-11 10:59:15 +02:00
Julien Duponchelle
29bf1e5dc4 Schemas cleanup 2015-06-11 10:37:01 +02:00
Julien Duponchelle
0f1b78e1a5 More supported topology in corruption check
Thanks to @ehlers
2015-06-11 10:27:34 +02:00
Julien Duponchelle
d03820bf91 Fix errori in IOU config export 2015-06-11 09:32:31 +02:00
Jeremy
adbf7aeb42 Graphical base to manage the GNS3 VM. 2015-06-10 17:46:39 -06:00
Julien Duponchelle
c3cadf0db3 Allow to turn on/off auth 2015-06-10 23:13:45 +02:00
Jeremy
b57bf29247 Removes settings types (was used for QSettings). 2015-06-10 15:11:19 -06:00
Julien Duponchelle
c5f1289aee Turn on/off local server auth
Fix #418
2015-06-10 23:09:19 +02:00
Julien Duponchelle
4a96468e42 Fix add image to topology
Fix #417
2015-06-10 17:49:54 +02:00
Julien Duponchelle
272c7850d7 Fix local server auto start
Fix #415
2015-06-10 17:39:50 +02:00
Julien Duponchelle
7466bda816 Change the location of the topology json schema
Fix #415
2015-06-10 17:04:38 +02:00
Julien Duponchelle
c202399eb6 Merge branch 'master' into unstable 2015-06-10 16:43:35 +02:00
Julien Duponchelle
3c046020ef Fix topology check for 3725
Fix #415
2015-06-10 16:22:28 +02:00
Julien Duponchelle
d4ffc21a11 Fix 'ValueError' object has no attribute 'errno' in IOS decompress
Fix #412
2015-06-10 11:54:24 +02:00
Julien Duponchelle
aefb061f22 Fix error if communication with the update server is intercepted by a
third party.

Fix #413
2015-06-10 11:48:20 +02:00
Julien Duponchelle
af3ab140bd Catch extraction error and exit
Fix #372
2015-06-10 11:38:37 +02:00
Julien Duponchelle
9d9d43a249 Add a specific icon for VPCS
Fix #410
2015-06-10 11:04:35 +02:00
Julien Duponchelle
5045447bc6 Ensure no colored log output on Windows 2015-06-10 10:33:34 +02:00
Jeremy
a9772dd313 Remember previously chosen directories for QFileDialog calls. Fixes #349. 2015-06-09 17:43:50 -06:00
Julien Duponchelle
675d161df0 Fix auth errors if you change the local server IP
Fix #409
2015-06-09 12:11:54 +02:00
Julien Duponchelle
fe45fd263b Support auth for local server
Fix https://github.com/GNS3/gns3-server/issues/222
2015-06-09 11:36:20 +02:00
Julien Duponchelle
2e7d8299a1 Ensure no colored log output on Windows 2015-06-09 10:04:18 +02:00
Julien Duponchelle
59999abb61 Merge pull request #399 from GNS3/json_schema
JSON schema for checking topologies
2015-06-09 09:32:36 +02:00
grossmj
23a42b7c48 Enable KVM acceleration option. 2015-06-08 14:51:06 -06:00
grossmj
8bda1fe719 Removes some unneeded QtGui imports. 2015-06-08 14:29:42 -06:00
grossmj
207e55e869 Apply the result of the auto Idle-PC feature to other routers with the same IOS image. 2015-06-08 11:55:41 -06:00
grossmj
a09b8f1762 Fixes issues when setting MAC address for a Qemu VM or IOS router. 2015-06-07 22:18:41 -06:00
grossmj
28f23ae595 Fixes issue with Node Properties dialog when only 1 node is selected. 2015-06-07 22:17:39 -06:00
Jeremy Grossmann
da0dc31ed0 Merge pull request #405 from boenrobot/qemuImgPatch1
Made Qemu image wizard text agnostic
2015-06-07 14:38:46 -06:00
Julien Duponchelle
6a9873dbaa Fix an issue with partial config written 2015-06-07 22:31:06 +02:00
grossmj
c68d311f92 Merge remote-tracking branch 'origin/unstable' into unstable 2015-06-07 14:16:39 -06:00
grossmj
c148fa9000 Fixes style for QListWidget and QComboBox. Fixes #218. 2015-06-07 14:16:15 -06:00
Julien Duponchelle
26fc48ce14 Improve config change autodetect
Related to #406
2015-06-07 22:04:37 +02:00
grossmj
0eb7174183 Show in file manager (#260: to complete using the VM directory instead). 2015-06-07 11:53:53 -06:00
grossmj
248e8750e1 Open/save dialog is opened in project folder when importing/exporting configs. Fixes #299. 2015-06-07 11:23:33 -06:00
grossmj
6c240fc5d3 Adds debug to help with #368 2015-06-07 11:01:38 -06:00
Vasil Rangelov
def3d617b0 Made the Qemu image wizard text-agnostic (uses form element names as indicators, instead of their texts). 2015-06-07 17:48:26 +03:00
grossmj
c49314e755 IPv6 support. 2015-06-06 21:37:34 -06:00
grossmj
18a80d4fdd Fixes issue with QFileDialog.getSaveFileName() returning a tuple in PyQt5. 2015-06-06 15:20:49 -06:00
grossmj
195e136798 Adds contributor names to the about dialog. 2015-06-06 15:19:45 -06:00
grossmj
606e702e6f Import/Export support for IOU nvrams. 2015-06-06 15:15:03 -06:00
grossmj
99d3925b6c Merge remote-tracking branch 'origin/master' 2015-06-05 14:57:20 -06:00
grossmj
aed7a6fbf3 Merge remote-tracking branch 'origin/master' into unstable 2015-06-05 14:56:15 -06:00
grossmj
1d584235e0 Fixes issue with default router settings for templates. 2015-06-05 14:55:43 -06:00
grossmj
bbb79bba0f Option to drop nvram & disk files for IOS routers in order to save disk space. 2015-06-05 14:54:22 -06:00
Julien Duponchelle
731a838c16 Another travis fix... 2015-06-05 18:05:25 +02:00
Julien Duponchelle
1a55c472e0 Fix PyQT download link 2015-06-05 17:57:42 +02:00
Julien Duponchelle
222b476d84 Add travis debug 2015-06-05 17:49:46 +02:00
Julien Duponchelle
0e42f31b88 Fix Travis PyQT5 2015-06-05 14:43:49 +02:00
Julien Duponchelle
d5b3f605f3 Fix IOU server edit
Fix #396
2015-06-05 14:41:20 +02:00
Julien Duponchelle
4e6c354ff9 Display a proper message if you use a remote server started with --local
Fix https://github.com/GNS3/gns3-server/issues/207
2015-06-05 11:51:34 +02:00
Julien Duponchelle
7203165d88 Catch zlib error when uncompress IOS
Fix #394
2015-06-05 11:32:43 +02:00
Julien Duponchelle
17471db248 JSON schema for checking topologies
Support:
* IOU
* Dynamips
* VPCS
* VirtualBox
* Qemu

VMWare is not supported

Tests schema are available in:
tests/schemas

And the test suite is auto generated from this directory you
can take a look to test_topology_check

Fix #342,#392,#384
2015-06-04 19:55:01 +02:00
Julien Duponchelle
e2cdff3604 Drop python 3.3 build 2015-06-04 10:48:18 +02:00
Julien Duponchelle
118b1a039b Merge branch 'master' into unstable 2015-06-04 10:46:27 +02:00
Julien Duponchelle
127ead0518 Raise error if we pass non string to Port name
Fix #393
2015-06-04 10:44:49 +02:00
grossmj
ea8119f3ad Replace RuntimeError by SystemExit. 2015-06-03 19:58:58 -06:00
grossmj
9b0f548336 Support for base MAC address for Qemu VMs. 2015-06-03 14:52:49 -06:00
grossmj
e8a7c15fee Drop Python 3.3 2015-06-03 12:08:24 -06:00
Julien Duponchelle
6055127118 Fix tests after merge 2015-06-03 18:56:44 +02:00
Julien Duponchelle
81e4a402f2 Merge branch 'master' into unstable 2015-06-03 18:45:17 +02:00
Julien Duponchelle
ca975e4f94 Fix: _findDynamips() takes 0 positional arguments but 1 was given
Fix #382
2015-06-03 18:35:22 +02:00
Julien Duponchelle
5bf0f08f25 Add basic auth support for local server 2015-06-03 16:23:14 +02:00
grossmj
2e06972161 ACPI shutdown support for Qemu VMs. 2015-06-02 22:33:38 -06:00
grossmj
d6f26f78a5 ACPI shutdown support for VirtualBox VMs. 2015-06-02 16:30:35 -06:00
Julien Duponchelle
8eb4c1e7c1 Update crash report key 2015-06-02 20:25:43 +02:00
Julien Duponchelle
3b4f0f67f7 1.3.5dev1 2015-06-02 20:04:58 +02:00
Julien Duponchelle
bf1436fdff Version 1.3.4.0 2015-06-02 19:49:19 +02:00
Julien Duponchelle
0bd47c8c72 1.3.4 2015-06-02 19:46:20 +02:00
Julien Duponchelle
7599ec6248 Catch OSError in restore snapshots
Fix #383
2015-06-02 16:19:29 +02:00
Julien Duponchelle
266df9bf71 Fix: _findDynamips() takes 0 positional arguments but 1 was given
Fix #382
2015-06-02 16:08:20 +02:00
Julien Duponchelle
69b937321c 1.3.4 Changelog 2015-06-02 14:48:24 +02:00
grossmj
ae53634f48 Catch exception in snapshot dialog. 2015-06-01 21:54:08 -06:00
Jeremy
09d8e1ce6b Rename node configurator to node properties. 2015-06-01 16:46:53 -06:00
Jeremy
5751a5c7e5 Bump version to 1.3.4.dev2 2015-06-01 16:29:49 -06:00
Jeremy Grossmann
535069587e Merge pull request #381 from GNS3/doubleclick_label
If you doubleclick on a node label we open the change hostname dialog
2015-06-01 16:16:15 -06:00
Jeremy
f9550e93d3 Check if an IOS image is set in the IOS router template. 2015-06-01 16:00:48 -06:00
Julien Duponchelle
5318fbaca1 If you doubleclick on a label we open the change hostname dialog
Corresponding idea:
https://community.gns3.com/ideas/1426
2015-06-01 15:54:12 +02:00
Julien Duponchelle
5f251c296e Merge branch 'master' into unstable
Fix #379
2015-06-01 10:54:09 +02:00
Julien Duponchelle
be7278294a Fix crash in autostart if no link is present
Fix #380
2015-06-01 10:52:15 +02:00
grossmj
291f87e197 Support for VMware linked clones. 2015-05-30 20:26:38 -06:00
Julien Duponchelle
cca86141fd Avoid recursion issue in config loading 2015-05-29 16:48:01 +02:00
Julien Duponchelle
84c4fb825c Merge branch 'master' into unstable 2015-05-28 17:58:46 +02:00
Julien Duponchelle
cd9bb16f79 Ensure the version number is written in configuration file 2015-05-28 17:57:40 +02:00
Julien Duponchelle
79272be631 Fix a small display issue introduce by the addtion of the ubridge path 2015-05-28 17:25:59 +02:00
Julien Duponchelle
4b9d03fb59 Detect config file change and reload the nodes
You can edit the list of devices in the config file
and the file will be reloaded. Usefull also if you run
two gns3-gui.
2015-05-28 16:54:39 +02:00
Julien Duponchelle
3c95e88f08 Typo same player build again .... 2015-05-28 13:19:21 +02:00
Julien Duponchelle
73ed4fa6f3 Do not crash if cacert is not found 2015-05-28 12:56:01 +02:00
Julien Duponchelle
6451f580cb Search resources relative to executable, avoid issue if run from another directory 2015-05-28 12:38:56 +02:00
Julien Duponchelle
dcf8a4948b Enable fault handler only for dev 2015-05-28 12:18:55 +02:00
Julien Duponchelle
3458cec41e Enable fault handler for dev version 2015-05-28 12:15:33 +02:00
Julien Duponchelle
809008561f Fix merge crash 2015-05-28 12:15:16 +02:00
Julien Duponchelle
72d60e1227 Merge branch 'master' into unstable 2015-05-28 12:01:01 +02:00
Julien Duponchelle
8fc335718a Fix cacert path on OSX 2015-05-28 11:21:05 +02:00
Julien Duponchelle
e6129ad78b Fix GNS3 server location for OSX 2015-05-28 11:17:56 +02:00
grossmj
10802d6a2c Serial console implementation for VMware VMs. 2015-05-27 21:06:18 -06:00
grossmj
7b05d26d7e Removes legacy QSettings system because it can cause issues (1.3.x was the transition). 2015-05-27 19:54:45 -06:00
grossmj
fa8d67ebe1 Ubridge configuration support. 2015-05-27 19:37:31 -06:00
grossmj
0d320c26cd Adds contributor to the About dialog. 2015-05-27 17:18:59 -06:00
Jeremy Grossmann
96c0276a0e Merge pull request #353 from boenrobot/qemuImg
Qemu-img wizard.
2015-05-27 17:07:34 -06:00
Vasil Rangelov
3cc5a8ae5c Adds a wizard for creating images with qemu-img and mofified qemu configuration page to use it. 2015-05-28 00:21:01 +03:00
grossmj
0bb15cc6b8 Prevent users to add links to running Qemu VMs and start a capture on running VirtualBox VMs. 2015-05-27 13:56:27 -06:00
Julien Duponchelle
5b0ca03640 Fix tests 2015-05-27 18:48:18 +02:00
Julien Duponchelle
df5abad690 Fix resize issue in server page
Fix #375
2015-05-27 11:08:28 +02:00
Julien Duponchelle
549758d789 Fix segfault when starting OSX server with allow connection from
anywhere

Fix https://github.com/GNS3/gns3-server/issues/197
2015-05-27 10:29:32 +02:00
Jeremy
b49a850297 Fixes bug when editing c7200 templates. 2015-05-26 19:06:26 -06:00
Jeremy
5cc1c11f1d Merge remote-tracking branch 'origin/master' 2015-05-26 17:42:28 -06:00
Jeremy
1e5a596aae Fixes IOS decompression. Fixes #370. 2015-05-26 17:42:22 -06:00
Julien Duponchelle
c63d3a5b61 Topology auto start work for VPCS
Fix #371
2015-05-26 16:56:19 +02:00
grossmj
0b8f195249 Avoid moving .gns3_temporary files. 2015-05-26 09:54:17 +02:00
Julien Duponchelle
0af08cf578 Merge pull request #369 from GNS3/download_project
Download remote project with md5 support
2015-05-26 09:46:33 +02:00
Julien Duponchelle
dfe21c5b8c Prevent downloading a running project 2015-05-26 09:46:21 +02:00
Julien Duponchelle
f8c5da52f3 Download remote project with md5 support 2015-05-26 09:46:21 +02:00
Julien Duponchelle
20752bf48e Merge pull request #357 from GNS3/remote_ssh
Support connection to GNS3 servers via SSH tunnels
2015-05-26 09:45:12 +02:00
Julien Duponchelle
7778790bae SSH 2015-05-26 09:44:57 +02:00
grossmj
1b04a50836 Handles MemoryError. 2015-05-25 19:35:09 -06:00
grossmj
fccbc90307 Avoid moving .gns3_temporary files. 2015-05-25 16:58:51 -06:00
grossmj
c5895a7d21 Merge remote-tracking branch 'origin/unstable' into unstable 2015-05-21 21:49:32 -06:00
grossmj
9262c8527b VMware vmnets management almost complete. 2015-05-21 21:48:59 -06:00
Julien Duponchelle
32484570bb PEP8 2015-05-21 11:41:50 +02:00
Julien Duponchelle
f26f6c33d0 Fix tests 2015-05-21 11:39:32 +02:00
Julien Duponchelle
ec2db0594e Pep 8 2015-05-18 17:25:12 +02:00
Julien Duponchelle
a6f3f425c3 Qt4 -> Qt5 fix
Fix #363
2015-05-18 17:25:12 +02:00
Julien Duponchelle
54c1e64739 Typo 2015-05-18 16:35:43 +02:00
Julien Duponchelle
e6e88d2a2b Fix crash when a process listen on GNS3 port return an empty JSON
Fix #367
2015-05-18 12:32:15 +02:00
Julien Duponchelle
7cd229acf0 Another fix for the topology None error
Fix #366
2015-05-18 12:23:58 +02:00
Julien Duponchelle
891c540d60 Fix a rare crash in completion
Fix #364
2015-05-18 12:10:03 +02:00
Julien Duponchelle
ebd8f300d0 Fix crash when loading topology in rare conditions
Fix #365
2015-05-18 12:06:39 +02:00
Jeremy
4566fec58a Adapters for VMware VMs. 2015-05-15 19:09:48 -06:00
Jeremy Grossmann
a362206e55 Merge pull request #362 from AdrianSimionov/patch-1
Adds support for IOS-XRv under Qemu wizard.
2015-05-15 09:40:36 -06:00
Julien Duponchelle
a9543e50f2 Correct Qemu browse button errors introduce in 1.4dev1
Fix #356
2015-05-15 16:10:33 +02:00
Julien Duponchelle
06fc3e726a New crash report key 2015-05-15 13:38:23 +02:00
Julien Duponchelle
e19a2ac67a Bump to 1.3.4 2015-05-15 13:38:22 +02:00
Julien Duponchelle
5e28fb5246 Version 1.3.3 2015-05-15 13:37:55 +02:00
grossmj
2ad9fcf701 New inline help text for the idle-pc dialog. 2015-05-15 13:37:42 +02:00
Jeremy
427b38912f Reactivate auto idle-pc in device contextual menu + save a chosen idle-pc value in template. 2015-05-15 13:37:04 +02:00
Jeremy
5d4619a70a Adds name to the thank you section. 2015-05-15 13:36:33 +02:00
Jeremy
5e56f27e45 Prevent users to use VirtualBox linked clone VMs in temporary projects (for now). 2015-05-15 13:34:31 +02:00
Jeremy
92fca450f1 Fixes #337. 2015-05-15 13:34:31 +02:00
grossmj
e52f8bbbde Fixes VMware Fusion local server deactivation. 2015-05-14 21:03:54 -06:00
grossmj
94c6ccb549 Remove unused export.svg file. 2015-05-14 20:46:53 -06:00
grossmj
a8edd8ffb9 No support for VMware Fusion (for now). 2015-05-14 20:14:53 -06:00
Julien Duponchelle
52dee04e72 New crash report key 2015-05-14 19:25:36 +02:00
Julien Duponchelle
e34f030073 Bump to 1.3.4 2015-05-14 19:21:43 +02:00
Julien Duponchelle
2b86c24175 Version 1.3.3 2015-05-14 19:00:01 +02:00
Julien Duponchelle
298768f0cb Fix crash 2015-05-14 18:55:22 +02:00
grossmj
0ba01ddcdd New inline help text for the idle-pc dialog. 2015-05-14 10:13:05 -06:00
Jeremy
abc6ae2dca Reactivate auto idle-pc in device contextual menu + save a chosen idle-pc value in template. 2015-05-13 17:58:24 -06:00
Jeremy
e3d47e1e5d Adds name to the thank you section. 2015-05-13 17:19:51 -06:00
Jeremy
17dae79660 Prevent users to use VirtualBox linked clone VMs in temporary projects (for now). 2015-05-13 16:53:03 -06:00
Jeremy
d6336710b8 Merge remote-tracking branch 'origin/master' 2015-05-13 16:04:01 -06:00
Jeremy
ed25a4191d Fixes #337. 2015-05-13 16:03:56 -06:00
Julien Duponchelle
5723097cbe Fix crash 2015-05-13 23:27:09 +02:00
Jeremy
b566098a56 Adds missing icons in resources file. Fixes #343. 2015-05-13 13:47:46 -06:00
Jeremy
f8f34e46e3 Build resources. 2015-05-13 13:43:24 -06:00
Jeremy
9227831922 Adds missing icons. 2015-05-13 13:40:19 -06:00
Julien Duponchelle
625d4c951e Merge branch 'master' into unstable 2015-05-13 19:03:27 +02:00
Julien Duponchelle
38b600520f Capture error if the command is invalid
Fix #358
2015-05-13 17:23:17 +02:00
Julien Duponchelle
0fae016d15 Cleanup egg cache when exit 2015-05-13 14:33:59 +02:00
Julien Duponchelle
5cdc479029 Fix a crash when right click in create link mode 2015-05-13 14:03:39 +02:00
Adrian Simionov
d385585291 Removed -enable-kvm option as it is linux specific. 2015-05-12 12:57:26 +02:00
Adrian Simionov
248107bfb8 Add support for IOS-XRv under qemu wizard.
I used router SVG file but I propose to be changed to something more appropriate for IOS-XRv.
2015-05-12 10:54:43 +02:00
Julien Duponchelle
539e336fa1 Fix notification stream
Fix #352
2015-05-11 17:26:02 +02:00
Julien Duponchelle
8ab07563e0 Merge branch 'master' into unstable 2015-05-11 14:39:22 +02:00
Julien Duponchelle
74b4013002 Fix a crash in console when you used non UTF-8 terminal
Fix #351
2015-05-11 14:34:18 +02:00
Julien Duponchelle
eede8bdc2f Fix crash during save as
Fix #350
2015-05-11 14:28:20 +02:00
grossmj
7db0de7ccc Change title when exporting an IOS startup-config. 2015-05-10 20:39:10 -06:00
grossmj
487332df40 Some cleaning. 2015-05-10 20:26:43 -06:00
Julien Duponchelle
68d156c0e8 Merge pull request #338 from boenrobot/zoomFix
CTRL+Wheel fix
2015-05-10 21:23:19 +02:00
Julien Duponchelle
a9a5622525 Merge branch 'boenrobot-zoomFix' into unstable 2015-05-10 21:22:43 +02:00
Vasil Rangelov
9e02950844 Fixes the CTRL+Wheel zoom (Qt5 misses "orientation" for some reason, and has renamed delta() to angleDelta()). 2015-05-10 21:22:03 +02:00
Julien Duponchelle
a1730c9524 Fix node dropping
Fix #348
2015-05-10 21:19:35 +02:00
Julien Duponchelle
ed3257399b Merge pull request #302 from GNS3/upload_image
Upload image via the GUI
2015-05-10 20:47:06 +02:00
Julien Duponchelle
763f65cbbe Upload images from gui 2015-05-10 20:46:45 +02:00
grossmj
364cde1287 Updates bug reporting link. 2015-05-09 17:38:19 -06:00
grossmj
26675eac64 Fixes issue with callback in HTTP Client. 2015-05-09 17:32:46 -06:00
Jeremy Grossmann
4789be70fc Merge pull request #303 from GNS3/listen_for_notification
Listen for VM notifications.
2015-05-09 17:26:09 -06:00
Jeremy Grossmann
2b0168296f Merge pull request #341 from boenrobot/alphaText
Allows alpha channel for text color.
2015-05-09 12:06:42 -06:00
grossmj
c532d74f8b Removes analytics client on closing. 2015-05-08 18:35:18 -06:00
grossmj
2a8868e029 Replaced old style signal connections that don't work in PyQt5. 2015-05-08 18:22:07 -06:00
grossmj
7410abf895 Adds missing cloud configuration page. 2015-05-08 14:00:33 -06:00
Vasil Rangelov
86d0c3bfcb Text can now has an alpha channel, allowing for transparent or semi-transparent text. 2015-05-08 15:49:20 +03:00
Julien Duponchelle
fb14747a8b Merge branch 'master' into unstable 2015-05-08 14:40:12 +02:00
Jeremy
2303c54ac5 Bump version to 1.3.3.dev3 2015-05-07 11:52:17 -06:00
Julien Duponchelle
6762ce347d Release 1.3.3rc1 2015-05-07 16:00:32 +02:00
Julien Duponchelle
2e884339a8 Another fix for the link creation issue on OSX
https://community.gns3.com/message/26786
2015-05-07 15:43:13 +02:00
Julien Duponchelle
3bdb18a2b4 Another broken pipe error catched for OSX
Fix https://github.com/GNS3/gns3-server/issues/166
2015-05-07 15:35:15 +02:00
Julien Duponchelle
aaf2b7e206 Prevent a topology made for next version to be open in previous version
Fix #345
2015-05-07 10:50:40 +02:00
Julien Duponchelle
ef7a711f07 Check if the local server is really a local server
Fix #344
2015-05-07 10:33:26 +02:00
Julien Duponchelle
d11fbc1069 Merge branch 'boenrobot-singleNodeConfig' into unstable 2015-05-07 09:52:40 +02:00
Julien Duponchelle
b48d8d4372 Merge branch 'singleNodeConfig' of https://github.com/boenrobot/gns3-gui into boenrobot-singleNodeConfig 2015-05-07 09:49:54 +02:00
Julien Duponchelle
e257a64772 Merge branch 'boenrobot-winPathFix' into unstable 2015-05-07 09:32:20 +02:00
Vasil Rangelov
a6b1961d77 Patched the file and folder dialogs (in both Qt4 and Qt5) to replace any "/" with the OS folder seprator (notably useful on Windows). 2015-05-07 00:13:28 +03:00
grossmj
dc95bad4aa Merge remote-tracking branch 'origin/master' 2015-05-06 14:59:35 -06:00
grossmj
327d0277fc NIO NAT support for QEMU VMs (user mode back-end is used). 2015-05-06 14:59:01 -06:00
Vasil Rangelov
d363212191 The device list in the configuration dialog is hidden by default when only one device is selected. 2015-05-06 21:14:33 +03:00
Vasil Rangelov
266bf202bb Fixes the CTRL+Wheel zoom (Qt5 misses "orientation" for some reason, and has renamed delta() to angleDelta()). 2015-05-06 18:30:51 +03:00
Vasil Rangelov
f280445138 Adds multi select support in all device template pages.
* Also adds "Delete" as part of the context menu of devices.
* (Some methods are reordered for consistency; Legacy signaling is fixed to the new one where encountered)
* Patched build_pyqt.py for Windows, and for it to remove the path of the .ui file in the comment.
* Shrinked the minimum width of all preference dialogs.
* Removed zorder nodes (PyQt5 complains...) and regenerated all preference dialogs.
2015-05-06 14:42:59 +02:00
Julien Duponchelle
fcd93c8db8 Merge branch 'master' into unstable 2015-05-06 13:41:47 +02:00
Julien Duponchelle
72add39182 Fix PyQT4 download link 2015-05-06 13:40:00 +02:00
Julien Duponchelle
d02f0bf5b4 Merge branch 'master' into unstable 2015-05-06 13:39:20 +02:00
Vasil Rangelov
509a946c92 Modified version requirements, so that they require the dependency versions as minimums.
Added some more detailed instructions for compilation on Windows.

Conflicts:
	requirements.txt
2015-05-06 13:38:41 +02:00
Julien Duponchelle
986734e29b Merge branch 'boenrobot-dbClickToConfigure' into unstable 2015-05-06 13:28:23 +02:00
Julien Duponchelle
147d9dbe83 Merge branch 'dbClickToConfigure' of https://github.com/boenrobot/gns3-gui into boenrobot-dbClickToConfigure 2015-05-06 13:25:37 +02:00
Julien Duponchelle
c974853fe8 Merge branch 'boenrobot-readmeAndReq' into unstable 2015-05-06 13:24:42 +02:00
Julien Duponchelle
d124f9c8e0 Merge branch 'readmeAndReq' of https://github.com/boenrobot/gns3-gui into boenrobot-readmeAndReq 2015-05-06 13:24:28 +02:00
Julien Duponchelle
cb9222271d Merge error 2015-05-06 13:23:42 +02:00
Julien Duponchelle
72505b550d Merge branch 'master' into unstable 2015-05-06 13:22:24 +02:00
Julien Duponchelle
b10946f0e8 PEP8 2015-05-06 13:21:17 +02:00
Julien Duponchelle
6bcb1ab113 Prevent user to enter a None port
I don't know how they force the None value in the input field...

Fix #334, #333
2015-05-06 11:06:50 +02:00
Julien Duponchelle
9dc22142ef Change crash report key
Fix #336
2015-05-06 10:58:43 +02:00
Julien Duponchelle
e23818b3b4 Typo 2015-05-06 10:52:29 +02:00
Julien Duponchelle
0eef72b6e3 Fix broken pipe error on OSX when frozen
Fix https://github.com/GNS3/gns3-server/issues/166
2015-05-06 10:47:03 +02:00
grossmj
00995e3a6a Merge remote-tracking branch 'origin/master' 2015-05-05 14:49:13 -06:00
grossmj
089dad31c0 Bump version to 1.3.3dev2 2015-05-05 14:49:03 -06:00
Jeremy Grossmann
b79d36e0eb Merge pull request #332 from GNS3/prevent_double_link
Prevent the same link to be created twice.
2015-05-05 14:37:34 -06:00
Julien Duponchelle
07a78b55cb Prevent the same link created twice 2015-05-05 22:27:34 +02:00
grossmj
7aa6f8fa9d Merge remote-tracking branch 'origin/master' 2015-05-05 12:29:05 -06:00
grossmj
47eaa1ac96 Project loading: names and IDs must be assigned to ports on the client side after nodes have been created. Fixes #326.
Fixes config updating for IOS router and IOU devices.
2015-05-05 12:28:56 -06:00
Julien Duponchelle
0866632b2f Fix a crash when dropping a .gns3
Fix #328
2015-05-05 19:58:20 +02:00
Julien Duponchelle
7500b602dc Merge branch 'master' into unstable 2015-05-05 14:21:34 +02:00
Julien Duponchelle
31b341cb68 Cleanup VPCS code
Fix #324
2015-05-05 14:16:07 +02:00
Julien Duponchelle
7c62945560 Turn off config parser interpolation
Fix #322
2015-05-05 11:50:05 +02:00
Julien Duponchelle
59fb3c1dbe Support unicode characters in regex 2015-05-05 10:21:05 +02:00
grossmj
ea86e2990b Fixes duplicate entries for "Recent files" on Windows. Fixes #316. 2015-05-04 22:59:46 -06:00
grossmj
b2e0ec4130 Fixes VPCS multi-host. Fixes #318. 2015-05-04 22:20:03 -06:00
grossmj
de8a73efb7 Fixes issues when importing configs for IOS, IOU and VPCS. Fixes #314. 2015-05-04 21:42:50 -06:00
grossmj
df95c2c85d Fixes issue when console setting present in IOS router templates. 2015-05-04 20:32:00 -06:00
Jeremy
df322ceacf Do not send empty settings when creating VMs. 2015-05-04 19:03:35 -06:00
Jeremy
78df3fc12c Do not set a default private-config when creating a new IOS router template. Fixes #317. 2015-05-04 18:47:56 -06:00
Jeremy
b1a1824522 Refactors how startup-config and private-config are handled for IOS routers. 2015-05-04 18:42:32 -06:00
Jeremy
ffab68e809 Fixes IOU and QEMU tests. 2015-05-04 16:07:10 -06:00
Vasil Rangelov
89410cc55d Modified version requirements, so that they require the dependency versions as minimums.
Added some more detailed instructions for compilation on Windows.
2015-05-04 23:33:23 +03:00
Vasil Rangelov
9d3b17d86b Adjusted the double click action so that a click on a stopped node opens the configuration dialog with all selected nodes and a double click on a started node consoles to all selected devices. 2015-05-04 23:23:19 +03:00
Jeremy
a4a242d58b Makes sure all IOS router settings are saved in the project file & simplify loading from a project. 2015-05-04 14:09:09 -06:00
Jeremy
b488764b79 Makes sure all VirtualBox VM settings are saved in the project file & simplify loading from a project. 2015-05-04 12:44:50 -06:00
Jeremy
38848f43e4 Makes sure all VPCS VM settings are saved in the project file & simplify loading from a project. 2015-05-04 12:05:35 -06:00
grossmj
9ffea5cadb Merge remote-tracking branch 'origin/master' 2015-05-04 11:20:08 -06:00
grossmj
9e05675823 Makes sure all IOU VM settings are saved in the project file & simplify loading from a project. 2015-05-04 11:20:08 -06:00
grossmj
3b4efc21a6 Makes sure all QEMU VM settings are saved in the project file & simplify loading from a project. 2015-05-04 11:19:30 -06:00
Julien Duponchelle
beaf31ae05 Fix save as by correctly renaming VM uuid project directory
Fix https://github.com/GNS3/gns3-server/issues/173
2015-05-04 17:23:29 +02:00
Julien Duponchelle
631e0b0741 Fix save as duplicate the .gns3 file
Fix #247
2015-05-04 13:29:14 +02:00
Julien Duponchelle
553e3b02f5 Fix about dialog with PyQT4 by turning off translation
Fix #312
2015-05-04 12:08:56 +02:00
Julien Duponchelle
c11db9f0af Another assert topology fixe
If you can not create the initial project directory the GUI
the project is in an dirty state.

Fix #319
2015-05-04 11:47:33 +02:00
Julien Duponchelle
9ce91345a7 Drop debug 2015-05-04 11:19:14 +02:00
Julien Duponchelle
a6653a3419 Prevent user to enter bad hostname
Fix #311
2015-05-04 11:16:34 +02:00
Julien Duponchelle
756f1dd218 Merge branch 'master' into unstable 2015-05-04 09:37:29 +02:00
Julien Duponchelle
accf332668 Fix crash 2015-05-04 09:36:11 +02:00
grossmj
8483b0d08e Fixes an issue when the IOU VM template has a console setting. 2015-05-03 18:10:17 -06:00
grossmj
b46be2445a Releasing adding a link. Fixes #235. 2015-05-03 14:03:20 -06:00
grossmj
d45328576f THis should fix RuntimeError: wrapped C/C++ object of type QNetworkReply has been deleted. 2015-05-03 11:55:56 -06:00
Julien Duponchelle
a31cc33c67 Do not crash if terminal doesn't support UTF-8
Fix #306
2015-05-02 15:41:18 +02:00
Julien Duponchelle
b874147b9c Fix windows build
Fix #304
2015-05-02 14:23:19 +02:00
grossmj
4b0b5cb85c List all available VMware VMs. 2015-05-01 18:47:46 -06:00
Jeremy
23ad776a74 Basic VMware support (start & stop a VM). 2015-04-30 19:05:37 -06:00
Jeremy
02cc9ec935 Old style signals are not supported in PyQt5. 2015-04-30 18:24:01 -06:00
Julien Duponchelle
1d0c21eff1 Listen for notifications from servers. 2015-04-30 17:29:55 +02:00
Julien Duponchelle
422c97f681 Support for reading an HTTP stream 2015-04-30 17:29:55 +02:00
Julien Duponchelle
f0d00420c3 Fix tests 2015-04-30 17:29:36 +02:00
Julien Duponchelle
64c1eac2d0 Merge branch 'master' into unstable 2015-04-30 16:59:39 +02:00
Julien Duponchelle
09046ab89e Fix test suite 2015-04-30 16:59:14 +02:00
Julien Duponchelle
ae7c98ce78 Merge branch 'master' into unstable
Conflicts:
	gns3/version.py
2015-04-29 14:27:55 +02:00
grossmj
62bff009c1 Fixes "show only devices with captures" in the topology summary. 2015-04-28 19:30:44 -06:00
Julien Duponchelle
0c3ea4b05d 1.3.3dev1 2015-04-28 21:48:53 +02:00
Julien Duponchelle
9dde2fbcf8 Version 1.3.2 2015-04-28 21:09:33 +02:00
grossmj
740041a844 Fixes bug when IOS configs are not in VM settings. 2015-04-28 12:49:01 -06:00
grossmj
31bcb8c82d Fixes small issue with Qemu VM monitor. 2015-04-28 12:12:50 -06:00
grossmj
425ef9f059 Fixes #297. 2015-04-28 10:56:18 -06:00
grossmj
e059ecc6c4 Fixes issue when only one port is added after a QEMU VM is created. Fixes #296. 2015-04-28 09:09:35 -06:00
Julien Duponchelle
e04fc7d950 Fix an invalid import 2015-04-28 11:08:36 +02:00
Julien Duponchelle
97f75fb971 Merge branch 'master' into unstable
Conflicts:
	gns3/graphics_view.py
	gns3/http_client.py
	gns3/main_window.py
	gns3/modules/dynamips/dialogs/ios_router_wizard.py
	gns3/modules/dynamips/pages/ios_router_preferences_page.py
	gns3/modules/vpcs/pages/vpcs_device_configuration_page.py
	gns3/utils/file_copy_worker.py
	gns3/utils/process_files_worker.py
	gns3/utils/progress_dialog.py
	gns3/utils/wait_for_connection_worker.py
2015-04-28 11:01:16 +02:00
grossmj
425a8c864b Avoid Cygwin warning with VPCS on Windows. 2015-04-27 22:23:27 -06:00
grossmj
56c2b1d9b5 Merge remote-tracking branch 'origin/master' 2015-04-27 21:18:08 -06:00
grossmj
ab74d19584 Fixes issues with QThread handling. 2015-04-27 21:17:56 -06:00
Jeremy
3e197b72a8 Fixes missing title + icon in layer position warning message box. 2015-04-27 19:11:37 -06:00
Jeremy
863e1a2e20 Allows the warning message box to be displayed once only when moving an object to a background layer. 2015-04-27 19:05:21 -06:00
Jeremy
a00c8e0a53 Fixes small issue with old monitor setting. 2015-04-27 18:58:42 -06:00
Jeremy
3b98206942 Check the config path is set when creating a IOU or IOS router. 2015-04-27 18:53:07 -06:00
Jeremy Grossmann
f6cee7297a Merge pull request #292 from GNS3/prevent_empty_file
Prevents writing empty topologies.
2015-04-27 16:33:29 -06:00
Jeremy
6792e3d701 Removes residual link when a NIO cannot be created on the server. Fixes #294. 2015-04-27 15:20:37 -06:00
Jeremy
df1e5aef9b Fixes #294. 2015-04-27 14:46:37 -06:00
Julien Duponchelle
6c3d2926b7 Fix VPCS tests 2015-04-27 21:00:52 +02:00
Julien Duponchelle
302fcfc7d7 Do not crash if an antivirus intercept a message and send non UTF-8
Fix #295
2015-04-27 17:34:39 +02:00
grossmj
42dd9969e4 Avoid C++ runtime error when progress dialog is finished. 2015-04-27 09:30:26 -06:00
grossmj
6a69ce26e3 Merge remote-tracking branch 'origin/master' 2015-04-27 09:17:57 -06:00
grossmj
8d6db96a4c Move FileCopyThread to FileCopyWorker. 2015-04-27 09:17:44 -06:00
Julien Duponchelle
e61a6bae7e If project loading fail fallback to real temporary project
It should avoid the issue with assert in topologyFile
2015-04-27 16:54:12 +02:00
Julien Duponchelle
37989854a7 Do not crash if rotation is a string
Some users have this error. Not sure if it's a bug
or a tutorial which explain how to modify .gns3 files.

Fix #293
2015-04-27 16:37:26 +02:00
Julien Duponchelle
c70f8441e2 I think it's prevent empty topologies
Fix #290
2015-04-27 11:15:27 +02:00
grossmj
f9073055e9 Explicit utf-8 decoding. 2015-04-26 21:19:39 -06:00
grossmj
a22cdd9553 Fixes rare maximum recursion depth exceeded exception. 2015-04-26 17:36:59 -06:00
grossmj
67b8166ebc Check for invalid base VM configuration files. 2015-04-26 17:06:09 -06:00
grossmj
762e498a5c Catch ValueError exception thrown by mmap(): cannot mmap an empty file. 2015-04-26 16:07:08 -06:00
grossmj
48c9862e18 Use QThreads the correct way (moveToThread). 2015-04-26 16:01:35 -06:00
grossmj
a8b7faaed3 Fixes broken serial console connection. 2015-04-25 16:57:09 -06:00
grossmj
c56abc020e Fixes "RuntimeError: wrapped C/C++ object ... has been deleted" exceptions with item links. 2015-04-25 16:40:33 -06:00
grossmj
20067b91eb Allows exported config files to be created even when there is no config set on VMs. 2015-04-25 15:13:35 -06:00
grossmj
43004af842 Do not try to export empty VPCS startup configs. 2015-04-25 14:42:56 -06:00
grossmj
6eb51fdafd Prevent issues when a file with a simple number is considered valid JSON. 2015-04-25 14:16:10 -06:00
grossmj
c3f831727b Explicit error when mmap throw an invalid argument exception. 2015-04-25 12:44:51 -06:00
grossmj
6d328eb376 Do not replace invalid utf-8 characters when reading the iourc file (we catch the exception to tell the user this is an invalid file). 2015-04-25 12:05:31 -06:00
grossmj
b9424f41ab Explicit utf-8 encoding where necessary to avoid Unicode errors on Windows (we require/set an utf-8 locale on other systems). 2015-04-25 11:58:34 -06:00
Jeremy
b8aa1af55a Save as dialog opens in the projects directory. Fixes #267. 2015-04-24 17:36:55 -06:00
Jeremy
1ba6e361bd Adds Terminal + nc for serial console connections on OSX. Fixes #228. 2015-04-24 17:11:06 -06:00
Jeremy
0e2c411198 Removes unneeded progress dialog in VMWizard. 2015-04-24 17:03:21 -06:00
Jeremy
ca7917b407 Merge remote-tracking branch 'origin/unstable' into unstable 2015-04-24 14:40:31 -06:00
Jeremy Grossmann
69013d2765 Merge pull request #281 from GNS3/api_list_images
Load list of images from the server.
2015-04-24 14:39:39 -06:00
Jeremy
8a022a2365 Merge remote-tracking branch 'remotes/origin/unstable' into api_list_images
Conflicts:
	gns3/modules/iou/dialogs/iou_device_wizard.py
2015-04-24 14:39:10 -06:00
Jeremy
0d07af4862 Merge branch 'api_list_images' into unstable 2015-04-24 14:35:38 -06:00
Jeremy
d5279fb50c Rename DeviceWizard to VMWizard. 2015-04-24 14:32:05 -06:00
Julien Duponchelle
7d887bdbef Cleanup 2015-04-24 21:55:08 +02:00
Julien Duponchelle
d688db95e9 Improve warning when non unicode char in iourc 2015-04-24 19:10:05 +02:00
Julien Duponchelle
d12770f97c Drop QEMU_BINARIES_FOR_CLOUD because we have generic implementation now 2015-04-24 18:50:36 +02:00
Julien Duponchelle
a3d9efbda2 Show / hide dock widget experimental 2015-04-24 18:45:17 +02:00
Julien Duponchelle
3f6479e578 Merge branch 'master' into unstable 2015-04-24 18:44:24 +02:00
Julien Duponchelle
9c14b42bda Crash report not for developers and new key 2015-04-24 18:42:44 +02:00
Julien Duponchelle
5f04224d57 Do not crash if we can't change IOU permission
Fix #280
2015-04-24 15:42:11 +02:00
Julien Duponchelle
5d8d8a5ffe Load list of images from the server
Support Qemu, IOU and Dynamips

* IOU: Choose l2 or l3 depending of user input
* Refactor Qemu, IOU and Dynamips wizard to share common code
* Dynamips set the correct platform in all cases
2015-04-24 10:58:48 +02:00
Julien Duponchelle
9d511e0370 Merge branch 'master' into unstable
Conflicts:
	gns3/modules/dynamips/pages/ios_router_preferences_page.py
	gns3/modules/dynamips/utils/decompress_ios_thread.py
2015-04-24 10:36:41 +02:00
grossmj
37f3bb42a0 More checks when decompressing IOS images. 2015-04-23 21:33:31 -06:00
Jeremy Grossmann
6af2b098e2 Merge pull request #287 from GNS3/no_routers_warning
Warn users that they must provide their router images.
2015-04-23 17:13:02 -06:00
Jeremy
a30a0f8d0b Warn users that they must provide their router images. 2015-04-23 17:12:17 -06:00
Jeremy Grossmann
73d26b45fc Merge pull request #286 from GNS3/wireshark_remote_capture
Wireshark remote packet capture support.
2015-04-23 16:47:48 -06:00
Jeremy
03d1cc4f78 Completes remote packet capture support. 2015-04-23 16:46:47 -06:00
Jeremy Grossmann
49c89810d8 Merge pull request #283 from GNS3/qt5
PyQt5 support with backward PyQt4 compatibility.
2015-04-23 16:13:13 -06:00
Jeremy
4dc3647370 Completes PyQt5 support with backward PyQt4 compatibility. 2015-04-23 16:10:22 -06:00
Julien Duponchelle
b78c37dbbe Display an error and link to the documentation if no router available
It's the most common issue on the support forum.
2015-04-23 14:18:14 +02:00
Julien Duponchelle
6ab00e46b2 Migration to QT5
I drop some related cloud support, we will restore it when we will be ready.
* Switch to Python3 super style
* Drop old object inheritance
* Fixed old super call
2015-04-23 12:24:26 +02:00
Julien Duponchelle
ec22d72f3f Merge branch 'master' into unstable 2015-04-23 11:41:58 +02:00
grossmj
e7fdb804ae Merge remote-tracking branch 'origin/master' 2015-04-22 20:30:16 -06:00
Jeremy Grossmann
6749aee5cd Merge pull request #284 from GNS3/console_print
Display printed messages on both stdout and the GNS3 Qt Console.
2015-04-23 00:57:16 +00:00
grossmj
c3b846bac7 Merge remote-tracking branch 'origin/master' 2015-04-22 18:54:10 -06:00
Julien Duponchelle
5c9bb477b4 Display print( in std console and Qt Console 2015-04-22 17:30:25 +02:00
Julien Duponchelle
97324ce4d4 Wireshark remote packet capture 2015-04-21 18:20:54 +02:00
Julien Duponchelle
a11d84e812 Merge branch 'master' into unstable 2015-04-21 18:17:53 +02:00
Julien Duponchelle
57247cd5cd Fix tests and a potential issue where initial_content is not send
Previously we didn't resend an initial_config if we already have
a vm id. The issue is if on the server your VM doesn't exist
because you import a topology it's broken.
2015-04-21 18:11:54 +02:00
Julien Duponchelle
1d7774bcd6 Support for reading an HTTP stream 2015-04-21 12:45:48 +02:00
grossmj
415ab6298e Merge remote-tracking branch 'origin/master' 2015-04-20 13:03:48 -06:00
Julien Duponchelle
806a8efe94 Merge branch 'master' into unstable 2015-04-20 17:25:35 +02:00
Julien Duponchelle
50925c4c30 Fix a crash in qemu loading
Fix #285
2015-04-20 11:12:46 +02:00
grossmj
c9d12184e0 Removes unnecessary progress dialog when listing VirtualBox VMs. 2015-04-19 17:53:30 -06:00
Julien Duponchelle
b0894b1e75 Merge branch 'master' into unstable 2015-04-17 15:07:57 +02:00
Julien Duponchelle
c2781b1f8b Drop unused code for the moment 2015-04-17 15:07:43 +02:00
grossmj
bd2ccc3612 Fixes issues when pushing configs for Dynamips and IOU. 2015-04-17 06:10:55 -06:00
Julien Duponchelle
92faccdd90 Merge branch 'master' into unstable 2015-04-16 18:38:35 +02:00
grossmj
5b42b41dcb Allow for empty initial-config path for IOU VM templates.
Send IOU VM settings while creating it (POST) and not using the update API call immediately after (PUT).
2015-04-15 19:56:55 -06:00
grossmj
8a5c429e87 Allow for empty startup-config and private-config paths for IOS routers. 2015-04-15 19:51:39 -06:00
grossmj
194923ca27 Send QEMU VM settings while creating it (POST) and not using the update API call immediately after (PUT). 2015-04-15 18:40:00 -06:00
grossmj
a2b8391174 Some cleaning. 2015-04-15 18:35:34 -06:00
Julien Duponchelle
c0fd535067 Include resources and tests in pypi packages
Require by Gentoo maintainer

Fix #266
2015-04-14 14:51:14 +02:00
Julien Duponchelle
6629c38d2a Authorize dev users to use different GNS3 version 2015-04-14 13:55:13 +02:00
Julien Duponchelle
58032012aa Fix issue during project import on Windows with non local server
It was a race condition during project import.

Fix #279
2015-04-13 20:10:22 +02:00
Julien Duponchelle
7025accd88 1.4.0 dev1 2015-04-13 15:56:41 +02:00
Julien Duponchelle
cc40afcc4d GNS3 1.3.2 dev1 2015-04-11 14:06:02 +02:00
Julien Duponchelle
3ff2b5f546 Prepare 1.3.1 release 2015-04-11 09:33:08 +02:00
Julien Duponchelle
f5e2309563 Prepare 1.3.1rc4 2015-04-09 10:59:37 +02:00
Julien Duponchelle
75aa6d50b3 Fix crash when save as can't create a directory
Fix #272
2015-04-09 10:11:00 +02:00
Julien Duponchelle
021ad2a5c2 Allow less strict dependencies
Fix #259
2015-04-09 09:52:54 +02:00
Julien Duponchelle
ffe486e284 Prepare 1.3.1rc3 2015-04-07 16:18:12 +02:00
Julien Duponchelle
6132aa7864 Send HTTP errors 400 to the crash report system
Fix #269
2015-04-07 12:34:15 +02:00
Julien Duponchelle
56e55d9cd6 Prepare 1.3.2rc2 2015-04-06 21:36:35 +02:00
Julien Duponchelle
2f0e91d96e Fix race condition during old project import
Fix #268
2015-04-06 21:16:20 +02:00
Julien Duponchelle
32a45ad0d3 Fix tests 2015-04-06 15:31:30 +02:00
Julien Duponchelle
f0d0d6b73a Update crash report key 2015-04-05 11:56:32 +02:00
Julien Duponchelle
03c470846b Prepare 1.3.1rc1 2015-04-05 11:34:07 +02:00
Julien Duponchelle
66f347c973 Fix rare occasion when user manage to put test in port field
Fix #257
2015-04-03 19:36:01 +02:00
Julien Duponchelle
1cf8cae166 Fix a crash when exporting vpcs startup script
Fix #262
2015-04-03 19:22:57 +02:00
Julien Duponchelle
f2585438bd Fix an issue with sending iourc when a topologies is reloaded
Fix #264
2015-04-03 19:18:31 +02:00
Julien Duponchelle
f1e2c5b0d1 Solve issue when iourc contains non ascii characters
Fix #263
2015-04-03 18:04:37 +02:00
Julien Duponchelle
466ba18ec8 Handle corrupted zip file with IOS image
Fix #252
2015-04-03 16:41:45 +02:00
Julien Duponchelle
844fb2e6ec Don't crash if we try to contact a non GNS3 remote server returning JSON
Fix #253
2015-04-03 16:17:30 +02:00
Julien Duponchelle
41d8e2a0ae Skip tests in package 2015-04-01 16:53:35 +02:00
Julien Duponchelle
49ea016980 Check port range
Fix #258
2015-04-01 16:19:08 +02:00
Julien Duponchelle
34a8972ce4 Add a warning about too much ram for IOS
Thanks to eduardo from the community pour l'aide
2015-04-01 15:56:26 +02:00
Julien Duponchelle
a980e1910c Fix crash if project is already closed
Fix #206
2015-04-01 11:31:42 +02:00
grossmj
10758879db Check if wait for connection thread still running before emitting a signal. 2015-03-31 19:59:15 -06:00
grossmj
1e0986b1f6 Check if process files thread still running before emitting a signal. 2015-03-31 19:51:45 -06:00
grossmj
57e16f46ce Missing struct import. 2015-03-31 19:48:34 -06:00
Julien Duponchelle
cc076cc803 Raven is an optionnal dependencies for Debian
Fix #249
2015-03-31 16:51:58 +02:00
Julien Duponchelle
254262c5c4 Fix crash if a dumped topology as no node during save as
Fix #251
2015-03-31 16:47:21 +02:00
grossmj
dc8279c3ea Remove old debug message. 2015-03-30 22:17:28 -06:00
Jeremy
d34d9316f3 Fix: remove old ID references for ATM and Frame-Relay switches. 2015-03-30 13:27:09 -06:00
Jeremy
7496b1de21 Bump version to 1.3.1.dev1 2015-03-30 13:09:05 -06:00
Julien Duponchelle
27eca480d0 1.3.0 release 2015-03-30 18:05:49 +02:00
Jeremy Grossmann
311ec1d5df Merge pull request #246 from GNS3/save_as
Fixes "save as". Fixes #244.
2015-03-30 15:49:44 +00:00
Julien Duponchelle
a66beecd8d Fix tests 2015-03-30 16:55:50 +02:00
Julien Duponchelle
f833c8c598 Correctly close the project before reopening (otherwise port conflict)
Fix #244
2015-03-30 16:24:13 +02:00
Julien Duponchelle
828c3b3c9c Fix save as feature by changing uuid of VM and project 2015-03-30 16:18:45 +02:00
grossmj
d5f432d07c Remove path settings for IOS router templates (redundant with image setting). Fixes #239. 2015-03-29 18:59:33 -06:00
grossmj
0f8404f686 Fixes progress dialog with deleted thread issue. 2015-03-28 22:16:54 -06:00
grossmj
ff46870bf1 Fixes #243. 2015-03-28 21:13:13 -06:00
grossmj
1b55a5a399 Remove old code for Monitor support. 2015-03-27 08:53:52 -06:00
grossmj
afb06cab99 Remove useless code in legacy EtherSwitch class. 2015-03-26 09:35:12 -06:00
Jeremy Grossmann
d26ac237e9 Merge pull request #242 from GNS3/etherswitch
Fix crash in etherswitch router
2015-03-26 15:14:16 +00:00
Julien Duponchelle
41c200a011 Fix crash in etherswitch router
Fix #241
2015-03-26 10:59:57 +01:00
Jeremy
fecabca368 Merge remote-tracking branch 'origin/master' 2015-03-25 14:37:10 -06:00
grossmj
4afb864bef Do not expose the Qemu monitor port in the GUI. 2015-03-23 22:50:20 -06:00
grossmj
7b8690cbb7 Fixes VirtualBox packet capture issue. 2015-03-23 21:40:20 -06:00
grossmj
9a97b4b754 Bump version to 1.3.0.dev3 2015-03-23 21:22:10 -06:00
Jeremy
ad4e1f216d Bump version to 1.3.0.dev3 2015-03-23 18:37:42 -06:00
Jeremy
d6264dfc0b Bump version to 1.3.0rc2 2015-03-23 15:41:10 -06:00
Jeremy
675228d841 Load getting started html from local file. 2015-03-23 15:32:44 -06:00
Jeremy
a28567b48a Adds missing images for getting started dialog. 2015-03-23 14:17:55 -06:00
Jeremy
317ba23e5a Merge remote-tracking branch 'origin/master' 2015-03-23 14:00:53 -06:00
Jeremy
26a30da072 New getting started dialog. Have it completely offline too. 2015-03-23 14:00:48 -06:00
Julien Duponchelle
b35e87780b Changelog 2015-03-23 20:23:45 +01:00
Julien Duponchelle
f9aab38575 Merge pull request #238 from GNS3/untitled
Default project name
2015-03-23 20:17:16 +01:00
Julien Duponchelle
01f8815413 Default project name 2015-03-23 19:27:00 +01:00
Julien Duponchelle
963aabb8f5 Add debug for issue #232 2015-03-23 15:46:48 +01:00
Julien Duponchelle
884fe3c7d9 Update sentry key 2015-03-23 15:27:46 +01:00
grossmj
8866e2aa13 Display adapters in the tooltips in the correct order. 2015-03-22 20:32:54 -06:00
grossmj
07ac9710a8 Open consoles in alphanumerical order. 2015-03-22 14:52:58 -06:00
grossmj
9177962454 Auto idle-PC improvements. 2015-03-22 12:03:46 -06:00
grossmj
a66545dac5 Bump version to 1.3.0.dev2 2015-03-21 22:47:12 -06:00
grossmj
0614dcb3e2 Adds project id when requesting UDP port. 2015-03-21 22:27:40 -06:00
grossmj
359d6c4dba Fixes Thread problem. Fixes #229. 2015-03-21 21:32:59 -06:00
grossmj
242018d0d3 Cancel network requests if the progress dialog itself is canceled.
Avoid closing the preferences dialog or any configuration dialog if there is a pending request.
Fixes #227.
2015-03-21 20:23:04 -06:00
grossmj
d9a81d1d14 Fixes #228 (no alternative interface has been chosen). 2015-03-21 18:06:24 -06:00
grossmj
eeb3b70328 Catch OSError when reading or writing the local server config file. 2015-03-21 17:37:04 -06:00
grossmj
ca6820f91b Fixes GUI that could not be closed when using an already running local server. 2015-03-21 17:16:31 -06:00
grossmj
257eed01df Save configs when project is committed. 2015-03-21 14:52:17 -06:00
Jeremy Grossmann
f08475605a Merge pull request #234 from rashoodkhan/Fix-Issue-18
Del key deletes selected link - Fixes #18
2015-03-21 19:04:34 +00:00
Rashid Khan
64d480be48 Updated the key press event callback to pass the del signal to lower levels 2015-03-21 16:43:44 +05:30
Rashid Khan
f240bca81a Del key deletes selected link - Fixes #18 2015-03-21 02:12:15 +05:30
Jeremy Grossmann
3b67dc4ac0 Merge pull request #233 from GNS3/fix_crash_no_servers
Fix crash is no remote servers is available
2015-03-20 15:39:45 +00:00
Julien Duponchelle
06fba3a816 Fix crash is no remote servers is available
Fix #230
2015-03-20 10:56:31 +01:00
grossmj
1586ba83dc Bump version to 1.3.0.dev1 2015-03-19 19:56:31 -06:00
Julien Duponchelle
ab3a5df71d Bump version and CHANGELOG 2015-03-19 17:36:31 +01:00
Jeremy
9d91629ba7 Bump version to 1.3.0rc1.dev3 2015-03-18 15:40:02 -06:00
Jeremy
0921d51262 Save IOS router configs when saving the project (done right this time). 2015-03-18 15:34:31 -06:00
Julien Duponchelle
4bf898c9d9 Do not use another port if socket is in the TIME_WAIT state 2015-03-18 17:08:43 +01:00
Julien Duponchelle
d346c69033 Fix shutdown local server
Fix #224
2015-03-18 10:48:04 +01:00
grossmj
cd68e387c9 Handle legacy snapshots. 2015-03-17 23:02:01 -06:00
Jeremy
ee3d51cb84 Bump version to 1.3.0rc1.dev2 2015-03-17 19:08:18 -06:00
Jeremy
8e584dbe12 Fixes Qemu VM template with type "default" has the networking legacy mode set to off on Mac and Windows when using an old Qemu version. 2015-03-17 19:07:39 -06:00
Jeremy
90f955e471 Support for snapshots before 1.3. 2015-03-17 18:18:41 -06:00
Jeremy
702fc5ac31 Adds server information to Qemu, VirtualBox and VPCS info boxes. Fixes #217. 2015-03-17 16:48:30 -06:00
Jeremy
746a84b50b Set Jungle news feed refresh to 5 min instead of 1 min. 2015-03-17 15:26:12 -06:00
Jeremy
e8cc49fe14 Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-03-17 13:00:06 -06:00
Jeremy
f5b9c97edb Fixes BadStatusLine exception. 2015-03-17 12:59:05 -06:00
Julien Duponchelle
376178b18a Solve issue with canceled progress dialog
Fix #214
2015-03-17 19:48:46 +01:00
Julien Duponchelle
76521218ae Support sending IOURC 2015-03-17 19:32:44 +01:00
Julien Duponchelle
f9a9c5c00f Send iourc to remote server 2015-03-17 18:59:46 +01:00
Julien Duponchelle
5779e164c6 Another fix for the pkg_ressources recurring bug
Fix #216
2015-03-17 11:51:39 +01:00
Jeremy
e17693905a Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-03-16 17:36:29 -06:00
Jeremy
92add6b14d Temporarily deactivate IOS router saveconfigs. 2015-03-16 17:36:23 -06:00
Julien Duponchelle
3493de7bb7 If project can't be create do not block application exit
Close #204
2015-03-16 23:11:02 +01:00
Julien Duponchelle
c0557f7974 Add assert in order to found bug #208 2015-03-16 22:44:06 +01:00
Julien Duponchelle
f3e8473f60 Fix missing context at first query
Fix #206, #209
2015-03-16 22:18:34 +01:00
Julien Duponchelle
d88a104237 Fix test 2015-03-16 22:18:34 +01:00
Jeremy
932c2162ad New remote servers were not set as non local by default. 2015-03-16 14:57:42 -06:00
Jeremy
6f3cdfcc4a Adds a 1MB disk by default for EtherSwitch router templates (to store the vlan database). 2015-03-16 13:18:21 -06:00
Jeremy
b311c7991c Fixes alignment options to ignore device labels. 2015-03-16 13:13:40 -06:00
Jeremy
2d25ff399f Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-03-16 12:52:07 -06:00
Jeremy
66c78f44c2 Prevent using lab instructions in a temporary project. Fixes #210. 2015-03-16 12:51:59 -06:00
Julien Duponchelle
6f68947815 Compute idlepc on remote servers
Fix #212
2015-03-16 19:29:30 +01:00
Julien Duponchelle
c24460962a Display a warning on console if port is already used 2015-03-16 18:57:18 +01:00
Julien Duponchelle
8a0512c956 Display an error if server version is incorect
Related to #211
2015-03-16 16:33:36 +01:00
grossmj
8f146c5161 Removes confreg setting for IOS routers. 2015-03-14 16:31:15 -06:00
grossmj
d5076999fd Fixes vanishing config paths when editing IOS router or IOU device templates 2015-03-14 16:13:47 -06:00
grossmj
69df0b6837 Bump version to 1.3.0rc1.dev1 2015-03-13 22:42:25 -06:00
grossmj
52bef05107 Bump version to 1.3.0beta2 2015-03-13 22:02:28 -06:00
grossmj
261f70c034 Update CHANGELOG 2015-03-13 22:00:19 -06:00
grossmj
c5e53125b5 Make sure local server is running before requesting shutdown. 2015-03-13 21:56:50 -06:00
Jeremy
304e84f901 Alternative local server shutdown (mostly intended for Windows). 2015-03-13 18:57:28 -06:00
Jeremy
ed4e4a1d93 Request user permission to kill the local server if it cannot be stopped. 2015-03-13 17:36:38 -06:00
Jeremy
ae00038493 Support RAM setting for VirtualBox VMs. 2015-03-13 17:13:36 -06:00
Jeremy
d6a60db1b7 Option to automatically take or not a screenshot when saving a project. Fixes #203. 2015-03-13 15:33:04 -06:00
Jeremy
a7fa3762aa Grey out local server preferences if the local server is not activated. 2015-03-13 15:16:37 -06:00
Jeremy
53a2b37c08 Adds "template" to the Wizard titles. 2015-03-13 11:10:31 -06:00
Jeremy
161f7cd514 Bump version to 1.3.0beta2.dev1 2015-03-12 18:51:22 -06:00
Jeremy
6816dc772b Changes to the Qemu VM wizard. 2015-03-12 18:03:29 -06:00
Jeremy
b72df57201 Fixes duplicate VM template entries for Qemu, VirtualBox and IOU. 2015-03-12 16:43:43 -06:00
grossmj
1bfdfc4535 Fixes tests. 2015-03-11 23:09:01 -06:00
grossmj
4149ed361b Update CHANGELOG. 2015-03-11 22:33:51 -06:00
grossmj
2e1b7e940b Bump version to 1.3beta1 2015-03-11 22:09:43 -06:00
grossmj
683c75d308 New title for VM/Devices/routers preference pages. 2015-03-11 22:08:31 -06:00
Jeremy
8e8efbb805 Deactivate auto idle-pc in contextual menu. 2015-03-11 19:32:40 -06:00
Jeremy
67da57e7f6 Optional IOU license key check. 2015-03-11 18:59:57 -06:00
Jeremy
1be5f9f748 Do not try to modify the project path on a remote server. 2015-03-11 18:05:28 -06:00
Jeremy
1ee5260d8c Relative picture paths are saved in the project. 2015-03-11 15:20:20 -06:00
Jeremy
c017586694 Relative path support of IOU, IOS and Qemu images. 2015-03-11 15:04:11 -06:00
Jeremy
ce8df3c833 More checks when automatically starting the local server. 2015-03-11 13:39:32 -06:00
Jeremy
b2a93c04c6 Fixes some issues when moving legacy settings. 2015-03-11 13:11:59 -06:00
Jeremy
2b19ba9572 Checks when opening or saving a project. 2015-03-11 11:14:20 -06:00
grossmj
3649ea612f Fixes GNS3 console issues. 2015-03-10 13:03:38 -06:00
grossmj
4dd9d3b18d Fixes base IOS and IOU base configs. 2015-03-10 12:20:05 -06:00
grossmj
db307ca37d Disk image browsers for HDC and HDD for Qemu VMs. 2015-03-10 12:09:32 -06:00
grossmj
5769927760 Support for HDC and HDD disk images in Qemu. 2015-03-10 11:50:30 -06:00
grossmj
e827e9be39 Renames server.conf and server.ini to gns3_server.conf and gns3_server.ini respectively. 2015-03-10 11:00:32 -06:00
Jeremy
b799e04c39 Remove remote servers list from module preferences + some other preferences re-factoring. 2015-03-09 18:22:53 -06:00
grossmj
0a1c45ef3b Bump version to 1.3.0beta1.dev2 2015-03-09 11:38:02 -06:00
grossmj
d06b6df34d Let the server know about the project name and convert old IOU projects on remote servers. 2015-03-08 19:13:01 -06:00
grossmj
b01854ec72 Bump the progress dialog minimum duration before display to 1000ms. 2015-03-08 12:47:52 -06:00
grossmj
89d2d28ccb Fixes port listing bug. 2015-03-08 12:47:11 -06:00
Jeremy
77f9bd931c Fixes Qemu networking. 2015-03-06 20:08:00 -07:00
Jeremy
9ae0779523 Give a warning when a object is move the background layer. 2015-03-06 17:54:07 -07:00
Jeremy
8d3952fcc9 Implement option to draw a rectangle when a node is selected. 2015-03-06 17:36:19 -07:00
Jeremy
0f759d763d New project icon. 2015-03-06 17:21:51 -07:00
Jeremy
22c7ae1053 Adds default name and placed in the project directory when taking a screenshot 2015-03-06 16:56:48 -07:00
Jeremy
f937aa374f Alignment options. 2015-03-06 15:39:32 -07:00
Jeremy
2a72cb9700 Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-03-06 13:43:54 -07:00
Jeremy
200bc94870 Fixes #196: Import / export of the preferences file. 2015-03-06 13:43:49 -07:00
Julien Duponchelle
168fad78a4 I hope it's fixed the pkg_ressource bug 2015-03-06 21:08:31 +01:00
Julien Duponchelle
741cd4a857 Revert "Drop qemu unused preferences page"
This reverts commit 84ed6cd722.

Conflicts:
	gns3/http_client.py
2015-03-06 19:56:49 +01:00
Jeremy
68102d1523 Includes SSL cacert file path in the warnings. 2015-03-06 11:25:25 -07:00
Jeremy
be72b8c9fd Adds warnings if the cacert.pem file cannot be found. 2015-03-06 11:20:28 -07:00
Jeremy
0d000cf19b Bump version to 1.3.0beta1.dev1 2015-03-06 10:34:02 -07:00
grossmj
0ecf21813e Removes result["code"] references. 2015-03-05 21:09:06 -07:00
Jeremy
e840fbd67d Removes debug messages. 2015-03-05 19:11:51 -07:00
Jeremy
e85ea6a3ef Support for Raven to send crash report from a frozen state. 2015-03-05 16:11:43 -07:00
Julien Duponchelle
f80c6ae6f3 Do not crash when moving a project from temporary to non temp
Fixes #198
2015-03-05 20:46:15 +01:00
Julien Duponchelle
5050cfa7e8 Do not crash if you use Tools => Multi VPCS on a temporary project
Fixes #199
2015-03-05 20:44:50 +01:00
Julien Duponchelle
23d87cd926 Do not crash if egg cache is broken on user computer
Fixes #200
2015-03-05 20:26:58 +01:00
Julien Duponchelle
c5a2974d53 Report more informations about the OS 2015-03-05 20:14:11 +01:00
Julien Duponchelle
3aa0736478 Add more informations to the crash report 2015-03-05 17:38:40 +01:00
Julien Duponchelle
92f6aab290 Cleanup old codes 2015-03-05 17:17:31 +01:00
Julien Duponchelle
12322b4be0 Do not crash if query id is missing 2015-03-05 17:03:44 +01:00
Julien Duponchelle
7a1b0e7a48 Fix a crash when you change project and some query a remaining 2015-03-05 14:50:24 +01:00
Jeremy
1914522c3a Fixes adapters restoration when loading a pre-1.3 project. 2015-03-04 18:55:17 -07:00
Jeremy
ad07bd9bb9 Fixes adapter bug with VirtualBox. 2015-03-04 18:24:15 -07:00
Julien Duponchelle
75d2c6686d Notation harmonisation 2015-03-03 18:48:11 +01:00
Jeremy
9253b7f841 Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-03-03 10:47:12 -07:00
Jeremy
60970134e6 Bump to version 1.3.0alpha1 2015-03-03 10:47:02 -07:00
Julien Duponchelle
ba7136f70a Changelog update 2015-03-03 18:44:28 +01:00
Jeremy
dc2c592ee1 Bump to version 1.3alpha1 2015-03-03 10:43:44 -07:00
Julien Duponchelle
f910eb7946 Fix tests 2015-03-03 15:09:15 +01:00
Julien Duponchelle
d72db0db77 Fix GUI 2015-03-03 15:08:42 +01:00
Julien Duponchelle
a251ec7739 Hide cloud memu 2015-03-03 11:46:11 +01:00
grossmj
a55d0e3b04 Fixes some more path initialization issues. 2015-03-02 23:34:21 -07:00
grossmj
5dc5f31d07 Check local server path is valid and fixes issues when starting on a clean system. 2015-03-02 22:54:53 -07:00
Jeremy
f97efabcdb Reload the server config only once when clicking on apply or ok in the preferences. 2015-03-02 15:42:47 -07:00
Jeremy
ba7995ab3f Prevent users to use the unfinished cloud integration. 2015-03-02 14:59:10 -07:00
Jeremy
bb1723e2bb Fixes old projects loading issue with Qemu. 2015-03-02 14:37:48 -07:00
Julien Duponchelle
95866fa5c2 Fix reopening of qemu topo 2015-03-02 21:15:53 +01:00
Julien Duponchelle
8a19456657 Reload config via API 2015-03-02 21:09:17 +01:00
Julien Duponchelle
4e24a9f4dd Fix blocking application when the server is dead 2015-03-02 19:34:52 +01:00
Julien Duponchelle
7a5f2412c0 Fix copy paste in GNS3 console
Fix #192
2015-03-02 19:14:39 +01:00
grossmj
cf334b1ea4 Check if executable path is set before os.path.exists() 2015-03-02 09:42:37 -07:00
grossmj
eb5a723991 Fixes executable path bugs (when shutil.which returns None). 2015-03-02 09:40:07 -07:00
grossmj
02e71a79bf Fixes auto save for converted projects. 2015-03-01 21:16:22 -07:00
grossmj
8eae452765 Fixes local server shutdown. 2015-03-01 21:14:27 -07:00
grossmj
05dea91c93 Fixes style loading. 2015-03-01 19:28:20 -07:00
grossmj
3f4dd04461 Check executable paths are valid when launching the GUI and find them if necessary. 2015-03-01 17:31:53 -07:00
grossmj
c2bbf98947 Fixes relative path in project file for IOU images. 2015-03-01 16:24:26 -07:00
grossmj
65be634999 Device IDs were not restored. 2015-03-01 13:05:04 -07:00
grossmj
c027648cb7 Bump to version 1.3.dev3 2015-02-28 21:39:52 -07:00
grossmj
96ff09885d Fixes image loading & some cleaning. 2015-02-28 21:35:47 -07:00
grossmj
cc08b18e9e Fixes WIC ports were not created. 2015-02-28 18:57:22 -07:00
grossmj
73186a771e Optional AUX console port allocation for Dynamips VMs. 2015-02-28 16:20:27 -07:00
grossmj
c7a266cdfc Fixes picture save and load in projects. 2015-02-28 14:58:58 -07:00
grossmj
a74b749421 Auto start the local server by default. 2015-02-28 14:52:32 -07:00
Jeremy
37a87dbdee Sync Dynamips config file. 2015-02-27 19:36:21 -07:00
Jeremy
054b9e3dd2 Some changes with config files on Windows. 2015-02-27 18:08:34 -07:00
Jeremy
9694eb5940 Delete temporary projects after the path has been changed on the server. 2015-02-27 16:50:19 -07:00
Jeremy
dafb36e3e9 Normalize paths in the local server config file on Windows. 2015-02-27 13:27:40 -07:00
Julien Duponchelle
364c771b96 Turn off pep8 verification in travis because the test are already slow
to run
2015-02-27 17:25:18 +01:00
Julien Duponchelle
93ba13b6a9 Try to fix a strange error in travis build 2015-02-27 17:01:41 +01:00
Julien Duponchelle
1969ad8dd9 Add Changelog file 2015-02-27 16:14:14 +01:00
Julien Duponchelle
0f1713ef32 Use the same logging code for gui and server
We have no longer references to tornado in the source
code.
2015-02-27 15:48:20 +01:00
Julien Duponchelle
4ddda18d5b Fix crash if you don't have gns3converter 2015-02-27 15:47:44 +01:00
Julien Duponchelle
7df1e92a36 Fix crash after creation of a link to a blank area
Fixes #191
2015-02-27 14:32:16 +01:00
Julien Duponchelle
998794e11e Keep path of vpcs startup file 2015-02-27 14:32:16 +01:00
grossmj
06036c41cd Fixes regression with Dynamips router. 2015-02-26 22:59:01 -07:00
Jeremy
cab6b7783b Do not hide the server console on Windows when debugging. 2015-02-26 19:29:38 -07:00
Jeremy
8abfe5ff7d Default style is now "Classic" on Windows. 2015-02-26 17:17:52 -07:00
Jeremy
9ce152bc42 Reactivates built-in module + some cleaning. 2015-02-26 16:38:02 -07:00
Jeremy
fb8ce37e4d Set the node name in setup. 2015-02-26 16:18:54 -07:00
Julien Duponchelle
b16d756941 Automatically save a converted project #189 2015-02-26 17:11:51 +01:00
Julien Duponchelle
72ad516140 Fix tests 2015-02-26 10:52:03 +01:00
Jeremy
56ed695544 IOU + VirtualBox conversion of old projects. 2015-02-25 18:55:35 -07:00
Jeremy
f567ab8b11 Fixes issue #184 (broken snapshots support). 2015-02-25 16:49:53 -07:00
Jeremy
968b879b0b Do not create the project instance twice when loading one. 2015-02-25 16:09:53 -07:00
Jeremy
05ffa8bc03 Fixes typos "egals" -> "equals". 2015-02-25 11:53:39 -07:00
Jeremy
ac4bfcb098 Allow for having no base configs for IOS and IOU. Fixes #144. 2015-02-24 16:45:55 -07:00
Julien Duponchelle
2be612e042 Crash report for GUI 2015-02-24 20:26:17 +01:00
Julien Duponchelle
1b1d7d9481 Report error setting from the GUI 2015-02-24 19:45:29 +01:00
Daniel Lintott
12ab8612cb Add GNS3 converter version to console version output 2015-02-24 15:40:52 +01:00
Julien Duponchelle
71696ab48b Fix race condition in project opening
Fixes #186
2015-02-24 15:34:33 +01:00
Julien Duponchelle
6d7e05a9e0 Fix the bug which prevent GUI close if server is dead
Fixes #185
2015-02-24 14:51:54 +01:00
Jeremy
82e13c7bed Move projects_path to the local server settings.
Properly start & stop the local server from the preferences.
2015-02-23 17:07:50 -07:00
Jeremy
df27824e3f Do not alter the scene when taking a screenshot. 2015-02-23 12:36:00 -07:00
Julien Duponchelle
fac0ccfe68 Note topology revision 2015-02-23 19:41:20 +01:00
Julien Duponchelle
d38536ff75 PEP8 2015-02-23 18:24:14 +01:00
Julien Duponchelle
56e0cafe0d Remove non pertinent TODO after test 2015-02-23 18:20:58 +01:00
Julien Duponchelle
c55bbe339f Fix tests 2015-02-23 17:49:04 +01:00
Julien Duponchelle
84ed6cd722 Drop qemu unused preferences page 2015-02-23 17:37:29 +01:00
Jeremy
dbcf8beda9 Restore the scene rect after a screenshot.
fixes idle-pc save to image ref.
2015-02-22 20:14:59 -07:00
Jeremy
dbe37d6bc0 Fixes aiohttp.errors.ClientDisconnectedError errors when SIGINT is received. 2015-02-22 12:36:44 -07:00
Jeremy
73b5652b5c Default NVRAM and Idle-PC for some IOS images. 2015-02-21 17:24:40 -07:00
Jeremy
2fea220ed8 Idle-PC and auto idle-pc for Dynamips. 2015-02-20 16:53:51 -07:00
Julien Duponchelle
8457854483 Zuper progress dialog, with progress bar when multiples queries waiting 2015-02-20 21:31:44 +01:00
Julien Duponchelle
f00ad62b96 Fix crash when click on blank project and after that you cancel 2015-02-20 17:44:00 +01:00
Julien Duponchelle
cd65f4c4d7 Qemu support 2015-02-20 17:31:49 +01:00
Julien Duponchelle
f9f4c59e55 Ignore Qt creator autosave files 2015-02-20 17:31:48 +01:00
Jeremy
402505e2cb Idle-PC proposals for Dynamips. 2015-02-19 19:14:30 -07:00
Jeremy
4b13e4f7c6 Fixes node configurator & new settings. 2015-02-19 17:28:42 -07:00
Jeremy
d0e9cc44e0 Dynamips import/export configs. 2015-02-19 16:04:15 -07:00
Jeremy
9af4e0e15e Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-02-18 18:40:16 -07:00
Jeremy
c2f77ba39f Fixes capture directory path. 2015-02-18 18:40:01 -07:00
grossmj
7db4e397f0 Set progress dialog timer to 500ms. 2015-02-18 17:54:51 -07:00
Jeremy
399db108f3 Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-02-18 14:11:13 -07:00
Julien Duponchelle
9de5e5f984 One click exit ! Lazy people will be happy 2015-02-18 21:38:37 +01:00
Jeremy
30505269a6 Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-02-18 13:26:56 -07:00
Julien Duponchelle
7b1f1268fc Progress dialog is back 2015-02-18 20:49:20 +01:00
Jeremy
fd23957e2e Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-02-18 12:48:42 -07:00
Julien Duponchelle
98dc5890fd Revert "Progress dialog"
This reverts commit 4e055a3eb0.
2015-02-18 20:47:40 +01:00
Jeremy
4a1eeeedd1 Merge remote-tracking branch 'origin/rest-api' into rest-api
Conflicts:
	gns3/http_client.py
2015-02-18 12:39:04 -07:00
Jeremy
bf3d11cbdc Fixes UDP allocation HTTP call with context. 2015-02-18 12:38:29 -07:00
Julien Duponchelle
4e055a3eb0 Progress dialog 2015-02-18 19:36:45 +01:00
Julien Duponchelle
e703f220ca Fix missing context 2015-02-18 18:24:31 +01:00
Julien Duponchelle
9e4ec60d47 A work in progress, progress dialog 2015-02-18 17:28:24 +01:00
Julien Duponchelle
6ea960f2b7 Fix IOU image dir 2015-02-18 16:45:39 +01:00
Julien Duponchelle
2d98d34137 Restore progress dialog, full credit to jeremy :) 2015-02-18 16:18:45 +01:00
Julien Duponchelle
42c2aec975 Fix bad location of the gns3_gui.conf file on OSX 2015-02-18 15:26:41 +01:00
Julien Duponchelle
b0f062234b Cleanup 2015-02-18 15:23:11 +01:00
Julien Duponchelle
16b3cb581b Set le répertoire des images IOU 2015-02-18 12:23:28 +01:00
Julien Duponchelle
65e5bc8da0 Fix tests 2015-02-18 11:30:44 +01:00
grossmj
82815cd697 Remove Dynamips hypervisor port range option. 2015-02-17 23:12:13 -07:00
Jeremy
87cabfeaeb Use context instead of partials for HTTP queries. 2015-02-17 18:39:09 -07:00
Julien Duponchelle
4dcd5712e8 Support initial config content 2015-02-17 18:22:50 +01:00
Julien Duponchelle
04a63d5e17 Fix a bug where remote server as seen as a local server 2015-02-17 15:29:44 +01:00
Julien Duponchelle
6b330eccef Fix tests after settings changes
@grossmj we need to discuss about the image directory
2015-02-17 15:17:24 +01:00
Julien Duponchelle
3b5a0a3067 Support IOU capture. Create a notion of context for HTTP queries 2015-02-17 11:34:55 +01:00
Jeremy
9c9c216f6c Save Qemu VMs using LocalConfig instead of QSettings. 2015-02-16 18:46:27 -07:00
Jeremy
e4cdecf653 Save IOU devices using LocalConfig instead of QSettings. 2015-02-16 18:36:46 -07:00
Jeremy
544e11ac9c Save Dynamips VM configs when closing a project. 2015-02-16 18:21:10 -07:00
Jeremy
3fe6f27c57 Save Dynamips routers using LocalConfig instead of QSettings. 2015-02-16 17:59:40 -07:00
Jeremy
c35a911d36 Adapter settings and configs for Dynamips VMs. 2015-02-16 16:53:50 -07:00
Jeremy
e7bb823677 readBaseConfig method for VMs 2015-02-16 13:10:21 -07:00
Julien Duponchelle
f79d7b8550 Support old IOU topology loading 2015-02-16 15:45:25 +01:00
Julien Duponchelle
11e5ebeacf Travis very verbose 2015-02-16 15:06:15 +01:00
Julien Duponchelle
2ed3da2328 Save initial config path in the topology 2015-02-16 11:44:46 +01:00
Julien Duponchelle
3d0a30e38c PEP8 2015-02-16 10:33:45 +01:00
grossmj
a8a8cd8158 Dynamips devices packet capture. 2015-02-15 17:45:53 -07:00
grossmj
b518520dd6 Dynamips devices support (packet capture to complete). 2015-02-15 12:18:12 -07:00
Julien Duponchelle
9e7662c255 Upload initial_config 2015-02-14 10:53:13 +01:00
Jeremy
0b70872163 Packet capture for Dynamips VMs. 2015-02-13 15:41:56 -07:00
Julien Duponchelle
cc3999e9f6 Slot => adapter 2015-02-13 19:46:08 +01:00
Julien Duponchelle
aa3e137c9a Fix IOU loading in GUI 2015-02-13 17:39:45 +01:00
Julien Duponchelle
c5dbf2d54d Compatible with PEP8 1.6 2015-02-13 11:23:32 +01:00
Julien Duponchelle
5770cfad3b PEP8 2015-02-13 10:51:15 +01:00
grossmj
9204ffae78 Successfully create a Dynamips router from the GUI via HTTP 2015-02-12 19:24:40 -07:00
Julien Duponchelle
5340ea400c Support network for IOU 2015-02-12 22:27:10 +01:00
Julien Duponchelle
990ccee91d Successfully create an iou device from the GUI via HTTP 2015-02-12 21:57:28 +01:00
grossmj
837885cb04 Fixes missing Node references. 2015-02-12 11:49:09 -07:00
Jeremy Grossmann
af00609edc Merge pull request #181 from GNS3/refactor_base_vm
Move duplicate code to node.py
2015-02-12 18:13:36 +00:00
Julien Duponchelle
8cf974701a Create a VM class 2015-02-12 19:04:54 +01:00
Julien Duponchelle
82cd586950 Move duplicate code to node.py 2015-02-12 14:22:18 +01:00
Julien Duponchelle
e7f74373dd Drop console port settings, now it's global 2015-02-12 11:05:53 +01:00
grossmj
a9bb8f7130 Prevent the scroll bars to be shown in the news dock widget. 2015-02-10 21:44:39 -07:00
Julien Duponchelle
68a084911d Merge branch 'allow_no_local_server' into rest-api 2015-02-10 16:52:21 +01:00
Julien Duponchelle
d02bb86083 Avoid side effect in test 2015-02-10 16:52:14 +01:00
Julien Duponchelle
408291403b Clean tests 2015-02-10 16:51:49 +01:00
Julien Duponchelle
5afe8d2805 Fix crash when changing server binary 2015-02-10 16:51:26 +01:00
Julien Duponchelle
1482b65c64 /version JIT 2015-02-10 16:40:46 +01:00
Julien Duponchelle
84173e2933 PEP 8 & tests 2015-02-10 11:09:08 +01:00
Jeremy
a0bd0c422e Create the directory for the gns3_gui.conf file. 2015-02-09 18:22:39 -07:00
Julien Duponchelle
6ebbc369ca WIP for allowing usage without a local server 2015-02-09 23:34:44 +01:00
Julien Duponchelle
72fa14cb8f Avoid side effect in test 2015-02-09 22:47:59 +01:00
Jeremy
7bed153cc8 Start local server with correct host/port (127.0.0.1:8000 by default). 2015-02-09 13:43:52 -07:00
Julien Duponchelle
07f0ccacb6 Fix bug of creation of recursive directory at topology opening 2015-02-09 18:56:20 +01:00
Julien Duponchelle
b95f75354e Reset HTTPCLient internal state between tests 2015-02-09 11:15:14 +01:00
Julien Duponchelle
15bf587616 Fix crash in tests 2015-02-09 10:45:36 +01:00
grossmj
e6dc1b5b09 Recent files with the new JSON local config. 2015-02-08 15:05:44 -07:00
grossmj
0839b06ec2 VirtualBox packet capture. 2015-02-08 14:44:56 -07:00
grossmj
67e9410f43 Transitioning to a JSON based config (away from QSettings). 2015-02-08 12:48:45 -07:00
grossmj
789409f74f Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-02-06 17:31:34 -07:00
grossmj
141d588596 VirtualBox implementation complete. 2015-02-06 17:31:13 -07:00
Julien Duponchelle
3a6a11bab3 Close project on all servers 2015-02-06 22:50:12 +01:00
Julien Duponchelle
bc17f8c865 Virtualbox support remote servers 2015-02-06 21:50:42 +01:00
Julien Duponchelle
9b434d4928 VPCS support remote server 2015-02-06 17:35:31 +01:00
Julien Duponchelle
56bbe64b35 The project class know if a project is created on remote server 2015-02-06 16:46:19 +01:00
Julien Duponchelle
5504e0e7b7 Fix an error in server config file writting 2015-02-06 14:47:00 +01:00
Julien Duponchelle
890c211fe2 Drop -files 2015-02-06 12:12:21 +01:00
Julien Duponchelle
14be61b5d8 PEP8 2015-02-06 12:03:01 +01:00
Julien Duponchelle
5455689f9b Save as ok? 2015-02-05 19:22:43 +01:00
Julien Duponchelle
68e10ea066 Solve a bug of double temporary project creation at startup 2015-02-05 14:26:16 +01:00
Julien Duponchelle
c2d3a2d94f Save as anonymous work 2015-02-05 11:38:41 +01:00
Julien Duponchelle
3905b9e089 Add travis badges 2015-02-05 10:56:27 +01:00
Jeremy
ce15caed4f Use deleteLater() for threads. 2015-02-04 19:04:37 -07:00
Jeremy
1c51219f40 Add project_id in all VM calls. 2015-02-04 17:13:35 -07:00
Julien Duponchelle
85d8446e93 Support temporary project Work in progress 2015-02-04 22:51:13 +01:00
Jeremy
83b5812ade Fixes merge issues. 2015-02-04 14:27:30 -07:00
Jeremy
488e26af6d Merge remote-tracking branch 'origin/rest-api' into rest-api
Conflicts:
	gns3/project.py
2015-02-04 13:53:39 -07:00
Jeremy
41549ae60d Explicit ID names, remove {uuid} from URLs and add vms in URLs for VMs. 2015-02-04 13:48:29 -07:00
Julien Duponchelle
1ede748d81 Display copyright 2015 in the console view 2015-02-04 19:40:38 +01:00
Julien Duponchelle
5913ba9491 Fix crash after previous commit 2015-02-04 19:38:46 +01:00
Julien Duponchelle
caaad2da85 Drop temporary directory settings in UI 2015-02-04 18:29:02 +01:00
Julien Duponchelle
143318dd34 Project commit 2015-02-04 18:05:07 +01:00
Julien Duponchelle
1d48e27c80 Api v1 2015-02-04 10:36:41 +01:00
Julien Duponchelle
c6ea09a031 Fix topology test 2015-02-04 09:17:03 +01:00
Jeremy
d75eca55ad Use project_id instead of project_uuid for the API. 2015-02-03 18:40:13 -07:00
Jeremy
e8432d0000 Change URL for projects: /project becomes /projects and project_id is used instead of uuid. 2015-02-03 18:23:11 -07:00
Julien Duponchelle
276f9dbfdb Fix project reopen 2015-02-03 22:28:20 +01:00
Julien Duponchelle
cf1a5ba382 Fix segfault 2015-02-03 20:17:22 +01:00
Julien Duponchelle
c551db1556 Do not send base config when reloading a VPCS 2015-02-03 20:12:28 +01:00
Julien Duponchelle
0caf3ea31a In case of error during project close continue. 2015-02-03 16:17:47 +01:00
Julien Duponchelle
a1bd6e34cc Cleanup temporary project code 2015-02-03 15:21:51 +01:00
Julien Duponchelle
c8d1c60bd8 This should improve travis build speed 2015-02-03 14:54:03 +01:00
Julien Duponchelle
41b2f64db4 Fix SIP version for build 2015-02-03 14:28:56 +01:00
Julien Duponchelle
3fc011e75e Fix travis build
Thanks to @dlintott
2015-02-03 14:24:24 +01:00
Julien Duponchelle
42a31a4479 Fix segfault 2015-02-03 11:37:35 +01:00
Julien Duponchelle
b044ff5f35 Update pyqt in build 2015-02-03 11:36:36 +01:00
Julien Duponchelle
843463a97f Auto pep8 2015-02-03 10:55:59 +01:00
Julien Duponchelle
c14765f69d Reuse old project uuid when reopen a topology 2015-02-03 10:48:06 +01:00
Jeremy
35e1b194c1 Fixes problem when retrieving the VirtualBox VM list. 2015-02-02 18:55:18 -07:00
Jeremy
912c2aeb03 Only save the necessary settings in the server config file. Rename setting path to vpcs_path. 2015-02-02 15:00:16 -07:00
Julien Duponchelle
25eeea20c7 Project uuid is loaded from topology.
A bug prevent the project restoration, this require more investiguation
2015-02-02 20:10:03 +01:00
Julien Duponchelle
67f5964aff Fix topology test 2015-02-02 19:44:39 +01:00
Julien Duponchelle
0bf7933d4d Drop project_settings Part 2 2015-02-02 17:19:07 +01:00
Julien Duponchelle
c5e868dc1b Drop project_settings PART 1 2015-02-02 16:20:17 +01:00
Jeremy
5f7e80643a Save port ranges in the config file. 2015-02-01 20:44:43 -07:00
Jeremy
bcd85eec82 Local server auto start. 2015-02-01 17:42:28 -07:00
Jeremy
55667b78df Clean local server settings save and load. 2015-02-01 17:39:23 -07:00
Jeremy
0ac429a0b6 New ConnectToServer to wait for a server connection to be complete. 2015-02-01 17:32:06 -07:00
Jeremy
bbc51b83b8 Use LocalServerConfig for VPCS and VirtualBox. Move port ranges in the local server preferences. 2015-01-31 19:49:46 -07:00
Jeremy
d0c709fa2f LocalServerConfig to load/save local server settings. 2015-01-31 19:47:29 -07:00
Jeremy
0dfcbb778b Completing VirtualBox VM implementation. 2015-01-31 15:09:35 -07:00
Jeremy
6ed70380b6 Deactivate modules but VPCS and VirtualBox. 2015-01-31 14:00:09 -07:00
Jeremy
4d844a1608 Remove error code + more VirtualBox integration. 2015-01-30 19:37:17 -07:00
Jeremy
9af650def7 Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-01-30 14:41:56 -07:00
Jeremy
1935bbf510 Do not delete the QNetworkResponse in the slot connected to finished() signal. 2015-01-30 14:41:51 -07:00
Julien Duponchelle
eadfd7fd48 Fix double ask unsaved before close 2015-01-30 22:26:20 +01:00
Julien Duponchelle
1c33ad4527 Close windows close the projects 2015-01-30 21:47:06 +01:00
Julien Duponchelle
ac6cc76d67 Rename getter in order to follow project conventions 2015-01-30 18:08:18 +01:00
Julien Duponchelle
6adc8014da PEP 8 2015-01-30 17:53:14 +01:00
Julien Duponchelle
138df7c2c0 VPCS import config 2015-01-30 17:50:44 +01:00
Julien Duponchelle
efb8cbc9f4 Update VPCS 2015-01-30 16:31:00 +01:00
Julien Duponchelle
f0d03f2196 VPCS delete NIO 2015-01-30 10:56:50 +01:00
Julien Duponchelle
ed4077b1ff Test topology loading and signal mocking 2015-01-29 19:26:50 +01:00
Julien Duponchelle
20fe982df2 Topology open work 2015-01-29 17:22:42 +01:00
Julien Duponchelle
25c33b69f3 Test topology loading 2015-01-29 15:01:50 +01:00
Jeremy
722c8f38d1 GET, DELETE and PUT support for the http client. 2015-01-28 19:33:07 -07:00
Jeremy
3bb01d8eaf Ping between two VirtualBox VMs using REST API work. 2015-01-28 18:01:19 -07:00
Jeremy
d4d7c64442 Use UUID instead of vpcs_id and update post requests. 2015-01-28 17:57:52 -07:00
Jeremy
4c559f20a3 Optional body for post requests. 2015-01-28 17:54:22 -07:00
Julien Duponchelle
81fa1bc43f Pep8 2015-01-28 16:50:07 +01:00
Julien Duponchelle
0c63f37a8e Test dump topology 2015-01-28 16:45:29 +01:00
Julien Duponchelle
90d20b7e1a Capture log in py.test 2015-01-28 15:55:48 +01:00
Julien Duponchelle
1cad2a94ec Py test timeout 2015-01-28 15:54:44 +01:00
Julien Duponchelle
92d95bd585 Cleanup the HTTP client code 2015-01-28 13:50:21 +01:00
Julien Duponchelle
39da7cbe22 Exclude build from the travis PEP8 check 2015-01-28 13:16:57 +01:00
Julien Duponchelle
061c603831 Add pep8 as dev dependencies 2015-01-28 11:34:08 +01:00
Julien Duponchelle
8fb92a316a PEP8 2015-01-28 11:13:10 +01:00
Julien Duponchelle
527a571bf6 Improve tests for VPCS device 2015-01-28 10:36:55 +01:00
Jeremy
b2e81e3070 Merge remote-tracking branch 'origin/rest-api' into rest-api 2015-01-27 13:37:52 -07:00
Jeremy
1a389d68c5 Fixes logging to file and debug command. 2015-01-27 13:37:44 -07:00
Julien Duponchelle
5908b4aaf2 Fix travis tests 2015-01-27 19:22:43 +01:00
Julien Duponchelle
684781aadd Test VPCS 2015-01-27 19:14:30 +01:00
Julien Duponchelle
2b771772e2 Ping between two VPCS using REST API work 2015-01-27 16:04:24 +01:00
Julien Duponchelle
ff439a2b0b Turn off irc notification 2015-01-27 15:05:56 +01:00
Julien Duponchelle
ea8bcae586 Create a VPCS using the project uuid 2015-01-27 12:13:39 +01:00
Julien Duponchelle
3e7fff0c35 Ugly project creation when application start 2015-01-27 11:24:22 +01:00
Julien Duponchelle
81bd3b4893 Start posting data to rest api 2015-01-26 17:13:51 +01:00
Jeremy
68e9842bd9 Bump version to 1.2.3 2015-01-16 17:58:09 -07:00
Jeremy
54552031d8 Fixes broken -netdev + legacy virtio in Qemu support. 2015-01-16 17:44:07 -07:00
Jeremy
bfabccc60d Fixes bug with WICs interfaces no showing up in the port list. 2015-01-16 15:17:03 -07:00
Jeremy
17fe1df029 Fixes #175. 2015-01-16 11:36:44 -07:00
Jeremy
e10ccea86c Fixes #177 (broken ASA kernel/initrd) file browsers). 2015-01-16 10:51:07 -07:00
Jeremy
fa470bd8bf Fixes missing devices from the node view that use a remote server. 2015-01-16 10:43:25 -07:00
Jeremy
9b7a2cda15 Bump version to 1.2.2 2015-01-15 17:44:10 -07:00
Jeremy
d0d60d26da Fixes problem when comparing directories on Windows. 2015-01-15 16:01:06 -07:00
Jeremy
b2c14c1218 Copy images to their default directory (if chosen by the user). No more symlinks. 2015-01-15 15:26:56 -07:00
Jeremy
2d59dc2c72 Fixes bug when IOS router slot1 doesn't exist. 2015-01-15 11:24:07 -07:00
Jeremy
bb48cdf0a0 Update the VM name in VirtualBox for linked clones. 2015-01-14 16:48:32 -07:00
Jeremy
e00dcbcd92 Do not make SuperPutty the default console on Windows. 2015-01-12 17:48:32 -07:00
Jeremy
5ab7d6e94e Fixes resource path when frozen. 2015-01-12 17:23:51 -07:00
Jeremy
d1da9adc88 Adds Julien in the About dialog. 2015-01-12 16:50:26 -07:00
Jeremy
1455babd62 Bump version to 1.2.2.dev2 2015-01-12 16:26:40 -07:00
Jeremy
fc8529323c Fixes bugs when changing the hostname for Dynamips switches and hub. 2015-01-12 15:07:48 -07:00
Jeremy
f9130794ee Fixes bug when changing the hostname of a cloud or host. 2015-01-12 14:50:57 -07:00
Jeremy
e62d6c0edd Adds change hostname action and VirtualBox name in tooltip. 2015-01-11 18:25:36 -07:00
Jeremy
8d1dc4b090 Fixes blocked console. 2015-01-11 14:40:46 -07:00
Jeremy
acf6cf6ea2 Fixes base config dir path. 2015-01-08 12:42:01 -07:00
Jeremy
d9ee44f90a Default jungle news image. 2015-01-07 17:52:11 -07:00
Jeremy
bd6da5db9a Updates default jungle news image. 2015-01-07 16:03:06 -07:00
Jeremy
4b3ade9b48 Fixes default news loading on Windows. 2015-01-06 19:18:33 -07:00
Jeremy
9daed7e0d4 Adds short port names to the topology summary. 2015-01-06 18:41:44 -07:00
Jeremy Grossmann
4ef61e7af1 Merge pull request #159 from shmygov/vboxuser
Run VirtualBox as another user
2015-01-05 16:19:10 -07:00
Jeremy
851f2d0517 Put base configs into a base_configs directory. 2015-01-05 15:32:01 -07:00
Jeremy
5e5e04de8e Fixes #167 2015-01-04 19:01:33 -07:00
Jeremy
e8b2f952af Support for IOURC file on the server side. 2015-01-04 15:59:00 -07:00
Jeremy
85b5d10e5a Bump the maximum network adapters to 32 for Qemu. 2015-01-03 16:16:07 -07:00
Jeremy
b916ca7bfb EtherSwitch routers can be added and configured like other IOS routers. 2014-12-31 12:29:38 -07:00
Jeremy
46190154f6 Fixes broken file browsers in QEMU wizard. 2014-12-30 17:20:18 -07:00
Jeremy Grossmann
194552d2d3 Merge pull request #172 from planctechnologies/gns-137a
Fix cloud project load
2014-12-28 13:58:27 -07:00
Jerry Seutter
a736cbc4d5 Fix cloud project load 2014-12-28 13:22:00 -07:00
Jeremy
0310ecdfd0 Import & export config options in contextual device menu. 2014-12-26 20:33:35 -07:00
Jeremy
28bbc8bbe9 Refactor how to deal with initial base configs for IOS, IOU and VPCS. 2014-12-24 18:02:00 -07:00
Jeremy
f36ef66623 Copy base config templates to the directory where GNS3 settings are stored. 2014-12-24 17:19:16 -07:00
Jeremy
16ba51aa8c More checks on minimum RAM for IOS routers and updates default values to match the latest IOS image requirements. 2014-12-24 15:46:59 -07:00
Jeremy
52847d1fad Auto start project support. 2014-12-24 14:13:59 -07:00
Jeremy
4733cc8a3e Fixes SuperPutty command line to connect to devices with spaces in their hostname. 2014-12-24 13:51:47 -07:00
Jeremy
aecf61135f Merge remote-tracking branch 'origin/master' 2014-12-24 13:12:19 -07:00
Jeremy
252d86eb70 Avoid uninitialized nodes to be saved in the project file. 2014-12-24 13:12:10 -07:00
grossmj
438b0fe9d3 Adds more network interface options to the Qemu VM configuration Ui as well as descriptions for all NICs. 2014-12-23 18:34:40 -07:00
grossmj
f6c58b5a28 Gives the possibility to apply or not the same text to all selected items when editing notes. 2014-12-23 15:46:13 -07:00
Jeremy Grossmann
dee2f94c38 Merge pull request #171 from shmygov/suspendqemu
Add QEMU monitor port to control running QEMU VMs.
2014-12-23 12:28:05 -07:00
grossmj
1fc4dec5ca Fixes bug when importing Host node with UDP NIOs. 2014-12-23 11:24:28 -07:00
Dmitry Shmygov
d7ab12bc61 Add QEMU monitor port to control running QEMU VMs 2014-12-23 15:11:21 +03:00
Jeremy
1f50612a16 VPCS multi-host support. 2014-12-22 19:08:56 -07:00
Jeremy Grossmann
43715f1e34 Merge pull request #170 from noplay/fix_travis
Fix travis build
2014-12-22 09:20:54 -07:00
Julien Duponchelle
1bf0ff69d8 Fix travis build
The travis build is now working. But tests are failling, i
think it's normal and now we need to fix them.

I commented a test in cloud inspector because the test
run forever.
2014-12-22 10:51:54 +01:00
Jeremy
abf992dfb8 Fixes problem with SuperPutty. Make it the default on Windows. 2014-12-20 17:21:33 -07:00
Jeremy
707dfee696 Prevents application to crash on Windows when importing GNS3 config file. 2014-12-20 16:47:02 -07:00
Jeremy
e8c4f059c0 Set 5 seconds timeout for local server connection. 2014-12-19 17:40:58 -07:00
Jeremy
1a6f80f2df Auxiliary console support for IOS routers. 2014-12-19 15:43:15 -07:00
Jeremy
47ae310ac7 Check if any device runs and warn the user before closing a project. 2014-12-17 17:53:27 -07:00
Jeremy
923c61f9c7 Restore the debug level status when starting. 2014-12-17 17:26:51 -07:00
Jeremy
18b8c558cd Merge remote-tracking branch 'origin/master' 2014-12-17 16:09:20 -07:00
Jeremy
84a091e380 Fixes resource access on Mac OS X. Adds a base configs dir in the GNS3 project directory and copy IOS base configs there. 2014-12-17 16:09:08 -07:00
grossmj
1399098e30 Automatically select the symbol and category corresponding the edited item in the symbol selection dialog. 2014-12-16 21:51:06 -07:00
Jeremy
593f8add5d Auto screenshot when saving a project. 2014-12-15 18:14:33 -07:00
Jeremy
2f26624f29 Sync MainWindow Ui. 2014-12-15 17:08:18 -07:00
Jeremy
14c901d219 Merge pull request: Migrate cloud project to local #169 2014-12-15 17:05:53 -07:00
Jeremy
2b2e45ca45 Merge pull request: Move local project to cloud #168 2014-12-15 17:00:23 -07:00
Jeremy
868e9a322e Scale SVG image to icon sizes. Fixes #124. 2014-12-15 16:53:13 -07:00
Jeremy Grossmann
d2f3f58de1 Merge pull request #166 from planctechnologies/gns-167
Fix ASA devices in qemu
2014-12-13 13:00:56 -07:00
Jeremy Grossmann
a69b3fcd11 Merge pull request #165 from planctechnologies/gns-165
Run VPCS devices on cloud servers
2014-12-13 13:00:29 -07:00
Jerry Seutter
a3505ee7f2 Spelling fix 2014-12-12 16:44:06 -07:00
Jerry Seutter
efe5e0e2c4 Update vpcs download location, fix error message 2014-12-12 16:42:47 -07:00
Jeremy
8745527c5d Catch OSError exception for subprocess calls. 2014-12-11 12:15:24 -07:00
grossmj
78b40df71e Have the classic icons a little less dark. 2014-12-10 15:20:03 -07:00
Jerry Seutter
9675619ab9 Run ASA devices 2014-12-09 13:38:21 -07:00
Jeremy Grossmann
68ca2c2be6 Merge pull request #162 from dlintott/fix_161
Fix logic when checking for transparency or border_style.
2014-12-09 12:35:29 -07:00
Daniel Lintott
835ecbb410 Fix logic when checking for transparency or border_style.
A value of 0 is valid for both transparency and border_style. Python evaluates 0 to be False.

Fixes #161
2014-12-09 15:22:20 +00:00
Jeremy Grossmann
22756a3c13 Merge pull request #160 from planctechnologies/dev
Warn when deleting cloud instance with running devices
2014-12-08 18:13:11 -07:00
Jerry Seutter
3c2fb04ed8 Added VPCS devices to cloud projects. 2014-12-08 17:20:54 -07:00
Jeremy
db5fb840a6 Darken classic style icons. 2014-12-08 14:34:15 -07:00
Jerry Seutter
65b05d707b Merge branch 'master' into dev 2014-12-08 14:26:09 -07:00
Dmitry Shmygov
1b972df7e2 Run VirtualBox as another user 2014-12-06 01:44:48 +03:00
Jeremy
40266c275d Bump version to 1.2.2.dev1 2014-12-05 13:53:31 -07:00
Jeremy
197db35c80 Disable cloud. 2014-12-04 12:50:50 -07:00
Jeremy
8771e1ace7 Bump version to 1.2.1 2014-12-04 12:49:40 -07:00
Jeremy
e6e1275ad2 Fixes missing options. 2014-12-04 12:35:36 -07:00
Jeremy
417dc0859b Use bundled Qemu on Windows and OSX by default and checks if remote server are registered. 2014-12-04 12:25:49 -07:00
Jeremy
806e1f29bb Bump version to 1.2.1.dev2 2014-12-02 18:52:28 -07:00
Jeremy
9724f5769d Support for CPU throttling and process priority for Qemu. 2014-12-02 18:12:37 -07:00
Jeremy
5a0c8914c4 Rename IOSv symbols + improve support for ASA on Windows. 2014-12-02 14:49:04 -07:00
Jeremy
c2e0a30da8 Merge pull request #157. 2014-12-02 12:37:21 -07:00
Jeremy
45ae4f20a0 Merge remote-tracking branch 'origin/master' 2014-12-02 12:34:06 -07:00
Jeremy
398826d7ef IOSv and IOSv-L2 integration. 2014-12-02 12:33:49 -07:00
grossmj
14e5f3bf74 Merge remote-tracking branch 'origin/master' 2014-12-02 11:51:32 -07:00
grossmj
57b1cbf41b Fixes SecureCRT command line. 2014-12-02 11:51:17 -07:00
Julien Duponchelle
51a0d88b9b Revert "Add start instructions for MacOSX"
This reverts commit 16d4d7d1ea.
2014-12-01 22:57:17 +01:00
Julien Duponchelle
16d4d7d1ea Add start instructions for MacOSX 2014-12-01 21:26:16 +01:00
Jerry Seutter
2affb1513d Merge branch 'dev' of github.com:planctechnologies/gns3-gui into dev 2014-12-01 09:42:21 -07:00
Jerry Seutter
214d4b2a9e Grammar fixes 2014-12-01 09:40:02 -07:00
jseutter
2f486d979b Merge pull request #48 from planctechnologies/gns-133
Gns 133 Deleting an instance orphans devices on canvas
2014-12-01 09:37:00 -07:00
grossmj
023c5fb99a Install scripts for Mac OS X. 2014-11-30 19:37:15 -07:00
grossmj
329ed371f9 Adds default path for VBoxManage on Mac OS X. 2014-11-29 16:42:57 -07:00
grossmj
0577bfbde3 Support for older Qemu versions like the 0.11.0 on Windows. 2014-11-29 14:11:51 -07:00
grossmj
3ce5c35143 Use PROGRAMFILES and PROGRAMFILES(X86) environment variables for console command lines on Windows. 2014-11-28 17:57:54 -07:00
Massimiliano Pippi
9258ef4bb3 do nothing if server is None 2014-11-28 17:08:39 +01:00
Massimiliano Pippi
e02facc170 remove devices when removing instances 2014-11-28 16:58:33 +01:00
Massimiliano Pippi
4dc76926ea remove nodes when removing instances 2014-11-28 16:56:05 +01:00
Massimiliano Pippi
ba6be7e987 utility methods for shutting down cloud servers 2014-11-28 16:55:36 +01:00
grossmj
6b2da1ec97 Fixes port sorting issues. 2014-11-27 11:34:01 -07:00
Jeremy Grossmann
6aa1b515c7 Merge pull request #154 from dlintott/master
Validate the Idle-PC value and display an error if invalid
2014-11-25 13:55:16 -07:00
Daniel Lintott
5d64ec1c8f Validate the Idle-PC value and display an error if invalid 2014-11-25 20:34:43 +00:00
Jeremy
e1b81fb931 Fixes PyQt module usage. 2014-11-25 11:54:35 -07:00
Jeremy Grossmann
c91752598c Merge pull request #153 from planctechnologies/dev
Remove image access server references
2014-11-25 11:51:07 -07:00
grossmj
708515925f Do not put space in VirtualBox linked VM names. 2014-11-24 20:11:34 -07:00
Jeremy
a61745f868 Fixes C7200 IO cards insert/remove issues and makes C7200-IO-FE the default. 2014-11-24 17:02:00 -07:00
Jeremy
2ca7af34df Load project from command line. Fixes #151. 2014-11-24 14:21:51 -07:00
jseutter
bd7e6f4e3e Merge pull request #47 from planctechnologies/gns-136
Gns 136 gui won't exit when telnet session open to device
2014-11-24 10:49:51 -07:00
jseutter
32e86d461e Merge pull request #46 from planctechnologies/gns-132
Gns 132 Remove IAS (Image Access Server) code
2014-11-24 10:23:37 -07:00
Massimiliano Pippi
66ea5ad979 close cloud server connections when gns3 exits 2014-11-24 12:47:56 +01:00
Massimiliano Pippi
ebfa80d444 return the list of cloud servers as a property 2014-11-24 12:47:06 +01:00
Massimiliano Pippi
4247cc819d removed references to the IAS server 2014-11-24 12:18:42 +01:00
Massimiliano Pippi
1f9f5bd734 hardcode Ubuntu image in cloud preferences 2014-11-24 12:11:36 +01:00
Jeremy
426d791eea Fixes #48, #152. 2014-11-23 19:26:37 -07:00
grossmj
30d99b812c Merge remote-tracking branch 'origin/master' 2014-11-23 19:04:35 -07:00
grossmj
981e55bc4d Use the Qt binding abstraction layer. 2014-11-23 19:04:11 -07:00
Jeremy
bab1090a25 Use SubprocessError to catch Subprocess exceptions. 2014-11-22 17:45:04 -07:00
Jeremy
84b5181fd8 Support for full screen mode (View -> Fullscreen). 2014-11-21 16:52:06 -07:00
Jeremy
222ebb58c0 Bump to version 1.2.1.dev1 and fixes vboxmanage lookup on Windows. 2014-11-20 19:01:00 -07:00
Jeremy
319ac95f8a Bump to version 1.2 2014-11-19 19:28:21 -07:00
Jeremy
0370d3084f Change how the local server is shutdown on Linux/OSX.
Some more style tweaks.
2014-11-19 19:11:51 -07:00
Jeremy
30cd030943 Charcoal style tweak for Mac OS X. 2014-11-19 18:08:51 -07:00
Jeremy
ee98a78264 Style improvements. 2014-11-19 17:34:02 -07:00
Jeremy
2abf316192 Classic style. 2014-11-19 14:55:28 -07:00
Jeremy Grossmann
25d1abcd6c Merge pull request #147 from vikram186/ui_fix
module/ios_preferences: Fix button state
2014-11-19 14:05:04 -07:00
Vikram Narayanan
3b823d9696 module/ios_preferences: Fix button state
Make the setEnabled to False when the list is empty

Signed-off-by: Vikram Narayanan <vikram186@gmail.com>
2014-11-19 21:03:24 +01:00
grossmj
7e13c2c67a Restore dock widgets. 2014-11-19 10:22:09 -07:00
Jerry Seutter
f5ad3a6a2e Merge branch 'master' into dev 2014-11-18 16:21:39 -07:00
Jerry Seutter
422af60827 Enabling cloud functionality 2014-11-18 16:21:17 -07:00
Jerry Seutter
9127321540 Merge branch 'master' into dev 2014-11-18 16:18:16 -07:00
Jeremy
ad57e3e9b6 Improvement for the charcoal style & style options move to general preferences. 2014-11-17 19:29:22 -07:00
Jeremy
ceacb5aceb Adds back missing start, stop and pause icons for the contextual menu. 2014-11-17 12:29:42 -07:00
jseutter
dcae059480 Merge pull request #44 from planctechnologies/gns-130
Gns 130: QThreads missing a parent QObject
2014-11-17 09:24:53 -07:00
jseutter
6d6603e013 Merge pull request #45 from planctechnologies/gns-131
Fix bug where new instances would not build.
2014-11-17 09:24:35 -07:00
Massimiliano Pippi
90fe8078c3 fixed transitions for custom instance states, fixes gns-131 2014-11-17 16:47:56 +01:00
Massimiliano Pippi
367fb32114 instance QThreads passing a parent 2014-11-17 14:24:03 +01:00
Massimiliano Pippi
b2b82afd71 fixed super() call, propagate parent 2014-11-17 14:23:52 +01:00
Jeremy
dc9f012d25 Bump to version 1.2.dev3 2014-11-15 16:47:30 -07:00
Jeremy
a21a397397 Linked clone support for VirtualBox (still problems with temporary projects). 2014-11-15 16:05:55 -07:00
Jeremy
fa86a04acc Fixes "don't show this again" for the getting started dialog. 2014-11-15 12:42:21 -07:00
Jeremy
4cf3f595d6 Fixes remote server issue when creating a new project while already in a project. 2014-11-14 19:59:06 -07:00
Jeremy
e619e56537 Shows cancel button in Wizards on OSX. Fixes crash on Windows 32-bit. 2014-11-14 10:18:36 -07:00
Jeremy Grossmann
0c9c81e9dc Merge pull request #142 from planctechnologies/pr3
Add support for Qemu devices on cloud instances (gui)
2014-11-12 21:20:51 -07:00
Jeremy Grossmann
3b5184b007 Merge pull request #141 from planctechnologies/pr2
Support IOU devices on cloud instances
2014-11-12 21:20:24 -07:00
Jeremy
0c6bfdafc3 Prepare new dark style. 2014-11-12 19:47:49 -07:00
Jerry Seutter
f64838ac59 Fix pull branch 2014-11-12 14:18:16 -07:00
Nasrullah Taha
53cfec5ce0 Merge pull request #43 from planctechnologies/gns-129
Move image path manipulation to server side
2014-11-12 11:56:42 -07:00
Nasrullah Taha
c9dfd99697 Merge branch 'dev' of github.com:planctechnologies/gns3-gui into dev 2014-11-12 11:41:30 -07:00
Jerry Seutter
3b29e898e4 Merge branch 'dev' of github.com:planctechnologies/gns3-gui into dev 2014-11-12 11:07:24 -07:00
Jerry Seutter
e89ad3ec4f Handle pre-existing ssh keys when creating an instance 2014-11-12 11:07:07 -07:00
Nasrullah Taha
c2a193cb8a Merge branch 'gns-125' into dev 2014-11-12 11:00:15 -07:00
Nasrullah Taha
26b668099c Merge pull request #38 from planctechnologies/gns-123
Add support for running IOU devices on cloud instances
2014-11-12 10:53:31 -07:00
Jeremy
f67f0f3768 Option to test IOS image from the wizard. 2014-11-10 18:55:41 -07:00
Jeremy
860873ac21 Adds gns3-converter as a dependency and finish integration. 2014-11-10 14:58:28 -07:00
Jeremy Grossmann
0472e4fddd Merge pull request #140 from planctechnologies/pr1
Instance inspector improvements
2014-11-10 11:56:28 -07:00
Jerry Seutter
4aa8f6f49a Do path manipulation server side, and remove UploadFileThread class 2014-11-10 11:30:11 -07:00
jseutter
4de3c78cfe Merge pull request #40 from planctechnologies/gns-106
Gns 106 list_instance failure causes missing server instances
2014-11-10 11:01:59 -07:00
jseutter
7df9316539 Merge pull request #42 from planctechnologies/gns-37a
Highlight devices running on instance
2014-11-10 11:00:15 -07:00
jseutter
c2b7a8e86f Merge pull request #41 from planctechnologies/gns-37
Gns 34 -  display the number of devices running on the instance
2014-11-10 09:21:02 -07:00
Massimiliano Pippi
144576ee86 emit signal when table is clicked, not when selection changes 2014-11-10 17:19:38 +01:00
Massimiliano Pippi
cabd57e5ab select nodes running on the selected cloud instance 2014-11-10 15:50:38 +01:00
Massimiliano Pippi
06c2d8d3e6 signal when an instance was selected/deselected 2014-11-10 15:50:38 +01:00
Massimiliano Pippi
f0845e2fff show number of devices running on each cloud instance, fixes gns-34 2014-11-10 11:45:35 +01:00
Massimiliano Pippi
e48d9d76b4 pass the instance id all the way down to the cloud server 2014-11-10 11:44:43 +01:00
Massimiliano Pippi
b250af6f26 populate model lazily, working even when first call to list_instances fails 2014-11-10 10:42:56 +01:00
Massimiliano Pippi
a7688cec8b return None instead of raising KeyError 2014-11-10 10:31:10 +01:00
Jeremy
ec07873990 Option to allow console connections to any local IP address when using the local server. 2014-11-09 23:01:13 -07:00
Jeremy
75cb485e6f Allows Qemu VM to have 0 interface. 2014-11-09 18:27:40 -07:00
Jeremy
4a7cc14270 Adds "open a project" and "recent projects" buttons to the new project dialog.
Option to deactivate the new project dialog at startup.
2014-11-09 18:27:16 -07:00
Jeremy
eca99ccd2c New host node (cloud with all Ethernet & TAP interfaces added). 2014-11-09 16:09:42 -07:00
Jeremy Grossmann
dd03139706 Merge pull request #138 from planctechnologies/dev
Fix cloud instance ready indicator
2014-11-09 11:51:49 -07:00
Jeremy
8ad391d2ab Base for VirtualBox linked clones (not completed yet). 2014-11-09 11:50:47 -07:00
Jerry Seutter
f7e53f685b Add support for running Qemu devices on a cloud instance 2014-11-08 09:02:51 -07:00
Jerry Seutter
0698b3942b Merge branch 'dev' into gns-125 2014-11-06 18:06:59 -07:00
Jerry Seutter
d866cedbca Merge branch 'master' into dev 2014-11-06 18:06:49 -07:00
Jerry Seutter
6105a1629f Merge branch 'dev' into gns-123 2014-11-06 16:28:12 -07:00
jseutter
8a49d90400 Merge pull request #37 from planctechnologies/gns-126
On cloud instances, only show the green icon when the build process is complete
2014-11-06 16:25:26 -07:00
Jerry Seutter
10dfd59203 Add support for running IOU devices on cloud instances 2014-11-06 16:07:40 -07:00
grossmj
afa91ef2f3 Merge remote-tracking branch 'origin/master' 2014-11-06 13:59:05 -07:00
grossmj
862d97b0a4 Rename "enable console" to "remote console". 2014-11-06 13:56:19 -07:00
Massimiliano Pippi
05a437e2fc fixed instance state handling 2014-11-06 09:33:13 +01:00
Massimiliano Pippi
6b679fc89e added a method to retrieve an instance by id 2014-11-06 09:33:13 +01:00
Jerry Seutter
9f3d831d4c Fixed bug when opening existing cloud projects 2014-11-05 10:07:13 -07:00
Jeremy Grossmann
1403c35443 Merge pull request #137 from planctechnologies/dev
Better tracking of live cloud instances
2014-11-05 09:25:12 -07:00
Jerry Seutter
d440d10371 Remove commented out code 2014-11-05 09:21:28 -07:00
jseutter
58a218f826 Merge pull request #36 from planctechnologies/gns-127
Better tracking of live cloud instances
2014-11-05 09:20:01 -07:00
Jerry Seutter
0756f9104e Call super in __init__ to keep Qt object tree intact 2014-11-05 09:19:45 -07:00
Jeremy
2847296cd4 Settings management refactoring and checks for name collisions. 2014-11-04 18:10:58 -07:00
Jeremy
61317fced0 New news dock widget. 2014-11-04 14:17:33 -07:00
Jeremy Grossmann
767d756ed4 Merge pull request #136 from planctechnologies/dev
Add a ENABLE_CLOUD global, add telnet over ssh support
2014-11-04 10:37:11 -07:00
grossmj
43f1c04d3e Merge remote-tracking branch 'origin/master' 2014-11-03 22:24:47 -07:00
grossmj
c985298c9a Fixes bug when editing a Qemu VM configured to run on a remote server. 2014-11-03 22:24:29 -07:00
Jerry Seutter
8e9574871b Better tracking of live cloud instances 2014-11-03 19:51:13 -07:00
jseutter
3536c0fc19 Merge pull request #35 from planctechnologies/gns-109
Gns 109 / Gns 95: Set up ssh tunnel for telnet session
2014-11-03 19:40:14 -07:00
Jeremy Grossmann
d196db8303 Merge pull request #135 from planctechnologies/cloud-run-merge
Run IOS devices on a cloud instance
2014-11-03 19:18:52 -07:00
Jeremy
18a4eeb6e9 Integrate GNS3 converter. 2014-11-03 17:35:23 -07:00
Jerry Seutter
cb29466e43 Add a ENABLE_CLOUD global 2014-11-03 16:40:42 -07:00
Jerry Seutter
58ad493e9e Merge branch 'master' into dev 2014-11-03 15:40:17 -07:00
grossmj
36b8092e53 Check for duplicate node names in Preferences. 2014-11-03 15:06:08 -07:00
Jerry Seutter
855b9901c7 Remove old comment 2014-11-03 11:45:13 -07:00
grossmj
f0f110b277 Show the Wireshark path when failing to open it. 2014-11-02 10:10:13 -07:00
grossmj
f0e51c59ff Make sure local paths are not sent to remote servers (i.e. Dynamips path). 2014-11-01 16:51:31 -06:00
Jeremy Grossmann
37b1c839e9 Merge pull request #134 from planctechnologies/cloud-export
Project import/export/delete in cloud files
2014-11-01 11:20:06 -06:00
Jerry Seutter
c4226315a5 Merge branch 'master' into cloud-export 2014-10-31 14:08:58 -06:00
Massimiliano Pippi
9fbf593db8 create a new endpoint on the tunnel when connecting via telnet to cloud devices 2014-10-31 17:10:55 +01:00
Massimiliano Pippi
79feec83fb return Endpoint instance instead of Endpoint ID when creating a tunnel 2014-10-31 17:09:34 +01:00
Jerry Seutter
b3b934847d Merge branch 'master' into dev 2014-10-31 10:03:04 -06:00
Massimiliano Pippi
9d71161a32 property to retrieve the tunnel 2014-10-31 16:38:52 +01:00
Massimiliano Pippi
7485fb968a disconnect tunnel when wss is closed 2014-10-31 16:38:39 +01:00
Massimiliano Pippi
4a39aad83d pass the ssh pkey all the way down to the wss and setup a tunnel upon wss connection 2014-10-31 16:35:19 +01:00
Massimiliano Pippi
56faee748e using relative import 2014-10-31 15:09:21 +01:00
Massimiliano Pippi
6577340e05 determine if node is on the cloud 2014-10-31 14:48:50 +01:00
Massimiliano Pippi
d5eef5a5f6 make iTerm work in a separate thread 2014-10-31 13:02:34 +01:00
Massimiliano Pippi
3347180a5a support Terminal sessions in a separate thread 2014-10-31 12:56:36 +01:00
Massimiliano Pippi
c4396fcac0 pass a callback to the telnet command 2014-10-31 12:56:04 +01:00
Massimiliano Pippi
418b912379 run telnet console in a separate thread 2014-10-31 12:39:16 +01:00
grossmj
7b6e32373a Fixes issue when getting the VirtualBox VM list. 2014-10-30 21:10:14 -06:00
Jeremy
c54de58a0d New VirtualBox support (under testing). 2014-10-30 18:53:17 -06:00
Jerry Seutter
7c21c7b29f Merge branch 'dev' of github.com:planctechnologies/gns3-gui into dev 2014-10-30 17:17:31 -06:00
Jerry Seutter
57ee86d251 Fix bug where images not found
Improve ssh_to_server script.
2014-10-30 17:15:59 -06:00
Nasrullah Taha
7c94595313 Merge pull request #34 from planctechnologies/gns-121
Start ios devices on a cloud instance
2014-10-30 13:16:10 -06:00
Jerry Seutter
2bbfefb5e1 Fix merge-induced error 2014-10-30 12:23:31 -06:00
Nasrullah Taha
e9850ee962 -adding root logger handler when no default exists
-fixes to ssh_to_server script for linux
-fixed callback for upload image thread
2014-10-30 12:10:14 -06:00
Jerry Seutter
4828b3a73b Fix bug where image wasn't being downloaded from cloud files 2014-10-29 15:18:23 -06:00
Jerry Seutter
de5e43578a Fix upload path 2014-10-29 10:36:44 -06:00
Jerry Seutter
15380ae80a Code cleanup 2014-10-28 12:11:22 -06:00
Jerry Seutter
e39c1f9579 Merge branch 'gns-110' into gns-121 2014-10-28 11:33:50 -06:00
Jerry Seutter
c0a7ed7a2c Merge branch 'dev' into gns-110 2014-10-28 11:00:14 -06:00
Jerry Seutter
e2be6bd0a9 Merge branch 'master' into dev 2014-10-28 09:32:38 -06:00
Jerry Seutter
6513acf141 Merge branch 'dev' into gns-118 2014-10-28 09:06:27 -06:00
grossmj
1c4ce90093 qemu-system-i386 is the new default on 32-bit platforms. 2014-10-27 21:58:32 -06:00
grossmj
adace0d6a1 Fixes platform detection issue with Cisco IOS image file name. 2014-10-27 19:58:07 -06:00
Jerry Seutter
a960ee05ce Fix missing dynamips symlink 2014-10-27 18:33:03 -06:00
Jerry Seutter
0b46653c79 Pull the server code from github. 2014-10-27 18:23:10 -06:00
Jerry Seutter
120cb89526 IOS devices can be deployed on cloud instances. 2014-10-27 18:11:39 -06:00
Jeremy
72c48968df Update README. 2014-10-27 15:58:13 -06:00
grossmj
2195a6199c Delay (default 500 ms) when Telneting to all nodes. 2014-10-26 19:28:08 -06:00
grossmj
509d5f8b82 Bump version to 1.2.dev1 2014-10-25 18:01:14 -06:00
jseutter
35fe0514ba Merge pull request #33 from planctechnologies/gns-60
GNS-60 Delete cloud project
2014-10-24 12:15:47 -06:00
Nasrullah Taha
98fd7b73b2 added delete cloud project option 2014-10-23 23:43:31 -06:00
grossmj
176bfe88ca Bump version to 1.1 2014-10-22 22:43:48 -06:00
grossmj
c261d2229d Warning message when using a remote server with IOU. 2014-10-22 22:42:36 -06:00
grossmj
99388cde15 Fixes more issues with EtherSwitch router. 2014-10-22 22:29:55 -06:00
grossmj
c07a81d228 Serial console for VirtualBox. 2014-10-22 21:59:11 -06:00
grossmj
6843b7acf2 Fixes EtherSwitch (until we come with a default template for it). 2014-10-22 20:48:46 -06:00
grossmj
1395a624f6 New Idle-PC dialog. 2014-10-22 18:06:37 -06:00
grossmj
bf27483965 Fixes #123 (Qemu binaries list not showing up). 2014-10-22 16:17:17 -06:00
Nasrullah Taha
00dfddde8a fixed tests broken by 9d0bd31 2014-10-22 15:37:07 -06:00
Nasrullah Taha
9d0bd31eea added project import dialog 2014-10-22 15:03:13 -06:00
grossmj
f721efd21c Fixes #119. 2014-10-22 13:18:56 -06:00
grossmj
571f7ac5af Fixes #126 (broken remote server feature). 2014-10-22 12:00:46 -06:00
grossmj
a409361049 Fixes #120 (broken cloud) 2014-10-22 10:56:34 -06:00
Massimiliano Pippi
b4e42f50ec redirect std error for gns3-server 2014-10-22 18:35:51 +02:00
Nasrullah Taha
c8ef818e1c merged dev into gns-59 2014-10-21 16:52:34 -06:00
Nasrullah Taha
d59a2bd7f9 added menu action and empty slot for importing project 2014-10-21 16:43:40 -06:00
Nasrullah Taha
e6cb49a19b added signals to update ui on progress 2014-10-21 16:43:03 -06:00
Jerry Seutter
fa8c166c18 Merge branch 'gns-121' into gns-110 2014-10-21 15:33:37 -06:00
Jerry Seutter
5ad6433e91 Handle opening existing projects 2014-10-21 15:17:49 -06:00
Jerry Seutter
ff4af1e22d Reuse cloud instances that are running when the gui is restarted 2014-10-21 14:39:08 -06:00
grossmj
46ece451ff Bump version to 1.1.dev1 (fixes #118). 2014-10-21 12:36:32 -06:00
Jerry Seutter
8a02288e28 Merge branch 'dev' into gns-121 2014-10-21 10:38:27 -06:00
grossmj
54f6e264cb Bump version to 1.1.dev1. 2014-10-21 10:02:07 -06:00
grossmj
2943a4e0df Polish and bump up to version 1.0! 2014-10-20 18:40:06 -06:00
Jerry Seutter
bf1a797519 Build instance dynamically from default ubuntu image (gns-121) 2014-10-20 17:07:15 -06:00
grossmj
534cff6be9 Possibility to configure a category for nodes (routers, switches, end devices or security devices). 2014-10-20 16:14:36 -06:00
Jeremy Grossmann
90067a2b38 Merge pull request #117 from AdrianSimionov/gns3-gui-0001
Added support for xfce4-terminal, for Xubuntu.
2014-10-20 10:30:17 -06:00
Adrian Simionov
ee371764d9 Added support for xfce4-terminal, for Xubuntu.
xfce4-terminal is the default terminal on Xubuntu, gnome-terminal is not installed.
2014-10-20 12:28:03 +02:00
grossmj
de5fd88ef6 Snapshots support. 2014-10-19 21:24:21 -06:00
grossmj
d72e129f3e Remote servers and load-balancing (still things to improve). 2014-10-19 17:29:04 -06:00
grossmj
c2ea5f68a7 GNS3 Jungle dock widget. 2014-10-18 15:21:12 -06:00
grossmj
78f9fc26ea Fixes #114. 2014-10-17 12:20:24 -06:00
grossmj
89bcd3e635 Merge remote-tracking branch 'origin/master' 2014-10-17 12:12:47 -06:00
grossmj
e07769ca89 Timeout for the getting started dialog. 2014-10-17 12:12:24 -06:00
Jeremy Grossmann
72a984fffa Merge pull request #111 from planctechnologies/dev
Restore remote server behaviour
2014-10-17 11:57:52 -06:00
Jeremy Grossmann
a9ab26e972 Merge pull request #113 from AdrianSimionov/master
Fix to include all files.
2014-10-17 11:50:38 -06:00
Nasrullah Taha
fddbe69ba0 added downloading image files used by the imported project 2014-10-17 10:38:38 -06:00
AdrianSimionov
7da9f25d73 Fix to include all files.
Extension of the file is not mandatory. All files filter should be "*" and not "*.*"
2014-10-17 12:53:38 +02:00
grossmj
741644ad69 Getting started HTML file. 2014-10-16 21:36:50 -06:00
grossmj
a01cc31a00 Getting started dialog. 2014-10-16 21:30:42 -06:00
Nasrullah Taha
1a154df621 changed download file method to skip downloading files if the same file already exists at the same local path 2014-10-16 13:15:08 -06:00
grossmj
8bf28a2b68 Analytics. 2014-10-16 08:42:10 -06:00
Jerry Seutter
e527b13930 Merge remote-tracking branch 'origin/gns-59' into gns-110 2014-10-15 15:34:32 -06:00
Jerry Seutter
aa3ec13e45 Move get_provider() out of utils.py 2014-10-15 15:33:51 -06:00
Nasrullah Taha
b7d7706682 added download file method to BaseCloudCtrl 2014-10-15 12:55:12 -06:00
grossmj
80b3b2818c Check for update feature. 2014-10-14 21:16:09 -06:00
grossmj
a6cca2943a Bump to version 1.0.dev1. 2014-10-14 17:47:52 -06:00
grossmj
10d6811283 Bump to version 1.0-beta4. 2014-10-14 17:20:28 -06:00
Nasrullah Taha
20bb456fa8 added method to BaseCloudCtrl that lists project zip files in projects folder in cloud storage 2014-10-14 16:13:57 -06:00
jseutter
031ca65dcd Merge pull request #31 from planctechnologies/gns53
GNS-53 Export project to cloud - Progress dialog
2014-10-14 15:13:35 -06:00
grossmj
c6af132c16 Add back temporary projects. 2014-10-14 14:34:38 -06:00
grossmj
165837ba03 Improvements on the IOS router wizard. 2014-10-14 13:55:22 -06:00
Jerry Seutter
f7e27b3e70 Merge from master 2014-10-14 13:54:15 -06:00
Nasrullah Taha
388e078d01 excluding large temporary files from project zip 2014-10-14 12:26:52 -06:00
Nasrullah Taha
1425fb5c53 Merge branch 'dev' into gns53 2014-10-14 10:52:41 -06:00
grossmj
76a6d09e98 Auto idle-pc feature and improvements/bug fixes for GNS3 preferences. 2014-10-13 19:53:17 -06:00
Nasrullah Taha
f9249bba7a added progress dialog box for project export 2014-10-10 13:04:40 -06:00
Jeremy Grossmann
4606e501bd Merge pull request #109 from planctechnologies/upstream-1
Backend support for exporting a project to cloud files
2014-10-10 10:52:51 -06:00
grossmj
33d524c7e7 Replace "..." by "Browse..." on buttons.
Fixes bugs with IOS routers slots/wics.
2014-10-10 10:51:39 -06:00
Jerry Seutter
b56e841e21 Merge 2014-10-10 10:41:25 -06:00
Jerry Seutter
9825cbab55 Merge branch 'upstream-1' into dev 2014-10-10 10:37:21 -06:00
Jerry Seutter
da7f46c733 Hide dynamips image server type 2014-10-10 10:28:24 -06:00
Jerry Seutter
806cd0bd0b Add in old remote server code 2014-10-10 10:25:02 -06:00
Jerry Seutter
ac21e351af Revert getRemoteServers call 2014-10-10 10:24:40 -06:00
Jerry Seutter
eaa60ce88a Restore remote server behavior 2014-10-10 10:24:10 -06:00
Jerry Seutter
5747dec094 Add server type ComboBox to IOS images preferences 2014-10-10 10:23:13 -06:00
jseutter
60035428d7 Merge pull request #28 from planctechnologies/gns53
GNS-53 Export complete local project to cloud
2014-10-10 10:14:41 -06:00
Jerry Seutter
865ae8445d Merge branch 'dev' into gns-118 2014-10-10 09:54:53 -06:00
jseutter
036ddf81b1 Merge pull request #30 from planctechnologies/gns-117
Restore getRemoteServer behavior
2014-10-10 09:13:07 -06:00
grossmj
a7e9a80d60 New look for IOS routers preferences. 2014-10-09 21:25:30 -06:00
Jerry Seutter
61d969b63a Add in old remote server code 2014-10-09 12:32:30 -06:00
Jerry Seutter
a4c5df8890 Revert getRemoteServers call 2014-10-09 12:18:52 -06:00
jseutter
29d484163d Merge pull request #29 from planctechnologies/gns-117
Restore remote server behaviour
2014-10-09 12:10:50 -06:00
jseutter
d4c3c90f14 Merge pull request #28 from planctechnologies/gns53
GNS-53 Export complete local project to cloud
2014-10-09 09:49:58 -06:00
Jerry Seutter
34ae3f389a Merge branch 'dev' into gns-117 2014-10-09 09:35:24 -06:00
Jerry Seutter
725de765b5 Merge branch 'master' into dev 2014-10-09 09:20:51 -06:00
Jerry Seutter
eed1558185 Restore remote server behavior 2014-10-09 09:20:18 -06:00
Nasrullah Taha
4473a40cdc Merge branch 'dev' into gns53 2014-10-08 14:56:55 -06:00
Nasrullah Taha
d7cbbfdf53 changed zipping project files to be platform independent 2014-10-08 14:54:12 -06:00
Nasrullah Taha
4eead2aeaf changed behaviour of uploading files to check checksum of files that already exist in cloud storage and overwrite files only when checksums are different from the local files' 2014-10-08 14:17:03 -06:00
grossmj
492dd33a74 New look for IOU devices preferences. 2014-10-07 21:47:51 -06:00
Jerry Seutter
8cecab16ed Merge branch 'dev' of github.com:planctechnologies/gns3-gui into dev 2014-10-07 15:51:13 -06:00
grossmj
734c5cffed New look for VirtualBox VMs preferences. 2014-10-07 15:13:32 -06:00
grossmj
d9b77f1755 Removes the temporary project feature. 2014-10-07 11:30:21 -06:00
grossmj
b20c14ef43 Merge remote-tracking branch 'origin/master' 2014-10-06 16:25:28 -06:00
grossmj
47c1c853e1 Fixes #105. 2014-10-06 16:25:13 -06:00
Jeremy Grossmann
9838e4a344 Merge pull request #102 from planctechnologies/dev
Fix bug where local server starting is broken
2014-10-06 11:54:02 -06:00
grossmj
fb929c664d New QEMU GUI. 2014-10-06 11:53:31 -06:00
jseutter
8c9a6a2dd8 Merge pull request #27 from planctechnologies/gns53
GNS-53 export project to cloud
2014-10-06 10:49:36 -06:00
Nasrullah Taha
f0cff8a25f merged dev into gns53 2014-10-06 10:39:24 -06:00
Jerry Seutter
596eeee426 Add server type ComboBox to IOS images preferences 2014-10-06 05:51:44 -06:00
Nasrullah Taha
1e8cff7630 bugfix: check if a node has an image before trying to upload it 2014-10-01 13:30:30 -06:00
Jerry Seutter
d25084982e Fix bug where local server starting is broken 2014-10-01 07:34:17 -06:00
grossmj
d1f8df6406 Fix apply in preferences dialog. 2014-09-30 21:20:18 -06:00
grossmj
a1adbf7b04 Improvements on the preferences dialog. 2014-09-30 19:59:15 -06:00
Nasrullah Taha
df50bca18c implemented uploading image files to cloud files if they don't already exist 2014-09-30 14:55:01 -07:00
grossmj
0942b0fae1 Fix missing paramiko module in setup.py and disable broken server version check. 2014-09-30 11:42:20 -06:00
Jeremy Grossmann
e92b06e98b Merge pull request #101 from planctechnologies/serverstart
Remote server start and ssh tunnel
2014-09-30 11:31:29 -06:00
Jeremy Grossmann
851023158f Merge pull request #100 from planctechnologies/security
Add SSL support to websocket connection
2014-09-30 11:29:43 -06:00
Jeremy Grossmann
9f6d74d83c Merge pull request #99 from planctechnologies/heartbeat
Send heartbeat messages from the gui to the server
2014-09-30 11:27:53 -06:00
Jeremy Grossmann
15fa5df2a2 Merge pull request #98 from planctechnologies/iasurl
Read the image access server URL from the config file
2014-09-30 11:26:59 -06:00
Jeremy Grossmann
3202c5bf9b Merge pull request #97 from planctechnologies/keypairs
ssh keypairs stored per-server
2014-09-30 11:26:05 -06:00
Jerry Seutter
f7e96e4867 Merge branch 'dev' into serverstart 2014-09-30 07:53:39 -06:00
Jerry Seutter
2ac865348a Merge commit '5c167ed' into security 2014-09-30 07:51:19 -06:00
Jerry Seutter
0f7b252ce2 Merge commit '930ddbc' into heartbeat 2014-09-30 07:48:41 -06:00
Jerry Seutter
7a7080822c Merge commit '31d49f1' into iasurl 2014-09-30 07:46:50 -06:00
Jerry Seutter
25e837b203 Merge commit '7918171' into keypairs 2014-09-30 07:43:33 -06:00
Jerry Seutter
a9f83e2b99 Merge branch 'dev' of github.com:planctechnologies/gns3-gui into dev 2014-09-30 07:23:29 -06:00
Jerry Seutter
931a22a261 Merge branch 'master' into dev 2014-09-30 07:23:14 -06:00
Michael
b98b3d3292 Merge pull request #25 from planctechnologies/gns-91a
Start gns3server on cloud instance and establish websocket connection
2014-09-29 19:56:21 -06:00
Jerry Seutter
aefdd9d23d Code review changes 2014-09-29 16:32:46 -06:00
grossmj
25eeaf1e05 Split the PATH environment variable using os.pathsep 2014-09-28 18:23:27 -06:00
Jerry Seutter
ff8c95e45e Reversion version number change 2014-09-26 18:28:06 -06:00
Jerry Seutter
4205658ccc websocket connection to cloud server 2014-09-26 18:17:12 -06:00
Nasrullah Taha
aa3207d84c implemented uploading zipped project files to cloud files 2014-09-24 12:38:16 -07:00
grossmj
f74dc93336 Bump to version 1.0-beta1.dev1. 2014-09-24 11:14:28 -06:00
grossmj
fdf7a97a8a Bump to version 1.0-beta3. 2014-09-24 11:01:33 -06:00
grossmj
b25c7391c9 QEMU VM suspend/resume not yet supported. 2014-09-24 10:57:12 -06:00
grossmj
ab0289a0d2 Tweaks to support Qemu on Windows. 2014-09-23 21:38:51 -06:00
grossmj
031ff1c8e0 Refactor node creation and improvements on QEMU VMs configuration. 2014-09-23 17:43:59 -06:00
grossmj
cd28d49147 Minor GUI changes for QEMU integration. 2014-09-23 13:49:03 -06:00
jseutter
d25745e839 Merge pull request #24 from planctechnologies/gns-94
Gns 94
2014-09-22 22:29:47 -06:00
grossmj
7254262b25 Qemu integration stage 2, support for ASA and IDS. 2014-09-22 21:24:55 -06:00
Michael
cc5a8fd475 Moved tunnel module into gns-gui base dir 2014-09-22 19:16:51 -06:00
Michael
9cc0ce761b Added another example2 and remove POC files 2014-09-22 19:15:52 -06:00
Jerry Seutter
77fe9f27ec Start gns3server when cloud instance running 2014-09-22 09:12:33 -06:00
Massimiliano Pippi
5c26273650 zip project contents 2014-09-22 14:45:34 +02:00
Massimiliano Pippi
20acadad53 menu action and empty slot for exporting project 2014-09-22 14:08:46 +02:00
Michael
530f98c1b7 Added example file 2014-09-22 00:05:21 -06:00
Michael
6949d8ff39 gns-94 - Working tunnel support, also created a tunnel module dir 2014-09-21 23:49:43 -06:00
Michael
1a47696d41 gns-94 - ssh tunnel module - work in progress 2014-09-21 21:01:46 -06:00
grossmj
76878ad0c6 Solarwinds Response Time Viewer integration (Windows 64-bit only). 2014-09-18 18:54:09 -06:00
grossmj
2cbf183de6 Base QEMU support. 2014-09-18 15:47:43 -06:00
jseutter
0ff31dd298 Merge pull request #23 from planctechnologies/server_start_workflow
Server start workflow
2014-09-17 10:46:35 -06:00
Massimiliano Pippi
f3c284a4b8 new workflow to start gns3 server and connect the websocket 2014-09-17 17:14:15 +02:00
Massimiliano Pippi
d1c9026447 threads for start the server and connect the websocket 2014-09-17 17:13:45 +02:00
Massimiliano Pippi
2f17206e77 removed custom instances states 2014-09-17 17:13:23 +02:00
Michael
5c167ed443 Merge pull request #22 from planctechnologies/gns-91
Gns 91- Encrypt communications to remote server
2014-09-15 21:52:51 -06:00
Jerry Seutter
f2955e58c3 gns-91, add SecureWebSocketClient 2014-09-15 23:08:35 +00:00
Jerry Seutter
aea800d7b1 Merge from dev 2014-09-15 19:03:20 +00:00
jseutter
a4cf95188e Merge pull request #21 from planctechnologies/gns-98
Gns 98 - don't store ssh keys in users .ssh/authorized_keys
2014-09-15 12:57:02 -06:00
Jerry Seutter
9ac2b55f05 gns-91, add SecureWebSocketClient 2014-09-15 17:54:13 +00:00
Jerry Seutter
0c98871b45 gns-91, add SecureWebSocketClient 2014-09-15 17:51:48 +00:00
Jerry Seutter
35a69b4ccd gns-91, add SecureWebSocketClient 2014-09-15 17:47:37 +00:00
Massimiliano Pippi
dd9ddbc7a7 do not store server keys upon SSH connections 2014-09-10 16:08:14 +02:00
Massimiliano Pippi
79f6f110e7 fixed bug on storing instance names into the topology file 2014-09-10 16:00:08 +02:00
Jerry Seutter
12963087c1 gns-91 - Added preliminary support for SSL and authentication 2014-09-08 15:49:58 +00:00
Michael
930ddbca31 Merge pull request #20 from planctechnologies/gns-44
Gns 44 - Send heartbeats from GUI to server
2014-09-03 22:54:16 -06:00
grossmj
9eb0c9db9c Bump version to 1.0-beta3.dev1. 2014-09-02 15:49:39 -06:00
grossmj
e7d7599cb6 Bump version to 1.0-beta2. 2014-09-02 13:06:26 -06:00
jseutter
482c4e21ff Merge pull request #19 from planctechnologies/gns-40
Gns 40 - ssh key management

Main changes:

Completed image lifecycle
new instance state to distinguish between image is running and gns3-server is running
stub procedure for SSH connections
moved gns3-ias url to settings
added -gns3 suffix to image and keypair names
2014-09-02 11:20:56 -06:00
grossmj
07f91da84b Fixes bug when loading a project file containing a syntax error. 2014-09-02 11:19:57 -06:00
grossmj
fa6e7ab4f3 Better support for rectangle and ellipse color transparency. 2014-09-02 10:47:59 -06:00
Jerry Seutter
804708b6e6 Remove the initial heartbeat notification as it attempts to send it before the connection is live. 2014-09-02 16:31:10 +00:00
Jerry Seutter
60abfb8213 GNS-42 - gui heartbeat frequency is now read as a config option 2014-09-02 16:16:09 +00:00
grossmj
37db20a824 Fixes config issue when using both EtherSwitch router and c3745 nodes. 2014-09-01 20:36:01 -06:00
grossmj
f9bdb0422e EtherSwitch support. 2014-09-01 14:56:26 -06:00
grossmj
5cb6a37b10 Add alpha chanel option for rectangle and ellipse colors.
Add parents to getFont and getColor.
2014-09-01 11:56:01 -06:00
grossmj
d1266a557f Multi-drop feature (use SHIFT key while dropping a node). 2014-08-31 19:25:42 -06:00
grossmj
2d12b3040a Default font and color for labels. 2014-08-31 14:48:30 -06:00
grossmj
c1a9dddf31 Topology summary: filter devices with capture(s), stop all captures. 2014-08-31 12:15:52 -06:00
grossmj
da7a8792a4 Commands for the GNS3 console (version, start, stop, suspend, reload, show device, show run, help and debug). 2014-08-31 11:17:00 -06:00
grossmj
b3cdca41b3 Layers implementation. 2014-08-30 18:41:06 -06:00
Jerry Seutter
0c9997095f The gui now sends heartbeat notifications to the server 2014-08-29 21:26:03 +00:00
grossmj
3dee3c5f04 New colors for the logo. 2014-08-29 14:30:52 -06:00
grossmj
12884d3bb0 Fixes empty image path bugs for IOS and IOU. 2014-08-26 16:32:24 -06:00
grossmj
7226641af0 Add "enable console" option to VirtualBox VMs (True by default).
Add "start at" option to VirtualBox VMs (adapter start index, 0 by default).
Fixes #86.
2014-08-26 15:26:45 -06:00
grossmj
271ee896b2 Fixes #38. Numeric sorting for Ethernet/hub ports. 2014-08-25 16:04:35 -06:00
grossmj
1e1c117bb2 Add restore default buttons for general, packet capture and GNS3 server preferences.
Change default port ranges.
Pedantic: uncompress -> decompress.
2014-08-25 15:41:55 -06:00
grossmj
ccf1333b8d Fetch the VirtualBox VM list only if the preferences page is shown. 2014-08-22 17:37:15 -06:00
grossmj
b37088b270 Prevent VirtualBox errors to be shown when opening the preferences dialog. 2014-08-21 18:12:20 -06:00
grossmj
4af457373f Fixes #48 (numeric sort on ports) and normalize capture file names. 2014-08-20 14:10:32 -06:00
grossmj
1a613562b1 More checks on device names, especially for IOS and IOU which forbid some characters. 2014-08-19 16:49:57 -06:00
grossmj
0d53e7d679 Handles zoom in or out using the mouse wheel + CTRL.
Resets the zoom using CTRL+0.
2014-08-19 12:15:52 -06:00
grossmj
8629a68787 Give credits in the about dialog and update the GNS3 icon. 2014-08-18 11:46:14 -06:00
grossmj
e27c34697a Add the new logo. 2014-08-17 18:08:08 -06:00
grossmj
2c70423806 Prevent node labels to be deleted. 2014-08-14 17:30:39 -06:00
grossmj
9e818a7557 Fixes #80. Tab in the console generates exception. 2014-08-14 15:25:21 -06:00
grossmj
a207b5f0b7 Fixes bug when deleting ports from an Ethernet switch. 2014-08-13 14:28:15 -06:00
grossmj
ac4fa63a59 Hide the GNS3 server console on Windows. 2014-08-13 12:13:38 -06:00
grossmj
7548823425 Bump to 1.0beta2.dev1 2014-08-10 15:29:21 -06:00
Massimiliano Pippi
31d49f16a9 fixed bug in cloud preferences instantiation 2014-08-04 15:29:43 +02:00
Massimiliano Pippi
3448322408 add -gns3 suffix to images created on rackspace 2014-08-03 17:00:06 +02:00
Massimiliano Pippi
a29fd45c80 moved gns3 ias url to settings 2014-08-03 16:50:28 +02:00
Jeremy Grossmann
5f1c86acbb Merge pull request #79 from planctechnologies/dev
Store cloud instance info in project file
2014-07-30 21:11:48 -06:00
Jeremy Grossmann
6b79abd3c0 Merge pull request #78 from braddeshong/master
Fix crash in debug log statements when linking a vde switch to another device.
2014-07-30 21:11:30 -06:00
Massimiliano Pippi
791817188a added paramiko to the requirements 2014-07-30 16:39:46 +02:00
Massimiliano Pippi
942b094017 added new custom state for instances 2014-07-30 15:50:08 +02:00
Massimiliano Pippi
6f5e3ebc33 fixed tests 2014-07-30 15:49:40 +02:00
Massimiliano Pippi
12af563b66 Merge branch 'dev' into gns-40 2014-07-30 13:24:24 +02:00
Massimiliano Pippi
1891e0fb1c start the thread inside the polling slot 2014-07-30 13:18:15 +02:00
Massimiliano Pippi
9377cd1862 added a thread to perform ssh connections 2014-07-30 13:17:49 +02:00
Massimiliano Pippi
8f8917c252 added param to inject ssh keypairs name in new instances 2014-07-30 12:37:24 +02:00
Massimiliano Pippi
ca01b37971 added context manager to wrap ssh connections 2014-07-30 12:36:34 +02:00
Massimiliano Pippi
d7e4530b57 better handling of ssh keypairs 2014-07-29 18:00:30 +02:00
Massimiliano Pippi
50af28741b added utility method 2014-07-29 18:00:02 +02:00
Massimiliano Pippi
66b2464233 added utility method, made keypair param mandatory 2014-07-29 17:59:37 +02:00
Jerry Seutter
59113d3cd7 Merge branch 'master' into dev 2014-07-28 22:39:36 +00:00
jseutter
c61c7e9d4e Merge pull request #18 from planctechnologies/gns-38
Each cloud project has its set of instances stored inside .gns3 project file.

Features added:

When a cloud project is created, an instance is created with the same name (size and image are retrieved from preferences), instance metadata are added to *.gns3 project file.
When a project is closed (another project created/opened or program closed) all its instances are destroyed
When a cloud project is opened from disk, instances listed inside *.gns3 project file are respawned
When an instance is added through the cloud inspector, that instance is added to *.gns3 project file
When an instance is removed through the cloud inspector, that instance is removed from *.gsn3 project file too and won't be respawned
Interaction with Rackspace are performed in a separate thread whenever possible and useful.
Current implementation does not handle SSH keypairs.
2014-07-28 15:44:07 -06:00
Brad DeShong
1355abb1eb Fix crash in debug log statements when linking a vde switch to another device. 2014-07-27 10:58:29 -04:00
Massimiliano Pippi
19b0c3fc80 fixed tests 2014-07-27 15:52:21 +02:00
Massimiliano Pippi
6fd5bd257c create ssh keypairs for every image 2014-07-27 15:49:18 +02:00
Massimiliano Pippi
c492e15209 create ssh keypairs along with image 2014-07-27 15:49:08 +02:00
Massimiliano Pippi
e6dbdb9ee5 add public and private key to topology structure 2014-07-27 15:48:48 +02:00
Massimiliano Pippi
635a7c7b02 added wrapper method for creating project instances 2014-07-27 15:16:55 +02:00
Massimiliano Pippi
db77cb6927 fixed tests 2014-07-24 17:46:27 +02:00
Massimiliano Pippi
926eb7b846 delete instances in a separate thread and remove them from the project 2014-07-24 17:18:18 +02:00
Massimiliano Pippi
274b5c3f23 delete instances by id not by name 2014-07-24 17:17:43 +02:00
Massimiliano Pippi
27f7931f08 added thread class to remove instances 2014-07-24 16:16:26 +02:00
Massimiliano Pippi
92396f6d82 add new instances to current project 2014-07-24 16:09:29 +02:00
Massimiliano Pippi
a330662f7b emit a signal when an instance is created 2014-07-24 15:08:01 +02:00
Massimiliano Pippi
060d7312b5 start instances when opening cloud projects 2014-07-24 15:02:36 +02:00
Massimiliano Pippi
1827feafc8 fixed settings key string 2014-07-21 17:58:16 +02:00
Massimiliano Pippi
0972f36033 filter images for current project in cloud inspector 2014-07-21 16:14:57 +02:00
Massimiliano Pippi
3b5167c72c reuse provider object from mainwindow to avoid another authentication call 2014-07-21 15:18:47 +02:00
Massimiliano Pippi
14ed3ad9ac moved utility threads to cloud.utils module 2014-07-21 15:12:37 +02:00
Massimiliano Pippi
303fbfe031 fixed tests 2014-07-21 15:12:12 +02:00
Massimiliano Pippi
922ec9cc84 create an instance when a cloud project is created 2014-07-21 15:08:00 +02:00
Massimiliano Pippi
056d362093 clear cloud inspector when closing a project 2014-07-21 15:07:44 +02:00
Massimiliano Pippi
4f25a6b2f1 store a reference to the cloud provider in the main window 2014-07-21 15:07:12 +02:00
Massimiliano Pippi
83bac27926 added utils module 2014-07-21 14:40:21 +02:00
Massimiliano Pippi
08cb7c6960 store also instance id 2014-07-21 14:39:55 +02:00
Massimiliano Pippi
db0e633544 fixed typo in dict key 2014-07-21 12:34:46 +02:00
Massimiliano Pippi
adf6dca43a update settings before saving project to avoid gns3 file containing wrong data 2014-07-21 12:32:58 +02:00
Massimiliano Pippi
49299a5c35 emit project_new_signal in the right places 2014-07-21 12:05:21 +02:00
Massimiliano Pippi
10b7456827 when a project is created and is of type cloud, fill cloud inspector 2014-07-21 12:00:49 +02:00
Massimiliano Pippi
31dd9366f4 added method to clear cloud inspector contents 2014-07-21 12:00:07 +02:00
Massimiliano Pippi
b72fb04039 emit signal when a project is about to be closed 2014-07-20 16:42:32 +02:00
Massimiliano Pippi
eb23d95ce3 store cloud instances into topology 2014-07-20 12:01:48 +02:00
grossmj
8add9d1534 Bump version to beta1. 2014-07-18 22:50:22 -06:00
grossmj
8b125692c8 Fixes live packet capture on Windows. 2014-07-18 22:43:38 -06:00
grossmj
83f4882034 Fixes issue when adding multiple VirtualBox VMs.
Remove early release dialog.
2014-07-18 21:10:46 -06:00
grossmj
e77acf0589 Update default Wireshark path. 2014-07-18 18:12:33 -06:00
grossmj
4eaa6f43e6 Remove privileged access checks for Dynamips. 2014-07-17 20:48:11 -06:00
grossmj
eef3eb84e2 Save the currently edited device when clicking on ok and apply in the preferences dialog. 2014-07-17 18:54:50 -06:00
grossmj
f81cb04bfb Fixes bug with live packet capture on Windows. 2014-07-17 18:04:00 -06:00
grossmj
24b5dbfa44 Fixes issue when spaces are in capture file paths. 2014-07-17 17:08:10 -06:00
grossmj
43a9a855f3 Prevent users to set the port and VLAN settings to 0 on Ethernet switches. 2014-07-17 16:14:49 -06:00
grossmj
e23d6c4581 Merge branch 'master' of github.com:GNS3/gns3-gui 2014-07-17 15:28:52 -06:00
grossmj
1c0c8858a1 Minimal VirtualBox integration. 2014-07-17 15:28:02 -06:00
Jeremy Grossmann
7ac072f844 Merge pull request #75 from planctechnologies/dev
Instance id descriptions
2014-07-17 10:02:30 -06:00
Massimiliano Pippi
9862368d25 updated ias url 2014-07-17 16:48:24 +02:00
Massimiliano Pippi
9d6f86c3e6 fixed tests 2014-07-17 16:48:24 +02:00
Massimiliano Pippi
72dd7c3e04 adjust column size when new rows are added 2014-07-17 16:48:24 +02:00
Massimiliano Pippi
a0b87fac9e make obvious in the gui that an instance is being deleted 2014-07-17 16:48:24 +02:00
Massimiliano Pippi
90fe49f31b better sync with rackspace data 2014-07-17 16:48:23 +02:00
Massimiliano Pippi
d1327d15a0 added thread for creating instances in background 2014-07-17 16:48:23 +02:00
Massimiliano Pippi
7b36037b94 translave flavor id into GNS3 sizes inside Qt model 2014-07-17 16:48:23 +02:00
Massimiliano Pippi
8d5e753674 get an image instance by ID 2014-07-17 16:48:23 +02:00
Massimiliano Pippi
60da6740e2 make SSH keys optional for instance creation 2014-07-17 16:48:23 +02:00
Massimiliano Pippi
87e396e8b5 ask users a name for the new instance 2014-07-17 16:48:23 +02:00
Massimiliano Pippi
9b129bfa39 fill create instance combo box in cloud inspector 2014-07-17 16:48:22 +02:00
Jerry Seutter
8b4f7df128 Remove pricing label from cloud preferences pane. 2014-07-17 14:18:47 +00:00
jseutter
3961a50989 Merge pull request #17 from planctechnologies/gns-34
Supply instance flavor descriptions
2014-07-17 07:47:29 -06:00
Jerry Seutter
54ab9583e9 Merge branch 'dev' of github.com:planctechnologies/gns3-gui into dev 2014-07-17 13:44:26 +00:00
grossmj
b5c8898a27 Base for VirtualBox support. 2014-07-12 13:17:40 -06:00
grossmj
6b9149c354 Bump to version 1.0b1.dev1. 2014-07-11 16:44:55 -06:00
Massimiliano Pippi
0dafebbf60 removed import from string, hardcoded RackspaceCtrl instead 2014-07-11 15:18:37 +02:00
Massimiliano Pippi
429c24b132 fixed tests 2014-07-11 15:11:45 +02:00
Massimiliano Pippi
3721424653 handle new settings for flavor/size values 2014-07-11 15:11:45 +02:00
Massimiliano Pippi
f8f15aaed7 select instance size with a combobox containing size (flavor) labels 2014-07-11 15:11:45 +02:00
Massimiliano Pippi
697e1028e9 changed settings names for cloud instances size 2014-07-11 15:11:45 +02:00
Massimiliano Pippi
7bce53b23c handle connection error when IAS is down 2014-07-11 15:11:45 +02:00
Massimiliano Pippi
5156584b76 retrieve instance flavor from Rackspace provider 2014-07-11 15:11:44 +02:00
jseutter
65d8d83bc6 Merge pull request #16 from planctechnologies/gns-35
Gns 35 - Make polling run on its own thread
2014-07-09 23:43:13 -06:00
grossmj
9eb21bbd00 Deactivate server file logging. 2014-07-09 17:20:14 -06:00
grossmj
ffcadc2f18 Bump version to 1.0a8. 2014-07-09 17:08:22 -06:00
grossmj
79b2f63818 New feature: change node symbols. 2014-07-09 14:49:24 -06:00
grossmj
c2869bf074 Use Windows interface names instead of their GUID (more user friendly).
Ask for an alternative interface if one cannot be found.
2014-07-08 14:01:45 -06:00
Massimiliano Pippi
c380869b24 keep track of instances by id, better add/update/remove handling 2014-07-07 11:20:31 +02:00
Massimiliano Pippi
fb56a49bb6 load cloud instances in a separate thread 2014-07-07 11:20:31 +02:00
grossmj
b66f2dc6f8 Merge remote-tracking branch 'origin/master' 2014-07-06 16:34:59 -06:00
grossmj
89dea9fe92 Find an alternative IOS or IOU image if one cannot be found when importing a topology. 2014-07-06 16:34:38 -06:00
Jeremy Grossmann
af2616f3b4 Merge pull request #73 from planctechnologies/dev
Gns-14 - Populate server images to start instances from
2014-07-04 19:34:16 -06:00
grossmj
51f7d10cbb Improvements on the topology summary and link highlighting. 2014-07-04 19:14:50 -06:00
jseutter
9a58de65f7 Merge pull request #15 from planctechnologies/gns-14
Gns-14 - Populate server images to start instances from
2014-07-04 18:11:43 -06:00
grossmj
a24da0c849 Start a packet capture from the device contextual menu. 2014-07-04 16:25:13 -06:00
grossmj
70395debdc Check the minimum required RAM when adding IOS images. 2014-07-04 12:57:01 -06:00
grossmj
30101db58a Fixes issue when deleting note items that have parent items. 2014-07-04 10:34:23 -06:00
grossmj
582cb904d2 New feature: import/export device configs. 2014-07-03 18:56:37 -06:00
grossmj
7e980749d4 Default port configuration for Ethernet switch and hub devices. 2014-07-03 11:13:25 -06:00
grossmj
242a579ecf Fixes #72. 2014-07-03 09:44:13 -06:00
grossmj
2e4b7c5ec5 New feature: insert image on the view.
Add some tooltips in preference and configuration pages.
2014-07-03 09:32:17 -06:00
grossmj
f4e4966edc Fixes size restoration issues for rectangles and ellipses when loading a project. 2014-07-01 09:08:52 -06:00
grossmj
31a0dfe2c2 Fixes error when connecting an IOU device to a cloud. 2014-07-01 08:22:17 -06:00
grossmj
41fc9c7fc7 Bump to version 1.0a8.dev1 and reactivate cloud features. 2014-07-01 08:19:19 -06:00
Massimiliano Pippi
45e85bb7a0 fixed tests after removing mocks 2014-07-01 11:49:12 +02:00
Massimiliano Pippi
69a04eea27 load/store default image value from settings 2014-07-01 11:29:21 +02:00
Massimiliano Pippi
6ee753e469 added settings to hold default image 2014-07-01 11:24:14 +02:00
Massimiliano Pippi
69036dbe27 retrieve and store tenantId for rackspace users 2014-07-01 11:24:14 +02:00
Massimiliano Pippi
6ac0c2e2f7 stop mocking 2014-07-01 11:24:14 +02:00
Massimiliano Pippi
dab9cf5291 added gui components for selecting image templates 2014-07-01 11:24:14 +02:00
grossmj
28ff103c8e Node labels must be selectable. 2014-06-29 11:15:40 -06:00
grossmj
58ddbc849d Fixes issue with relative image paths. 2014-06-29 10:14:49 -06:00
grossmj
ec7837f21f Do not load cloud settings for the alpha7 release. 2014-06-29 08:37:33 -06:00
grossmj
b20a86ec39 Hide cloud stuff for the alpha7 release. 2014-06-29 04:05:31 -06:00
grossmj
2b19810019 Bump version to 1.0a7. 2014-06-29 03:59:35 -06:00
grossmj
b04bd4feca Fixes empty cloud provider in settings (temporary fix). 2014-06-28 16:04:16 -06:00
grossmj
bd03c9c3a4 Do not use relative paths for configs. 2014-06-28 13:35:05 -06:00
grossmj
907c6f9f01 Fixes pretty logging error if the settings directory doesn't exist. 2014-06-28 12:45:04 -06:00
Jeremy Grossmann
dc2ec7b9b0 Merge pull request #71 from planctechnologies/master
Instance inspector improvements
2014-06-28 11:55:44 -06:00
jseutter
57860c19f7 Merge pull request #14 from planctechnologies/gns-81
Added two relevant methods to RackspaceCtrl class:

_get_shared_images to perform HTTP requests against gns3-ias server
list_images higher-level method to retrieve a dictionary (image_id, image_name) of shared images ready to be used by the GUI client
A note about integration tests: I've made significant changes to give developers the opportunity to pass rackspace credentials through command line and have more control about which tests to run and how.
More details here: https://planctechnologies.atlassian.net/wiki/display/GNS/Developer+Installation
2014-06-28 11:35:48 -06:00
Jerry Seutter
dca7a3e0b7 Merge remote-tracking branch 'upstream/master' 2014-06-28 16:23:57 +00:00
grossmj
c1f9ddc396 New feature: packet capture for IOU (not working, issue with iouyap). 2014-06-27 09:42:34 -06:00
Massimiliano Pippi
c9a28869a7 iterate through region ditcts non-destructively 2014-06-27 16:02:17 +02:00
grossmj
932193f759 New feature: packet capture for the Ethernet hub and Ethernet, ATM and Frame relay switches. 2014-06-27 07:26:47 -06:00
jseutter
ae8fed620d Spelling/grammar fix to docstring 2014-06-27 07:13:07 -06:00
grossmj
0988246ec0 New feature: packet capture for IOS routers. 2014-06-26 03:06:59 -06:00
Massimiliano Pippi
02b7a3aea4 fixed tests code 2014-06-25 16:58:27 +02:00
Massimiliano Pippi
57971f84aa tests for list_images 2014-06-25 16:57:53 +02:00
Massimiliano Pippi
f9019535c6 handle multiple images coming from ias 2014-06-25 16:57:29 +02:00
Massimiliano Pippi
932e6a6130 better integration tests 2014-06-25 12:26:37 +02:00
Massimiliano Pippi
b50e000e63 _get_shared_image method plus tests 2014-06-24 14:50:02 +02:00
Massimiliano Pippi
e1526a4735 added docs to testsuite 2014-06-24 14:50:02 +02:00
Massimiliano Pippi
11feb2d44f run integration tests with pytest 2014-06-24 14:50:01 +02:00
jseutter
0e86b16a24 Merge pull request #13 from planctechnologies/dev_merge
Dev merge
2014-06-23 10:07:15 -06:00
grossmj
8bc875b8a6 New feature: option to uncompress an IOS image. 2014-06-21 09:08:13 -06:00
Massimiliano Pippi
cbb5db539d fixed settings for first time startup 2014-06-21 15:02:27 +02:00
Massimiliano Pippi
7de5000731 provide a default value for cloud provider 2014-06-21 15:01:51 +02:00
Massimiliano Pippi
4b0cf5a0d8 fixed tests according to master branch changes 2014-06-21 13:35:02 +02:00
Massimiliano Pippi
bfb4b777b6 handle default value 2014-06-21 13:34:44 +02:00
grossmj
cb58c755a2 Fixes IOS image relative path problems. 2014-06-21 05:29:01 -06:00
grossmj
9433b4eced Fixes #66. 2014-06-21 00:03:00 -06:00
grossmj
df5f003d5f Move dialogs to a dialogs package. 2014-06-20 14:30:52 -06:00
grossmj
63455492ff Fixes #62. 2014-06-20 10:04:19 -06:00
grossmj
3b2a74bb1c Style settings for note, rectangle and ellipse items. Possibility to edit interface and node labels. 2014-06-20 09:52:21 -06:00
Jerry Seutter
64c9aff5c0 Merge branch 'master' into dev 2014-06-19 18:08:22 +00:00
Jerry Seutter
e3563365d0 Merge branch 'dev' of github.com:planctechnologies/gns3-gui into dev 2014-06-19 18:08:09 +00:00
grossmj
b295ab1b7e IOU: rename startup-config to initial-config because it makes more sense. 2014-06-18 06:08:00 -06:00
grossmj
7ffa68b47c Exception when showing cloud labels. Fixes #60. 2014-06-18 05:13:41 -06:00
grossmj
a377af4067 Delete key on notes. Fixes #57. 2014-06-16 12:11:45 -06:00
jseutter
69017c94b0 Merge pull request #12 from planctechnologies/cloud_inspector
Implement calls to the cloud provider class
2014-06-16 10:41:43 -06:00
grossmj
8c24d761c5 Use Dynamips, IOU and VPCS identifiers to correctly load a topology. 2014-06-15 05:19:39 -06:00
grossmj
3b5b7c4d37 New feature: duplicate option for notes, rectangles and ellipses. 2014-06-14 13:26:22 -06:00
grossmj
6dc2e072e6 New feature: recent file menu. 2014-06-14 09:36:14 -06:00
grossmj
cb7acf571c New feature: load a project by dropping the project file on the view. 2014-06-13 13:30:19 -06:00
grossmj
099473aea4 New feature: contextual device menu. 2014-06-13 13:12:36 -06:00
grossmj
b32aba3546 New feature: show/hide interface labels. 2014-06-13 11:56:38 -06:00
grossmj
b015f358c2 New features: add rectangles & ellipses. 2014-06-11 13:42:40 -06:00
grossmj
e53c54a2a5 New feature: add a note. 2014-06-11 10:04:40 -06:00
grossmj
51025d9d0d Lab instructions.
Handle IOS and IOU image changes taking into account servers.
2014-06-10 13:10:48 -06:00
grossmj
52d89733d5 Add node names to the allocated name list when loading a project. 2014-06-10 09:00:20 -06:00
grossmj
9dceef9bea Merge remote-tracking branch 'origin/master' 2014-06-07 09:57:46 -06:00
grossmj
47868f08fb Fixes refresh issue in the topology summary dock when a linked node is renamed. 2014-06-07 09:57:12 -06:00
Massimiliano Pippi
177de3947d handle failures on authentication inside cloud inspector, tests 2014-06-03 17:55:46 +02:00
Massimiliano Pippi
0c2fc87823 another fix in region labels tests 2014-06-03 17:34:41 +02:00
Jeremy Grossmann
35c02d9301 Merge pull request #55 from planctechnologies/master
Cloud Inspector widget
2014-06-02 13:36:53 -06:00
Massimiliano Pippi
a2d7f1b539 better testcase 2014-06-02 19:54:02 +02:00
Massimiliano Pippi
d1e42a82fd fixed tests for region labels 2014-06-02 19:51:48 +02:00
Massimiliano Pippi
174ca5b635 pass lowercase region ids to libcloud 2014-06-02 19:47:16 +02:00
Massimiliano Pippi
10da8e4db2 call updated method on self._model 2014-06-02 19:47:01 +02:00
Massimiliano Pippi
a78961371e start/restart the timer after inspector loads 2014-06-02 19:46:25 +02:00
Massimiliano Pippi
70b46a79e9 update the whole row when instance changes 2014-06-02 19:45:58 +02:00
Jerry Seutter
e987823ae3 Merge remote-tracking branch 'origin/cloud_inspector' into dev 2014-06-02 17:09:19 +00:00
Massimiliano Pippi
2cc701fa69 make test order reflect columns order 2014-06-02 19:08:38 +02:00
Massimiliano Pippi
718d34afff added test for table view 2014-06-02 17:44:46 +02:00
Massimiliano Pippi
e221bd3068 moved timer outside the model into the view 2014-06-02 17:44:35 +02:00
Massimiliano Pippi
ef7523b280 GNS-37 emit signal when instance is selected 2014-06-02 17:44:26 +02:00
Massimiliano Pippi
4c9f377345 fixed docstrings 2014-06-02 17:44:20 +02:00
Massimiliano Pippi
d9f454c9fb bugfixing and tests added 2014-06-02 17:44:12 +02:00
Massimiliano Pippi
549e75c5fe moved into init module some utils 2014-06-02 17:44:00 +02:00
Massimiliano Pippi
f9a81a9d36 handle real provider in cloud inspector 2014-06-02 17:43:54 +02:00
Massimiliano Pippi
9e50cb3749 pass in cloud settings to cloud inspector 2014-06-02 17:43:48 +02:00
Massimiliano Pippi
685b640c40 moved utility code to proper package 2014-06-02 17:43:37 +02:00
Massimiliano Pippi
22239cb9c7 call cloud api to delete an instance 2014-06-02 17:43:18 +02:00
Jerry Seutter
b3c5bb48a2 Merge branch 'dev'
Conflicts:
	gns3/main_window.py
	gns3/ui/main_window_ui.py
2014-06-02 15:17:49 +00:00
jseutter
8fc1948bb6 Merge pull request #11 from planctechnologies/cloud_inspector
Cloud inspector
2014-06-02 08:57:51 -06:00
grossmj
a0cdc9102a Update README. 2014-05-31 14:43:07 -06:00
grossmj
81774a8ba9 Bump to version alpha7.dev1 2014-05-31 10:51:19 -06:00
grossmj
179e78d8e1 Fixes problems non-existent paths for logfiles. 2014-05-31 02:04:26 -06:00
grossmj
fb840280dd Bump to version 1.0-alpha6. 2014-05-30 13:49:52 -06:00
grossmj
6f3527bab0 Fix issue when deleting a temporary project. 2014-05-30 13:43:04 -06:00
grossmj
23497fc21e Fix issue with server logging. 2014-05-30 13:34:05 -06:00
grossmj
171ece52d2 Fix inconsistency with new project. 2014-05-30 12:56:51 -06:00
grossmj
f82792a83f Log to files (GNS3_client.log and GNS3_server.log) + fixes Ethernet hub loading. 2014-05-30 05:56:15 -06:00
grossmj
d3fab8c509 Replace decode errors when reading device configs. 2014-05-29 12:59:13 -06:00
grossmj
f8e6b36818 Config dir for IOU, VPCS and router configuration pages. 2014-05-28 16:45:15 -06:00
grossmj
df7390956c New project dialog and project-wide settings. 2014-05-28 14:44:03 -06:00
grossmj
c8ea656e02 Fixes #53. 2014-05-28 08:18:02 -06:00
grossmj
bbb2506f78 Hostname management refactoring. 2014-05-27 11:20:16 -06:00
Massimiliano Pippi
cfc2ee14db more compact layout for cloud inspector 2014-05-27 14:48:23 +02:00
Massimiliano Pippi
221de5a144 rearranged cloud inspector columns 2014-05-27 12:33:05 +02:00
grossmj
fd887b6385 New hostnames management for the Dynamips module. 2014-05-27 03:57:18 -06:00
grossmj
d432005a40 Add requests module dependency. Fixes #52. 2014-05-26 12:35:23 -06:00
grossmj
098a23520a Relative paths support for IOS/IOU images in project files. 2014-05-26 12:32:58 -06:00
Jeremy Grossmann
abc0b17311 Merge pull request #51 from planctechnologies/master
Cloud/Local dialog on new project, and instance types API method
2014-05-26 08:56:35 -06:00
grossmj
b04da2dd1e Change default projects directory path and introduce the images directory path. 2014-05-26 08:55:12 -06:00
Massimiliano Pippi
923fbb34c3 better table column resizing 2014-05-26 16:48:50 +02:00
grossmj
34865dde0d Default paths for OSX support. 2014-05-25 11:14:36 -06:00
grossmj
e008ec79cf Change open file name filters, path to tools and set some dialog as modal for OSX support. 2014-05-25 01:54:45 -06:00
Massimiliano Pippi
5f48b10b3b context menu on cloud inspector 2014-05-22 23:51:22 +02:00
Massimiliano Pippi
e46ebedb6f added instance polling 2014-05-22 23:20:47 +02:00
Massimiliano Pippi
2ee4a23944 method to update instances status 2014-05-22 22:58:12 +02:00
Massimiliano Pippi
ec2e5d96f3 instance status incons and tests 2014-05-22 17:37:08 +02:00
Massimiliano Pippi
f10f6869e8 fixed path for promoted widget 2014-05-22 17:36:34 +02:00
grossmj
ba0fdbb70e Reactivate cloud preferences page after alpha5. 2014-05-21 23:32:57 -06:00
grossmj
553dc08b8f Bump version to alpha5. 2014-05-21 19:14:13 -06:00
grossmj
1a9861a09d Fixes NIO add and delete requests for VPCS. 2014-05-21 19:12:37 -06:00
Massimiliano Pippi
37934c2aac load fake nodes to test the gui 2014-05-21 17:06:51 +02:00
Massimiliano Pippi
e01825178a load cloud inspector at startup (temporary hack) 2014-05-21 17:06:30 +02:00
Massimiliano Pippi
63bf77cdaf select rows not cells 2014-05-21 17:05:38 +02:00
Massimiliano Pippi
41631a4049 added a table view 2014-05-21 11:13:33 +02:00
Massimiliano Pippi
adcacaf610 added cloud inspector to dock view menu 2014-05-21 10:17:32 +02:00
Massimiliano Pippi
992782d0a0 added cloud inspector promoted widget 2014-05-21 10:17:23 +02:00
Massimiliano Pippi
38d16df415 added cloud inspector widget 2014-05-21 10:17:13 +02:00
grossmj
1482cecb7a Remove uneeded param for IOS router setup. 2014-05-20 18:05:18 -06:00
grossmj
8385ebaa87 Remove L1 keepalives option from preferences. Fix console port
restoration for IOU and VPCS (when loading a project).
2014-05-20 17:27:42 -06:00
grossmj
277a233b6c Relative paths for device configs. Change L1 keepalives to be
deactivated by default.
2014-05-20 11:20:48 -06:00
Jerry Seutter
48a78d6f15 Grammar change. 2014-05-20 17:02:51 +00:00
Jerry Seutter
f1b8df2661 Merge branch 'gns-75' of github.com:planctechnologies/gns3-gui into dev 2014-05-20 16:52:48 +00:00
Jerry Seutter
420bbea55c Merge branch 'gns-28' of github.com:planctechnologies/gns3-gui into dev 2014-05-20 16:50:25 +00:00
grossmj
0400be29ab Use INI format for GNS3 settings on OSX. 2014-05-19 19:11:27 -06:00
grossmj
f18c33e0ca Look for vpcs, dynamips and iouyap locations when not to Windows. 2014-05-19 18:51:34 -06:00
grossmj
96b16c4e1a IOU layer 1 keepalive messages support. 2014-05-19 15:50:13 -06:00
grossmj
f592685409 Hide test settings button to avoid questions. 2014-05-19 11:36:26 -06:00
grossmj
c8724ea416 Option to automatically start on not the local server on startup. Fixes
#35.
2014-05-19 11:30:10 -06:00
grossmj
4b074bc97c Remote server support for VPCS. 2014-05-19 10:58:44 -06:00
grossmj
db9ed984cf Working VPCS implementation. 2014-05-18 19:13:21 -06:00
Massimiliano Pippi
9e07f222b5 ask users which kind of resources to use for current project 2014-05-17 22:42:28 +02:00
Massimiliano Pippi
f7acf6b559 fixed bug in topology clear() method 2014-05-17 22:42:18 +02:00
Massimiliano Pippi
420729c971 added dialog for choosing local/cloud resources 2014-05-17 22:42:10 +02:00
Massimiliano Pippi
5ed49ce962 store resources type into project files 2014-05-17 22:42:02 +02:00
Massimiliano Pippi
5e71e65cfb fix GNS-75 (do not close preferences on errors) + tests 2014-05-17 22:41:51 +02:00
grossmj
0fbe6e4e1f Normalize config paths for Windows. 2014-05-16 15:04:47 -06:00
grossmj
b4f2314bb4 Support for configs in "Frozen" versions of GNS3. 2014-05-16 14:46:15 -06:00
grossmj
aa65aa1519 Merge branch 'joebowen-master' 2014-05-16 13:36:39 -06:00
grossmj
0ea1935800 Merge branch 'master' of https://github.com/joebowen/gns3-gui into joebowen-master
Conflicts:
	gns3/modules/vpcs/ui/vpcs_preferences_page_ui.py
2014-05-16 13:35:52 -06:00
grossmj
d4a495abec More checks for cloud connections. 2014-05-16 13:30:04 -06:00
grossmj
899956c5ed Prevent devices to be started, stopped or suspended if their status
isn't right. Fixes #43.
2014-05-16 12:37:26 -06:00
Joe Bowen
a71d28c28e Added base64 transmission of script_file 2014-05-16 11:43:04 -06:00
grossmj
98a044a8e1 IOU l2 and l3 base startup-configs. 2014-05-16 11:23:50 -06:00
jseutter
bb6c9b390a Merge pull request #7 from planctechnologies/gns-10
Gns 10
2014-05-16 10:18:11 -06:00
Jerry Seutter
786fbb3925 Merge branch 'dev' into gns-10 2014-05-16 16:15:56 +00:00
grossmj
c717e11f62 Base config for IOU & improved base config management. 2014-05-16 00:02:12 -06:00
grossmj
6c7375c8a3 Show item coordinates in the status bar. 2014-05-15 17:35:24 -06:00
grossmj
63b9aec279 Bump version to 1.0a5.dev1. 2014-05-15 10:44:32 -06:00
Joe Bowen
04fa48b459 Fixed VPCS base_script_file setting 2014-05-15 09:33:46 -06:00
Joe Bowen
a021636da8 Fixed VPCS base_script_file setting 2014-05-15 09:28:11 -06:00
Kieron Bulloch
154fffdce5 Adding 'list_sizes' function and related integration test. 2014-05-14 23:21:20 -04:00
grossmj
4483dc992a Reactivate cloud and vpcs after alpha4. 2014-05-14 17:59:34 -06:00
grossmj
56c68753d9 Bump version to alpha4. 2014-05-14 17:44:38 -06:00
grossmj
18550ed1cb Experimental support for Mac OS X. 2014-05-14 16:02:05 -06:00
grossmj
465c9c97f0 Show Windows interface names in the cloud tooltips. 2014-05-14 15:35:36 -06:00
grossmj
46c2980518 Windows interface names for clouds. 2014-05-14 14:28:03 -06:00
Joe Bowen
e55e2deb3e Fixed VPCS path setting 2014-05-14 13:43:22 -06:00
grossmj
ca5bb8c2d0 Fixes #36. 2014-05-14 10:53:26 -06:00
Jeremy Grossmann
5eb96cba57 Merge pull request #40 from planctechnologies/master
Cloud API functionality
2014-05-14 10:12:09 -06:00
grossmj
f7d30dc10d Delete temporary Dynamips files. 2014-05-14 10:08:50 -06:00
Jerry Seutter
27ed9aec88 Merge branch 'dev' of github.com:planctechnologies/gns3-gui into dev 2014-05-14 13:31:50 +00:00
jseutter
1165135687 Merge pull request #8 from planctechnologies/gns-21-through-27
Cloud API calls - GNS-21 through GNS-27
2014-05-14 07:27:01 -06:00
Jerry Seutter
f785236058 Fixing tests 2014-05-14 13:25:45 +00:00
grossmj
b5b4f0a885 Changes for VPCS implementation. 2014-05-13 16:10:38 -06:00
grossmj
7093df19a9 Merge branch 'master' of git@github.com:GNS3/gns3-gui.git 2014-05-13 15:21:42 -06:00
grossmj
b8b2bb7323 Merge branch 'joebowen-master' 2014-05-13 15:18:42 -06:00
grossmj
aaaf9aba70 Merge branch 'master' of https://github.com/joebowen/gns3-gui into joebowen-master
Conflicts:
	gns3/modules/__init__.py
2014-05-13 15:17:58 -06:00
Joe Bowen
52adc5b147 Update Class names to camelcase 2014-05-13 15:01:09 -06:00
Kieron Bulloch
93cc39c392 Merge branch 'gns-21-through-27' of https://github.com/planctechnologies/gns3-gui into gns-21-through-27 2014-05-13 15:54:33 -04:00
Jerry Seutter
13a9edfb54 Merge branch 'dev' into gns-21-through-27 2014-05-13 23:10:38 +00:00
Kieron Bulloch
3370fce742 Merge branch 'dev' of https://github.com/planctechnologies/gns3-gui into gns-21-through-27
Conflicts:
	tests/test_cloud_integration.py
2014-05-13 15:37:53 -04:00
Kieron Bulloch
8c851198c9 Removing whitespace. 2014-05-13 15:32:19 -04:00
Joe Bowen
8e42f0b554 Updated variable names to lowercase 2014-05-13 13:31:36 -06:00
Joe Bowen
ba49dbbdee Fixed first round of bugs/comments from first pull request 2014-05-13 10:18:02 -06:00
Kieron Bulloch
1e8e8b8871 Adding tests to test_cloud_integration.py
Cleaning up comments, etc before pull request
2014-05-13 08:17:32 -04:00
Jeremy Grossmann
ee584a5558 Merge pull request #38 from planctechnologies/master
Cloud preference instance details
2014-05-12 12:02:21 -06:00
Jerry Seutter
fa302281b3 Merge branch 'master' into dev 2014-05-12 15:43:56 +00:00
Jerry Seutter
14fd852a95 Remove an extra space in a label 2014-05-12 15:40:53 +00:00
Massimiliano Pippi
c979a8a28c added integration tests 2014-05-12 17:30:18 +02:00
Massimiliano Pippi
ce203940f2 do not run all tests by default, let user specify them 2014-05-12 17:30:17 +02:00
Massimiliano Pippi
c608356a3a fix region parsing logic 2014-05-12 17:30:17 +02:00
Massimiliano Pippi
780996c850 mock tests with real values 2014-05-12 17:30:17 +02:00
Massimiliano Pippi
f148b8d164 removed mocking and call actual ctrl class + tests 2014-05-12 17:30:17 +02:00
Massimiliano Pippi
eb38b584aa fixed string path to cloud ctrl path 2014-05-12 17:30:17 +02:00
jseutter
e1c77fd09f Merge pull request #6 from planctechnologies/gns-11-20
Code for Gns-11, GNS-12, GNS-13, GNS-20
2014-05-12 09:13:23 -06:00
Joe Bowen
12ee0d4bb3 Changed the way vpcs closes by using the socket to send quit message instead of pid kill 2014-05-12 08:17:29 -06:00
Kieron Bulloch
c2ab645e4b Re-working exception handling to reduce code duplication, ease base controller
class abstraction.

Adding additional exceptions.

Adding unit tests for exceptions based on API response HTTP status code.
2014-05-10 19:41:01 -04:00
grossmj
e154805398 Revert "Hide the cloud page for alpha4 release."
This reverts commit f621266596.
2014-05-09 12:08:58 -06:00
grossmj
549e5d78a2 Revert "Bump to alpha4."
This reverts commit 6adcaa6ddc.
2014-05-09 12:08:23 -06:00
grossmj
f621266596 Hide the cloud page for alpha4 release. 2014-05-09 11:38:01 -06:00
grossmj
6adcaa6ddc Bump to alpha4. 2014-05-09 11:22:55 -06:00
grossmj
8894bfb23f Remove .gns3 from folder name. 2014-05-09 11:19:25 -06:00
grossmj
70125a1aa4 Disconnect the server if the version differs with the GUI. 2014-05-08 14:20:56 -06:00
grossmj
c8e8197f9f Move cloud code to a builtin module and support for clouds on remote
servers.
2014-05-07 19:33:57 -06:00
Massimiliano Pippi
217d8a63d4 changed labels text 2014-05-08 00:36:47 +02:00
Massimiliano Pippi
2b7b1b71cb use custom spinbox 2014-05-08 00:29:03 +02:00
Massimiliano Pippi
a918460984 added custom spinbox for selecting RAM values 2014-05-08 00:28:44 +02:00
grossmj
ddfdfb3d04 Option to use default IOU RAM & NVRAM values. Avoid to silently not
display exceptions before the GUI has started.
2014-05-07 15:54:08 -06:00
Joe Bowen
e6a3876c74 Layout of the VPCS UI 2014-05-07 14:43:15 -06:00
grossmj
9f11d9eac5 Fixes #33. RAM and NVRAM IOU image settings not propagated when creating
the device.
2014-05-07 11:13:05 -06:00
Jeremy Grossmann
70f0278e14 Merge pull request #34 from planctechnologies/master
Authenticate with cloud provider (GNS-48)
2014-05-07 10:20:20 -06:00
Jerry Seutter
91e1611dde Merge dev to master
Includes cloud authentication changes GNS-48
2014-05-07 15:18:01 +00:00
Jerry Seutter
0132e241d7 Disabling Rackspace tests while not scalable 2014-05-07 15:12:46 +00:00
Kieron Bulloch
40571c7cb9 Adding methods to base_cloud_ctrl:
create_instance, list_instances, delete_instance, get_instance,
  create_key_pair, list_key_pairs, delete_key_pair

Adding exception classes
2014-05-06 23:08:10 -04:00
grossmj
9bfc40d9ae Check is current working directory exists. 2014-05-06 19:12:27 -06:00
grossmj
0a257c142c Fixes #31. 2014-05-06 14:16:58 -06:00
grossmj
6467f26c9c Change name of default base startup and private configs 2014-05-06 13:47:06 -06:00
Joe Bowen
5504084bfd First draft of VPCS module 2014-05-06 13:38:11 -06:00
Joe Bowen
4a37b4e39b First draft of VPCS module 2014-05-06 12:45:12 -06:00
grossmj
76d2a12950 Fixes bug where IOS nvram/disk files were not kept after closing a
topology.
2014-05-06 12:22:13 -06:00
Kieron Bulloch
862c45192b Adding create_instance method. 2014-05-05 20:40:35 -04:00
Massimiliano Pippi
1e2ba38401 GNS-12 store/erase cloud settings depending on users choice 2014-05-06 00:58:21 +02:00
Kieron Bulloch
466b7a8dad Merge branch 'gns-25-26-27-key-pairs' into gns-21-22-23-24-instances
Conflicts:
	gns3/cloud/base_cloud_ctrl.py
	tests/test_cloud_integration.py
2014-05-05 18:57:49 -04:00
Kieron Bulloch
a2fe78508c Adding methods to create, list, and delete key pairs. 2014-05-05 18:27:36 -04:00
Kieron Bulloch
0454f25b9e Adding methods to list, get, and delete instances. 2014-05-05 18:27:36 -04:00
Kieron Bulloch
9ae025b831 Adding set_region and list_instances methods to RackspaceCtrl class.
Adding tests for set_region.
2014-05-05 18:27:35 -04:00
Kieron Bulloch
b57d31adfd Re-working instance related methods to maintain a local list. Will re-add
this functionality if latency impacts user experience.
2014-05-05 18:26:40 -04:00
Kieron Bulloch
ee3853ae5a Adding methods to list, get, and delete instances. 2014-05-05 18:26:39 -04:00
Kieron Bulloch
4ecb8a2a79 Adding set_region and list_instances methods to RackspaceCtrl class.
Adding tests for set_region.
2014-05-05 18:26:38 -04:00
Massimiliano Pippi
a5589e26c3 test settings are erased when users ask for 2014-05-06 00:14:26 +02:00
Massimiliano Pippi
0152e31f4e added tests 2014-05-06 00:14:26 +02:00
Massimiliano Pippi
778b6a3850 load/store timeout settings 2014-05-06 00:14:26 +02:00
Massimiliano Pippi
8bddc7142b instance timeout settings 2014-05-06 00:14:26 +02:00
Massimiliano Pippi
fa3f4cf419 gui controls for instance timeout 2014-05-06 00:14:26 +02:00
Massimiliano Pippi
c5d7874529 terms and conditions link 2014-05-06 00:14:26 +02:00
Massimiliano Pippi
6d36effd81 added tests 2014-05-06 00:14:26 +02:00
Massimiliano Pippi
5a7bd6ec76 save/restore new settings 2014-05-06 00:14:25 +02:00
Massimiliano Pippi
4cfcfcbfc9 changed name to ui controls
Conflicts:
	gns3/ui/cloud_preferences_page.ui
	gns3/ui/cloud_preferences_page_ui.py
2014-05-06 00:14:25 +02:00
Massimiliano Pippi
53a78f3329 added gui interaction tests 2014-05-06 00:14:25 +02:00
Massimiliano Pippi
ec70fcf127 validate terms acceptance 2014-05-06 00:14:25 +02:00
Massimiliano Pippi
21d281c7a2 added instance related settings 2014-05-06 00:14:25 +02:00
grossmj
2f3678a008 Fixes bug that prevented changing any IOU device setting when connected
to another node.
2014-05-05 16:01:42 -06:00
Jerry Seutter
9f106a0835 Merge branch 'dev' of github.com:planctechnologies/gns3-gui into dev 2014-05-05 21:58:22 +00:00
jseutter
92c10ef774 Merge pull request #4 from planctechnologies/gns-48-cloud-authenticate
Gns 48 cloud authenticate
2014-05-05 15:58:01 -06:00
Jeremy Grossmann
2634ff758c Merge pull request #32 from planctechnologies/master
Cloud provider and cloud region preferences
2014-05-05 15:38:33 -06:00
Jerry Seutter
e5bc8e29ec Grammar check docstring 2014-05-05 21:32:10 +00:00
Jerry Seutter
f1befdb908 Re-enabling the cloud preferences page after alpha release 2014-05-05 21:18:56 +00:00
Jerry Seutter
4063801541 Removing duplicate code introduced by merge 2014-05-05 21:08:22 +00:00
Jerry Seutter
94717cb85e Merge remote-tracking branch 'upstream/master' 2014-05-05 19:29:14 +00:00
jseutter
761eb6f7f8 Merge pull request #3 from planctechnologies/gns-10-provider-and-region
Gns 10 provider and region
2014-05-05 13:24:19 -06:00
grossmj
c0ffa1247c Add "All files" filter when looking for an IOU or IOS image in the file
broswer.
2014-05-05 12:51:41 -06:00
grossmj
35d16838cb Fixes duplicated node id issue. 2014-05-03 18:23:55 -06:00
Kieron Bulloch
b04d94975a Moving cloud code into 'cloud' module. 2014-05-03 16:29:30 -04:00
Massimiliano Pippi
50756b7f0a fixed tests 2014-05-02 15:17:36 +02:00
Massimiliano Pippi
5ef1b71ba0 changed parameter name 2014-05-02 15:16:08 +02:00
Massimiliano Pippi
add45546d3 store --> persist 2014-05-02 15:09:50 +02:00
Kieron Bulloch
bf3fb1cc2d Adding "Accept: application/json" header to API requests
Correcting use of requests.Response.json() function (it returns a Python object, not
a JSON string)

Adding call to connection.close() after response received

Adding integration tests for RackspaceCtrl class
2014-04-29 23:01:38 -04:00
Kieron Bulloch
624fc267af Merge branch 'dev' of https://github.com/planctechnologies/gns3-gui into gns-48-cloud-authenticate 2014-04-29 21:48:39 -04:00
Kieron Bulloch
7933520880 Adding unit tests for RackspaceCtrl 2014-04-29 21:47:00 -04:00
Massimiliano Pippi
b9b7503ce4 fixed bugs on loading defaults, added tests 2014-04-30 01:14:32 +02:00
Massimiliano Pippi
b41f339b15 ask cloud provider api for some settings in loadPreferences method + tests 2014-04-30 00:33:33 +02:00
Massimiliano Pippi
3aaf5a2d89 put in settings a string containing provider module path 2014-04-30 00:32:38 +02:00
Massimiliano Pippi
0790263c0a perform validation only when userid/apikey are set 2014-04-29 23:10:15 +02:00
Massimiliano Pippi
35bdf1b226 store cloud settings on disk only when requested 2014-04-29 22:38:46 +02:00
Massimiliano Pippi
7651a880bf test cloud settings storaging 2014-04-29 22:38:02 +02:00
Massimiliano Pippi
883c89944e define group string for cloud settings only once 2014-04-29 22:26:25 +02:00
Massimiliano Pippi
b7bd1940d2 restored type checking on settings load 2014-04-29 22:02:46 +02:00
Massimiliano Pippi
facd537032 forgot in last merge 2014-04-29 21:59:01 +02:00
Massimiliano Pippi
71f296dce2 completed gui test for current stage 2014-04-29 21:58:47 +02:00
Massimiliano Pippi
beeff42120 gui testing, in progress 2014-04-29 21:58:34 +02:00
Massimiliano Pippi
fb5ce128f4 added controls and logic to cloud prefs page 2014-04-29 21:58:20 +02:00
Massimiliano Pippi
333c072d7d added provider list and regions 2014-04-29 21:57:41 +02:00
Kieron Bulloch
5bfc1604d7 Creating base class for cloud API interaction.
Creating provider-specific cloud conroller, RackspaceCloudCtrl
2014-04-28 03:29:23 -04:00
944 changed files with 229067 additions and 268696 deletions

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
gns3/version.py merge=ours

View File

@@ -0,0 +1,34 @@
---
name: GNS3 bug report
about: Create a report to help us fix a bug
title: 'Short description of the bug'
labels: Bug
assignees: ''
---
**Before you start**
Please open an issue only if you suspect there is a bug or any problem with GNS3. Go to https://gns3.com/community for any other questions or for requesting help with GNS3.
You may also post this issue directly on the GNS3 server repository if you know the bug comes from the server: https://github.com/GNS3/gns3-server/issues/new
**Describe the bug**
Please provide a clear and detailed description of what the bug is.
**GNS3 version and operating system (please complete the following information):**
- OS: [e.g. Windows, Linux or macOS]
- GNS3 version [e.g. 2.1.14]
- Any use of the GNS3 VM or remote server (ESXi, bare metal etc.)
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Screenshots or videos**
If applicable, add screenshots (e.g. of the topology and/or error message) or links to videos to help explain the problem. This will help us a lot to quickly find the bug and fix it.
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,10 @@
---
name: GNS3 development
about: Any question or discussion regarding GNS3 development
title: ''
labels: ''
assignees: ''
---

View File

@@ -0,0 +1,25 @@
---
name: GNS3 feature request
about: Suggest an idea for GNS3
title: 'Short description of the feature request'
labels: Enhancement
assignees: ''
---
**Before you start**
Please check if a similar feature request has already been submitted.
You may also post this issue directly on the GNS3 server repository if you know the feature request only applies to the server: https://github.com/GNS3/gns3-server/issues/new
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen. If applicable, please provide screenshots
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -0,0 +1,16 @@
name: Add new issues to GNS3 project
on:
issues:
types:
- opened
jobs:
add-to-project:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v0.4.0
with:
project-url: https://github.com/orgs/GNS3/projects/3
github-token: ${{ secrets.ADD_NEW_ISSUES_TO_PROJECT }}

76
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,76 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]
schedule:
- cron: '27 6 * * 2'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

19
.github/workflows/testing.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: testing
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build and run Docker image
run: |
docker build -t gns3-gui-test .
docker run gns3-gui-test

19
.gitignore vendored
View File

@@ -37,6 +37,7 @@ nosetests.xml
# PyCharm
.idea
/.eggs
# OSX
.DS_Store
@@ -45,3 +46,21 @@ nosetests.xml
*_log.txt
*.log
# Gedit Temp Files
*~
# Qt creator
*.autosave
# Licence keys
keys
# Custom config
/gns3_server.ini
updates
.cache
__pycache__
# Virtualenv
env
venv

View File

@@ -1,24 +0,0 @@
language: python
python:
- "2.7"
- "3.3"
install:
- "pip install -r requirements.txt --use-mirrors"
- "pip install tox"
script: "python setup.py test"
branches:
only:
- master
notifications:
email: false
irc:
channels:
- "chat.freenode.net#gns3"
on_success: change
on_failure: always

14
.whitesource Normal file
View File

@@ -0,0 +1,14 @@
{
"scanSettings": {
"configMode": "AUTO",
"configExternalURL": "",
"projectToken" : "",
"baseBranches": ["master", "2.2", "3.0"]
},
"checkRunSettings": {
"vulnerableCheckRunConclusionLevel": "failure"
},
"issueSettings": {
"minSeverityLevel": "LOW"
}
}

View File

@@ -1 +1,2 @@
Jeremy Grossmann
Jeremy Grossmann
Julien Duponchelle

2446
CHANGELOG Normal file

File diff suppressed because it is too large Load Diff

54
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,54 @@
# Contributing to GNS3
We welcome contributions and bugs reports from everyone.
We are friendly so don't be afraid to ask questions.
## Bug reports
Before reporting an issue:
* check our website over at https://gns3.com
* check if an issue already exists on https://github.com/GNS3/gns3-gui
* check if an issue already exists on https://github.com/GNS3/gns3-server
Please post on our community website if you are unsure you found a bug,
you will get faster support and be able to exchange with more users.
If you are unsure which project you should create an issue for, just do
it on https://github.com/GNS3/gns3-gui we will take care of the triage.
For bugs specific to the GNS3 VM, please report on https://github.com/GNS3/gns3-vm
## Security issues
For security issues please keep it private and send an email to developers@gns3.net
## Asking for new features
The best is to start a discussion on the community website in order to get feedback
from the whole community.
## Contributing code
We welcome code contribution from everyone including beginners.
Don't be afraid to submit a half finished or mediocre contribution and we will help you.
Don't hesitate to share your plans before starting working on a contribution, we can help
you to find the best approach.
### Contributors License Agreements
We at GNS3 are eager to work with you. For small changeslittle bugfixes, correcting typos, and the likeplease just submit pull requests to any of our projects. For larger changes, though, we have to ask you to jump through a little hoop.
In particular, in order for us to accept any major patches from you, you will have to electronically sign a statement that indicates two things:
- You are willingly licensing your contributions under the terms of the open source license of the project that youre contributing to.
- You are legally able to license your contributions as stated.
The reason we do this is to ensure, to the extent possible, that we dont “taint” the projects we manage with contributions that turn out to be improper. This protects everyone who wants to use the projects, including you!
More information there: https://github.com/GNS3/cla
### Pull requests
Creating a pull request is the easiest way to contribute code. Do not hesitate to create one early when contributing for new feature in order to get our feedback.

504
COPYING Normal file
View File

@@ -0,0 +1,504 @@
GNU Public License (GPL)
------------------------
GNS3 is released under the GPLv3 (see LICENSE) with the additional
exemption that compiling, linking, and/or using OpenSSL is allowed.
GNS3 trademark
--------------
"GNS3" is a trademark of GNS3 Technologies, Inc.
Windows Driver Kit
------------------
The Windows binary distribution includes devcon.exe, a Microsoft(R)
Windows Driver Kit (WDK) sample in object code form which is
redistributed under the terms of the WDK License terms.
With respect to binaries built using the Microsoft(R) Windows
Driver Kit (WDK), GPLv3 does not extend to any WDK Distributable Code.
All WDK Distributable Code is considered by the licensors of GNS3
to constitute, or be equivalent to, "System Libraries" as defined in
section 1 of GPLv3.
OpenSSL License
---------------
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
the OpenSSL License and the original SSLeay license apply to the toolkit.
See below for the actual license texts. Actually both licenses are BSD-style
Open Source licenses. In case of any license issues related to OpenSSL
please contact openssl-core@openssl.org.
/* ====================================================================
* Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
Original SSLeay License
-----------------------
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
=====================================================================================================
Several fantastic pieces of free and open-source software have really get GNS3 to where it is today.
A few require that we include their license agreements within our software.
=====================================================================================================
License notice for Qt
---------------------
http://doc.qt.io/qt-4.8/gpl.html
License notice for PyQt
-----------------------
http://www.gnu.org/licenses/gpl.html
License notice for jsonschema
-----------------------------
https://github.com/Julian/jsonschema/blob/master/COPYING
Copyright (c) 2013 Julian Berman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
License notice for aiohttp
--------------------------
https://github.com/KeepSafe/aiohttp/blob/master/LICENSE.txt
Copyright (c) 2013, 2014, 2015 Nikolay Kim and Andrew Svetlov
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
License notice for Jinja
------------------------
https://github.com/KeepSafe/aiohttp/blob/master/LICENSE.txt
Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details.
Some rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* The names of the contributors may not be used to endorse or
promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License notice for raven
------------------------
https://github.com/getsentry/raven-python/blob/master/LICENSE
Copyright (c) 2015 Functional Software, Inc and individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* The names of the contributors may not be used to endorse or
promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License notice for pywin32
--------------------------
https://github.com/SublimeText/Pywin32/blob/master/License.txt
Unless stated in the specfic source file, this work is
Copyright (c) 1996-2008, Greg Stein and Mark Hammond.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
Neither names of Greg Stein, Mark Hammond nor the name of contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License notice for Winpcap
--------------------------
https://www.winpcap.org/misc/copyright.htm
Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy).
Copyright (c) 2005 - 2010 CACE Technologies, Davis (California).
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* The names of the contributors may not be used to endorse or
promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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 2
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License notice for cpulimit
---------------------------
https://github.com/opsengine/cpulimit/blob/master/LICENSE
Copyright (C) 2005-2012, by: Angelo Marletta <angelo dot marletta at gmail dot com>
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 2
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
License notice for Cygwin
-------------------------
https://cygwin.com/licensing.html
License notice for SuperPutty
-----------------------------
https://github.com/jimradford/superputty/blob/master/License.txt
Copyright (c) 2009 Jim Radford http://www.jimradford.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
License notice for Putty
------------------------
http://www.chiark.greenend.org.uk/~sgtatham/putty/licence.html
PuTTY is copyright 1997-2015 Simon Tatham.
Portions copyright Robert de Bath, Joris van Rantwijk, Delian Delchev, Andreas Schultz, Jeroen Massar,
Wez Furlong, Nicolas Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus Kuhn,
Colin Watson, Christopher Staite, and CORE SDI S.A.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
License notice for iouyap
-------------------------
https://github.com/GNS3/iouyap/blob/master/LICENSE
License notice for Dynamips
---------------------------
https://github.com/GNS3/dynamips/blob/master/COPYING
License notice for Qemu
-----------------------
http://wiki.qemu.org/License
License notice for VPCS
-----------------------
Copyright (c) 2007-2013, Paul Meng (mirnshi@gmail.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
License notice for Python
-------------------------
https://www.python.org/download/releases/3.4.2/license/
License notice for BusyBox
---------------------------
BusyBox is distributed under version 2 of the General Public License
https://busybox.net/license.html
Source code is available here:
https://github.com/GNS3/busybox
Licence notice for zipstream
-----------------------------
zipstream is distributed under version 3 of the General Public License
https://github.com/allanlei/python-zipstream/blob/master/LICENSE
Source code is available here:
https://pypi.python.org/pypi/zipstream
Licence notice for aiohttp_cors
-------------------------------
Copyright 2015 Vladimir Rutsky <vladimir@rutsky.org>.
Licensed under the Apache License, Version 2.0, see LICENSE file for details.
https://github.com/aio-libs/aiohttp_cors

16
Dockerfile Normal file
View File

@@ -0,0 +1,16 @@
# Run tests inside a container
FROM ubuntu:18.04
MAINTAINER GNS3 Team
RUN apt-get update
RUN apt-get install -y --force-yes python3.6 python3-pyqt5 python3-pip python3-pyqt5.qtsvg python3-pyqt5.qtwebsockets python3.6-dev xvfb
RUN apt-get clean
ADD dev-requirements.txt /dev-requirements.txt
ADD requirements.txt /requirements.txt
RUN pip3 install --no-cache-dir -r /dev-requirements.txt
ADD . /src
WORKDIR /src
CMD xvfb-run python3.6 -m pytest -vv

View File

@@ -1,11 +1,10 @@
include README.rst
include README.md
include AUTHORS
include INSTALL
include LICENSE
include MANIFEST.in
include tox.ini
include requirements.txt
recursive-include tests *
recursive-include docs *
recursive-include gns3 *
recursive-include resources *
recursive-exclude * __pycache__
recursive-exclude * *.py[co]

62
README.md Normal file
View File

@@ -0,0 +1,62 @@
GNS3-gui
========
[![image](https://github.com/GNS3/gns3-gui/workflows/testing/badge.svg)](https://github.com/GNS3/gns3-gui/actions?query=workflow%3Atesting)
[![image](https://img.shields.io/pypi/v/gns3-gui.svg)](https://pypi.python.org/pypi/gns3-gui)
[![image](https://snyk.io/test/github/GNS3/gns3-gui/badge.svg)](https://snyk.io/test/github/GNS3/gns3-gui)
GNS3 GUI repository.
Installation
------------
Please see <https://docs.gns3.com/>
Software dependencies
---------------------
PyQt5 which is either part of the Linux distribution or installable from
PyPi. The other Python dependencies are automatically installed during
the GNS3 GUI installation and are listed
[here](https://github.com/GNS3/gns3-gui/blob/master/requirements.txt)
For connecting to nodes using Telnet, a Telnet client is required. On
Linux that's a terminal emulator like xterm, gnome-terminal, konsole
plus the telnet program. For connecting to nodes with a GUI, a VNC
client is required, optionally a SPICE client can be used for Qemu
nodes.
For using packet captures within GNS3, Wireshark should be installed.
It's recommended, but if you don't need that functionality you can go
without it.
Development
-----------
If you want to update the interface, modify the .ui files using QT
tools. And:
``` {.bash}
cd scripts
python build_pyqt.py
```
### Debug
If you want to see the full logs in the internal shell you can type:
``` {.bash}
debug 2
```
Or start the app with --debug flag.
Due to the fact PyQT intercept you can use a web debugger for inspecting
stuff: <https://github.com/Kozea/wdb>
Security issues
---------------
Please contact us at <security@gns3.net>

View File

@@ -1,35 +0,0 @@
GNS3-gui
========
New GNS3 GUI repository (alpha stage).
Warning: this is not the repository for the stable version of GNS3 (0.8.6), please go to the gns3-legacy repository for it.
Linux/Unix
----------
Dependencies:
- Python version 3.3 or above
- pip & setuptools must be installed, please see http://pip.readthedocs.org/en/latest/installing.html
(or sudo apt-get install python3-pip but install more packages)
- PyQt must be installed, to install on Debian-like Linux: sudo apt-get install python3-pyqt4
- Dynamips version 0.2.11 or above (http://github.com/GNS3/dynamips)
.. code:: bash
cd gns3-gui-master
sudo python3 setup.py install
gns3
`Detailed instructions for Debian Jesse <http://forum.gns3.net/topic8988.html>`_.
Windows
-------
Please use our all-in-one installer.
Mac OS X
--------
DMG package is not available yet.

5
SECURITY.md Normal file
View File

@@ -0,0 +1,5 @@
# Security Policy
## Reporting a Vulnerability
Please use GitHub's report a vulnerability feature. More information can be found in https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability

20
appveyor.yml Normal file
View File

@@ -0,0 +1,20 @@
version: '{build}-{branch}'
image: Visual Studio 2022
platform: x64
environment:
PYTHON: "C:\\Python38-x64"
DISTUTILS_USE_SDK: "1"
install:
- cinst nmap
- "%PYTHON%\\python.exe -m pip install -U pip setuptools" # upgrade pip & setuptools first
- "%PYTHON%\\python.exe -m pip install -r dev-requirements.txt"
- "%PYTHON%\\python.exe -m pip install -r win-requirements.txt"
build: off
test_script:
- "%PYTHON%\\python.exe -m pytest -v"

View File

@@ -1,4 +1,5 @@
-rrequirements.txt
pytest
pytest-pythonpath # useful for running tests outside tox
pytest==7.2.0
flake8==5.0.4
pytest-timeout==2.1.0

40
fake_frozen_gns3.py Executable file
View File

@@ -0,0 +1,40 @@
#!/usr/bin/env python
#
# 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/>.
"""
This script fake GNS3 run as a frozen app.
Use it for testing stuff like self update.
"""
import os
import sys
import importlib
# Fake GNS3 run from a binary
sys.executable = os.path.realpath(__file__)
# Add site-package directory before cx_freeze directory
sys.path.insert(0, os.path.dirname(sys.executable))
sys.path.insert(0, os.path.join(os.path.dirname(sys.executable), 'site-packages'))
sys.frozen = True
sys.executable = "/Applications/GNS3.app/Contents/MacOS/gns3"
os.environ["_"] = "/Applications/GNS3.app/Contents/MacOS/gns3"
module = importlib.import_module("gns3.main")
module.main()

29
gns3-gui.appdata.xml Normal file
View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2016 Athmane Madjoudj <athmane@fedoraproject.org> -->
<component type="desktop">
<id>gns3-gui.desktop</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0+</project_license>
<name>GNS3</name>
<summary>Graphical Network Simulator 3</summary>
<description>
<p>
GNS3 is a graphical network simulator that allows you to design complex network
topologies. You may run simulations or configure devices ranging from simple
workstations to powerful routers.
</p>
</description>
<screenshots>
<screenshot type="default">
<image>https://a.fsdn.com/con/app/proj/gns-3/screenshots/127765.jpg</image>
</screenshot>
<screenshot>
<image>https://a.fsdn.com/con/app/proj/gns-3/screenshots/127755.jpg</image>
</screenshot>
<screenshot>
<image>https://a.fsdn.com/con/app/proj/gns-3/screenshots/127755.jpg</image>
</screenshot>
</screenshots>
<url type="homepage">http://gns3.com/</url>
<update_contact>athmane_at_fedoraproject.org</update_contact>
</component>

9
gns3-gui.desktop Normal file
View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Name=GNS3
GenericName=Graphical Network Simulator 3
Comment=Graphical Network Simulator 3
Exec=gns3
Icon=gns3
Terminal=false
Type=Application
Categories=Application;Network;Qt;

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#!/usr/bin/env python
#
# Copyright (C) 2014 GNS3 Technologies Inc.
# 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
@@ -15,13 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Base class for NIOs (Network Input/Output).
"""
from .main import main
class NIO(object):
def __init__(self):
pass
main()

93
gns3/appliance_manager.py Normal file
View File

@@ -0,0 +1,93 @@
#!/usr/bin/env python
#
# Copyright (C) 2016 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/>.
from .qt import QtCore
from .controller import Controller
from .local_config import LocalConfig
from .settings import GENERAL_SETTINGS
import logging
log = logging.getLogger(__name__)
class ApplianceManager(QtCore.QObject):
"""
Manager for appliances.
"""
appliances_changed_signal = QtCore.Signal()
def __init__(self):
super().__init__()
self._appliances = []
self._controller = Controller.instance()
self._controller.connected_signal.connect(self.refresh)
self._controller.disconnected_signal.connect(self._controllerDisconnectedSlot)
def refresh(self, update=False):
"""
Gets the appliances from the controller.
"""
if self._controller.connected():
settings = LocalConfig.instance().loadSectionSettings("MainWindow", GENERAL_SETTINGS)
symbol_theme = settings["symbol_theme"]
if update is True:
self._controller.get("/appliances?update=yes&symbol_theme={}".format(symbol_theme), self._listAppliancesCallback, progressText="Downloading appliances from online registry...")
else:
self._controller.get("/appliances?symbol_theme={}".format(symbol_theme), self._listAppliancesCallback)
def _controllerDisconnectedSlot(self):
"""
Called when the controller has been disconnected.
"""
self._appliances = []
self.appliances_changed_signal.emit()
def appliances(self):
"""
Returns the appliances.
:returns: array of appliances
"""
return self._appliances
def _listAppliancesCallback(self, result, error=False, **kwargs):
"""
Callback to get the appliances.
"""
if error is True:
log.error("Error while getting appliances list: {}".format(result.get("message", "unknown")))
return
self._appliances = result
self.appliances_changed_signal.emit()
@staticmethod
def instance():
"""
Singleton to return only on instance of ApplianceManager.
:returns: instance of ApplianceManager
"""
if not hasattr(ApplianceManager, '_instance') or ApplianceManager._instance is None:
ApplianceManager._instance = ApplianceManager()
return ApplianceManager._instance

69
gns3/application.py Normal file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/env python
#
# 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 sys
from .qt import QtWidgets, QtGui, QtCore
from gns3.utils import parse_version
from .version import __version__
import logging
log = logging.getLogger(__name__)
class Application(QtWidgets.QApplication):
file_open_signal = QtCore.pyqtSignal(str)
def __init__(self, argv, hdpi=True):
self.setStyle(QtWidgets.QStyleFactory.create("Fusion"))
# both Qt and PyQt must be version >= 5.6 in order to enable high DPI scaling
if parse_version(QtCore.QT_VERSION_STR) >= parse_version("5.6") and parse_version(QtCore.PYQT_VERSION_STR) >= parse_version("5.6"):
# only available starting Qt version 5.6
if hdpi:
if sys.platform.startswith("linux"):
log.warning("HDPI mode is enabled. HDPI support on Linux is not fully stable and GNS3 may crash depending of your version of Linux. To disabled HDPI mode please edit ~/.config/GNS3/gns3_gui.conf and set 'hdpi' to 'false'")
self.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
self.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps)
else:
log.info("HDPI mode is disabled")
self.setAttribute(QtCore.Qt.AA_DisableHighDpiScaling)
super().__init__(argv)
# this is tell Wayland what is the name of the desktop file (gns3.desktop)
self.setDesktopFileName("gns3")
# this info is necessary for QSettings
self.setOrganizationName("GNS3")
self.setOrganizationDomain("gns3.net")
self.setApplicationName("GNS3")
self.setApplicationVersion(__version__)
# File path if we have received the path to
# a file on system via an OSX event
self.open_file_at_startup = None
def event(self, event):
# When you double click file you receive an event
# and not the file as command line parameter
if sys.platform.startswith("darwin"):
if isinstance(event, QtGui.QFileOpenEvent):
self.open_file_at_startup = str(event.file())
self.file_open_signal.emit(str(event.file()))
return super().event(event)

342
gns3/base_node.py Normal file
View File

@@ -0,0 +1,342 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Base class for node classes.
"""
from .qt import QtCore
from .ports.port import Port
import logging
log = logging.getLogger(__name__)
class BaseNode(QtCore.QObject):
"""
BaseNode implementation.
:param module: Module instance
:param server: client connection to a server
:param project: Project instance
"""
# signals used to let the GUI know about some events.
created_signal = QtCore.Signal(int)
started_signal = QtCore.Signal()
stopped_signal = QtCore.Signal()
suspended_signal = QtCore.Signal()
updated_signal = QtCore.Signal()
loaded_signal = QtCore.Signal()
deleted_signal = QtCore.Signal()
error_signal = QtCore.Signal(int, str)
server_error_signal = QtCore.Signal(int, str)
_instance_count = 1
# node statuses
stopped = 0
started = 1
suspended = 2
# node categories
routers = "router"
switches = "switch"
end_devices = "guest"
security_devices = "firewall"
def __init__(self, module, compute, project):
super().__init__()
# create an unique ID
self._id = BaseNode._instance_count
BaseNode._instance_count += 1
self._module = module
self._compute = compute
assert project is not None
self._project = project
self._initialized = False
self._loading = False
self._status = BaseNode.stopped
self._ports = []
self._links = set()
def links(self):
"""
Links connected to this node
"""
return self._links
def addLink(self, link):
"""
Add a link connected to this node
:param link: link object
"""
self._links.add(link)
def deleteLink(self, link):
"""
Delete a link connected to this node
:param link: link object
"""
try:
self._links.remove(link)
except KeyError:
pass
def state(self):
"""
Returns a human readable status of this node.
:returns: string
"""
status = self.status()
if status == self.started:
return "started"
elif status == self.stopped:
return "stopped"
elif status == self.suspended:
return "suspended"
return "unknown"
@classmethod
def reset(cls):
"""
Reset the instance count.
"""
cls._instance_count = 1
def module(self):
"""
Returns this node module.
:returns: Module instance
"""
return self._module
def compute(self):
"""
Returns this node compute.
:returns: Compute instance
"""
return self._compute
def project(self):
"""
Returns this node project.
:returns: Project instance
"""
return self._project
def id(self):
"""
Returns this node identifier.
:returns: node identifier (integer)
"""
return self._id
def setId(self, new_id):
"""
Sets an identifier for this node.
:param new_id: node identifier (integer)
"""
self._id = new_id
# update the instance count to avoid conflicts
if new_id >= BaseNode._instance_count:
BaseNode._instance_count = new_id + 1
def status(self):
"""
Returns the status of this node.
0 = stopped, 1 = started, 2 = suspended.
:returns: node status (integer)
"""
return self._status
def setStatus(self, status):
"""
Sets a status for this node.
0 = stopped, 1 = started, 2 = suspended.
:param status: node status (integer)
"""
if status == self._status:
return
self._status = status
if status == self.started:
for port in self._ports:
# set ports as started
port.setStatus(Port.started)
self.started_signal.emit()
elif status == self.stopped:
for port in self._ports:
# set ports as stopped
port.setStatus(Port.stopped)
self.stopped_signal.emit()
elif status == self.suspended:
for port in self._ports:
# set ports as suspended
port.setStatus(Port.suspended)
self.suspended_signal.emit()
def initialized(self):
"""
Returns if the node has been initialized
:returns: boolean
"""
return self._initialized
def setInitialized(self, initialized):
"""
Sets if the node has been initialized
:param initialized: boolean
"""
self._initialized = initialized
def update(self, new_settings):
"""
Updates the settings for this node.
Must be overloaded.
:param new_settings: settings dictionary
"""
raise NotImplementedError()
def ports(self):
"""
Returns all the ports for this node.
:returns: list of Port instances
"""
return self._ports
def controllerHttpPost(self, path, callback, body={}, context={}, **kwargs):
"""
POST on current server / project
:param path: Remote path
:param callback: callback method to call when the server replies
:param body: params to send (dictionary)
:param context: Pass a context to the response callback
"""
self._project.post(path, callback, body=body, context=context, **kwargs)
def controllerHttpPut(self, path, callback, body={}, context={}, **kwargs):
"""
PUT on current server / project
:param path: Remote path
:param callback: callback method to call when the server replies
:param body: params to send (dictionary)
:param context: Pass a context to the response callback
"""
self._project.put(path, callback, body=body, context=context, **kwargs)
def controllerHttpGet(self, path, callback, context={}, **kwargs):
"""
Get on current server / project
:param path: Remote path
:param callback: callback method to call when the server replies
:param body: params to send (dictionary)
:param context: Pass a context to the response callback
"""
self._project.get(path, callback, context=context, **kwargs)
def controllerHttpDelete(self, path, callback, context={}, **kwargs):
"""
Delete on current server / project
:param path: Remote path
:param callback: callback method to call when the server replies
:param context: Pass a context to the response callback
"""
self._project.delete(path, callback, context=context, **kwargs)
@staticmethod
def defaultCategories():
"""
Returns the default categories.
:returns: dict
"""
categories = {"Routers": BaseNode.routers,
"Switches": BaseNode.switches,
"End devices": BaseNode.end_devices,
"Security devices": BaseNode.security_devices}
return categories
@staticmethod
def defaultSymbol():
"""
Returns the default symbol path for this node.
Must be overloaded.
:returns: symbol path (or resource).
"""
raise NotImplementedError()
@staticmethod
def categories(self):
"""
Returns the node categories the node is part of (used by the device panel).
:returns: list of node category (integer)
"""
raise NotImplementedError()
def __str__(self):
"""
Must be overloaded.
"""
raise NotImplementedError()

View File

@@ -1,21 +0,0 @@
!
kerberos password
crypto RSA-key-pair %h.mydomain.com 0 1014940935
30820155 02010030 0D06092A 864886F7 0D010101 05000482 013F3082 013B0201
00024100 A7EA2920 73033037 689F8166 B6AEA7FF 91015466 7379FA4F D7B175C3
8D5D1E56 89B00E73 D5553491 06D651DA 71213D18 3E4EAF44 8C5F05F1 E8C1FE47
B07D5A1B 02030100 01024049 FE964106 6DD14199 8930ACE2 B3F4B45A 620B9F5A
23D67A78 C26AF2D1 C8C72504 987ADD3E 2755DCC4 70AADB86 679171D7 54A9038F
0EB080E7 8B514EB8 8A038102 2100D588 DF0A6D31 AEF5C231 5A4A3459 5D3FD973
F1A13EA8 2C25D210 6ACD4733 39AF0221 00C94EC2 9428B371 2599E7EA 8C89E86C
E188F689 3AFCFE7A 59B42810 E83DABBD 55022100 944FB792 D75ACDC9 96328F22
C10F5CAC 2F4DCF83 0E30E250 F6813E9D 0B99F1B3 02204863 D126D428 0B05197E
4362FC68 9F56CF18 D0AA6CB5 DA2B8DD4 66980D2D 47ED0221 00991914 B6CDC66E
60AF0332 D5FB2771 B9F0317B 886E6E48 B86CDFDF 3FC1D48E CA
quit
305C300D 06092A86 4886F70D 01010105 00034B00 30480241 00A7EA29 20730330
37689F81 66B6AEA7 FF910154 667379FA 4FD7B175 C38D5D1E 5689B00E 73D55534
9106D651 DA71213D 183E4EAF 448C5F05 F1E8C1FE 47B07D5A 1B020301 0001
quit
end

View File

@@ -1,21 +0,0 @@
!
hostname %h
!
no ip domain lookup
no ip icmp rate-limit unreachable
ip tcp synwait 5
no cdp log mismatch duplex
!
line con 0
exec-timeout 0 0
logging synchronous
privilege level 15
no login
line aux 0
exec-timeout 0 0
logging synchronous
privilege level 15
no login
!
!
end

247
gns3/compute.py Normal file
View File

@@ -0,0 +1,247 @@
#!/usr/bin/env python
#
# Copyright (C) 2016 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 uuid
class Compute:
"""
An instance of a compute.
"""
def __init__(self, compute_id=None):
if compute_id is None:
compute_id = str(uuid.uuid4())
self._compute_id = compute_id
self._name = compute_id
self._connected = False
self._protocol = "http"
self._host = None
self._port = 3080
self._user = None
self._password = None
self._cpu_usage_percent = None
self._memory_usage_percent = None
self._capabilities = {"node_types": []}
self._last_error = None
def id(self):
"""
Returns the compute ID.
:returns: compute identifier
"""
return self._compute_id
def name(self):
"""
Returns the compute name.
:returns: compute name
"""
return self._name
def setName(self, name):
"""
Sets the compute name.
:param name: compute name
"""
self._name = name
def connected(self):
"""
Returns whether or not there is a connection to the compute.
:returns: boolean
"""
return self._connected
def setConnected(self, value):
"""
Sets whether or not there is a connection to the compute.
:param value: boolean
"""
self._connected = value
def host(self):
"""
Returns the compute host.
:returns: host (string)
"""
return self._host
def setHost(self, host):
"""
Sets the compute host.
:param host: host (string)
"""
self._host = host
def port(self):
"""
Returns the compute port number.
:returns: port number (integer)
"""
return self._port
def setPort(self, port):
"""
Sets the compute port number.
:param port: port number (integer)
"""
self._port = port
def user(self):
"""
Returns the compute user for HTTP authentication.
:returns: user (string)
"""
return self._user
def setUser(self, user):
"""
Sets the compute user for HTTP authentication.
:param user: user (string)
"""
self._user = user
def setPassword(self, password):
"""
Returns the compute password for HTTP authentication.
:returns: password (string)
"""
self._password = password
def protocol(self):
"""
Returns the compute protocol.
:returns: protocol (string)
"""
return self._protocol
def setProtocol(self, protocol):
"""
Sets the compute protocol.
:param protocol: protocol (string)
"""
self._protocol = protocol
def cpuUsagePercent(self):
"""
Returns the compute CPU usage.
:returns: CPU usage (integer)
"""
return self._cpu_usage_percent
def setCpuUsagePercent(self, usage):
"""
Sets the compute CPU usage.
:param usage: CPU usage (integer)
"""
self._cpu_usage_percent = usage
def setMemoryUsagePercent(self, usage):
"""
Returns the compute memory usage.
:returns: memory usage (integer)
"""
self._memory_usage_percent = usage
def memoryUsagePercent(self):
"""
Sets the compute memory usage.
:param usage: memory usage (integer)
"""
return self._memory_usage_percent
def capabilities(self):
"""
Returns the compute capabilities
:returns: capabilities (dictionary)
"""
return self._capabilities
def setCapabilities(self, value):
"""
Sets the compute capabilities
:param value: capabilities (dictionary)
"""
self._capabilities = value
def setLastError(self, last_error):
self._last_error = last_error
def lastError(self):
return self._last_error
def __str__(self):
return self._compute_id
def __json__(self):
return {"host": self._host,
"port": self._port,
"protocol": self._protocol,
"user": self._user,
"password": self._password,
"name": self._name,
"compute_id": self._compute_id}
def __eq__(self, v):
if isinstance(v, Compute):
return self.__json__() == v.__json__()
return False

265
gns3/compute_manager.py Normal file
View File

@@ -0,0 +1,265 @@
#!/usr/bin/env python
#
# Copyright (C) 2016 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/>.
from .qt import QtCore
from .compute import Compute
from .controller import Controller
import sys
import copy
import urllib
import datetime
import logging
log = logging.getLogger(__name__)
class ComputeManager(QtCore.QObject):
"""
Manager for computes.
"""
created_signal = QtCore.Signal(str)
updated_signal = QtCore.Signal(str)
deleted_signal = QtCore.Signal(str)
def __init__(self):
super().__init__()
self._computes = {}
self._controller = Controller.instance()
self._controller.connected_signal.connect(self._controllerConnectedSlot)
self._controller.disconnected_signal.connect(self._controllerDisconnectedSlot)
self._controllerConnectedSlot()
# No need to refresh via an API call if we received fresh data from the notification feed
self._last_computes_refresh = datetime.datetime.now().timestamp()
self._timer = QtCore.QTimer()
self._timer.setInterval(1000)
self._refreshingComputes = False
self._timer.timeout.connect(self._refreshComputesSlot)
self._timer.start()
def _refreshComputesSlot(self):
"""
Called when computes are refreshed.
"""
if self._refreshingComputes:
return
if self._controller.connected() and datetime.datetime.now().timestamp() - self._last_computes_refresh > 1:
self._last_computes_refresh = datetime.datetime.now().timestamp()
self._refreshingComputes = True
self._controller.get("/computes", self._listComputesCallback, showProgress=False, timeout=30)
def _controllerConnectedSlot(self):
"""
Called when connected to a compute.
"""
if self._controller.connected():
self._refreshingComputes = True
self._controller.get("/computes", self._listComputesCallback, showProgress=False, timeout=30)
def _controllerDisconnectedSlot(self):
"""
Called when disconnected from a compute.
"""
for compute_id in list(self._computes):
del self._computes[compute_id]
self.deleted_signal.emit(compute_id)
def _listComputesCallback(self, result, error=False, **kwargs):
"""
Callback to list computes.
"""
self._refreshingComputes = False
if error is True:
log.error("Error while getting compute list: {}".format(result["message"]))
return
for compute in result:
self.computeDataReceivedCallback(compute)
def computeDataReceivedCallback(self, compute):
"""
Called when we received data from a compute node.
"""
self._last_computes_refresh = datetime.datetime.now().timestamp()
new_node = False
compute_id = compute["compute_id"]
if compute_id not in self._computes:
new_node = True
self._computes[compute_id] = Compute(compute_id)
self._computes[compute_id].setName(compute["name"])
self._computes[compute_id].setConnected(compute["connected"])
self._computes[compute_id].setProtocol(compute["protocol"])
self._computes[compute_id].setHost(compute["host"])
self._computes[compute_id].setPort(compute["port"])
self._computes[compute_id].setUser(compute["user"])
self._computes[compute_id].setCpuUsagePercent(compute["cpu_usage_percent"])
self._computes[compute_id].setMemoryUsagePercent(compute["memory_usage_percent"])
self._computes[compute_id].setCapabilities(compute["capabilities"])
self._computes[compute_id].setLastError(compute.get("last_error"))
if new_node:
self.created_signal.emit(compute_id)
else:
self.updated_signal.emit(compute_id)
def computeIsTheRemoteGNS3VM(self, compute):
"""
:returns: boolean True if the remote server is the remote GNS3 VM
"""
if compute.id() != "local" and compute.id() != "vm":
if self.vmCompute() and "GNS3 VM ({})".format(compute.name()) == self.vmCompute().name():
return True
return False
def computes(self):
"""
:returns: List of computes nodes
"""
computes = []
for compute in self._computes.values():
# We filter the remote GNS3 VM compute from the computes list
if not self.computeIsTheRemoteGNS3VM(compute):
computes.append(compute)
return computes
def vmCompute(self):
"""
:returns: The GNS3 VM compute node or None
"""
try:
return self._computes["vm"]
except KeyError:
return None
def localCompute(self):
"""
:returns: The local compute node or None
"""
try:
return self._computes["local"]
except KeyError:
return None
def localPlatform(self):
"""
Return the platform of the local compute.
With a remote controller it could be different of our local platform
"""
c = self.localCompute()
if c is None:
return sys.platform
return c.capabilities().get("platform", sys.platform)
def remoteComputes(self):
"""
:returns: List of non local and non VM computes
"""
return [c for c in self._computes.values() if c.id() != "local" and c.id() != "vm"]
def getCompute(self, compute_id):
"""
Gets a compute by ID
:param compute_id: compute identifier
:returns: compute
"""
if compute_id.startswith("http:") or compute_id.startswith("https:"):
u = urllib.parse.urlsplit(compute_id)
for compute in self._computes.values():
if "{}:{}".format(compute.host(), compute.port()) == u.netloc:
return compute
raise KeyError("Compute ID {} is missing.".format(compute_id))
if compute_id not in self._computes:
self._computes[compute_id] = Compute(compute_id)
self.created_signal.emit(compute_id)
return self._computes[compute_id]
def deleteCompute(self, compute_id):
"""
Deletes a compute by ID
:param compute_id: compute identifier
"""
if compute_id in self._computes:
del self._computes[compute_id]
self._controller.delete("/computes/{compute_id}".format(compute_id=compute_id), None)
self.deleted_signal.emit(compute_id)
def updateList(self, computes):
"""
Sync an array of compute with remote
"""
for compute_id in copy.copy(self._computes):
# Delete compute on controller not in the new computes
if compute_id in ["local", "vm"]:
continue
if compute_id not in [c.id() for c in computes]:
log.debug("Delete compute %s", compute_id)
self.deleteCompute(compute_id)
else:
# Update the changed nodes
for c in computes:
if c.id() == compute_id and c != self._computes[compute_id]:
log.debug("Update compute %s", compute_id)
self._controller.put("/computes/" + compute_id, None, body=c.__json__())
self._computes[compute_id] = c
self.updated_signal.emit(compute_id)
# Create the new nodes
for compute in computes:
if compute.id() not in self._computes:
log.debug("Create compute %s", compute.id())
self._controller.post("/computes", None, body=compute.__json__())
self._computes[compute.id()] = compute
self.created_signal.emit(compute.id())
@staticmethod
def reset():
ComputeManager._instance = None
@staticmethod
def instance():
"""
Singleton to return only on instance of ComputeManager.
:returns: instance of ComputeManager
"""
if not hasattr(ComputeManager, '_instance') or ComputeManager._instance is None:
ComputeManager._instance = ComputeManager()
return ComputeManager._instance

View File

@@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Compute summary view that list all the compute, their status.
"""
from .qt import QtGui, QtCore, QtWidgets
from .compute_manager import ComputeManager
from .topology import Topology
from .node import Node
import logging
log = logging.getLogger(__name__)
class ComputeItem(QtWidgets.QTreeWidgetItem):
"""
Custom item for the QTreeWidget instance
(topology summary view).
:param parent: parent widget
:param compute: Compute instance
"""
def __init__(self, parent, compute):
super().__init__(parent)
self._compute = compute
self._parent = parent
self._status = "unknown"
self._refreshStatusSlot()
def _refreshStatusSlot(self):
"""
Changes the icon to show the node status (started, stopped etc.)
"""
if self is None:
return
usage = None
text = self._compute.name()
if self._compute.cpuUsagePercent() is not None:
text = "{} CPU {}%, RAM {}%".format(text, self._compute.cpuUsagePercent(), self._compute.memoryUsagePercent())
self.setText(0, text)
if self._compute.connected():
self._status = "connected"
self.setToolTip(0, "Server {} version {} running on {}".format(self._compute.name(),
self._compute.capabilities().get("version", "n/a"),
self._compute.capabilities().get("platform", "")))
if usage is None or (self._compute.cpuUsagePercent() < 90 and self._compute.memoryUsagePercent() < 90):
self.setIcon(0, QtGui.QIcon(':/icons/led_green.svg'))
else:
self.setIcon(0, QtGui.QIcon(':/icons/led_yellow.svg'))
else:
last_error = self._compute.lastError()
if last_error:
self.setToolTip(0, "Failed to connect to {}: {}".format(self._compute.name(), last_error))
self.setIcon(0, QtGui.QIcon(':/icons/led_red.svg'))
elif self._status == "unknown":
self.setToolTip(0, "Discovering or connecting to {}...".format(self._compute.name()))
self.setIcon(0, QtGui.QIcon(':/icons/led_gray.svg'))
else:
self._status = "stopped"
self.setToolTip(0, "{} is stopped or cannot be reached".format(self._compute.name()))
self.setIcon(0, QtGui.QIcon(':/icons/led_red.svg'))
self._parent.sortItems(0, QtCore.Qt.AscendingOrder)
# add nodes belonging to this compute
self.takeChildren()
nodes = Topology.instance().nodes()
for node in nodes:
if node.compute().id() == self._compute.id():
item = QtWidgets.QTreeWidgetItem()
item.setText(0, node.name())
if node.status() == Node.started:
item.setIcon(0, QtGui.QIcon(':/icons/led_green.svg'))
elif node.status() == Node.suspended:
item.setIcon(0, QtGui.QIcon(':/icons/led_yellow.svg'))
else:
item.setIcon(0, QtGui.QIcon(':/icons/led_red.svg'))
self.addChild(item)
self.sortChildren(0, QtCore.Qt.AscendingOrder)
class ComputeSummaryView(QtWidgets.QTreeWidget):
"""
Compute summary view implementation.
:param parent: parent widget
"""
def __init__(self, parent):
super().__init__(parent)
self._computes = {}
ComputeManager.instance().created_signal.connect(self._computeAddedSlot)
ComputeManager.instance().updated_signal.connect(self._computeUpdatedSlot)
ComputeManager.instance().deleted_signal.connect(self._computeRemovedSlot)
for compute in ComputeManager.instance().computes():
self._computeAddedSlot(compute.id())
def _computeAddedSlot(self, compute_id):
"""
Called when a compute is added to the list of computes
:params url: URL of the compute
"""
compute = ComputeManager.instance().getCompute(compute_id)
if ComputeManager.instance().computeIsTheRemoteGNS3VM(compute):
return
self._computes[compute_id] = ComputeItem(self, compute)
def _computeUpdatedSlot(self, compute_id):
"""
Called when a compute is updated
:params url: URL of the compute
"""
if compute_id in self._computes:
compute = ComputeManager.instance().getCompute(compute_id)
# We hide the remote GNS3 VM
if ComputeManager.instance().computeIsTheRemoteGNS3VM(compute):
self._computeRemovedSlot(compute_id)
else:
self._computes[compute_id]._refreshStatusSlot()
else:
self._computeAddedSlot(compute_id)
def _computeRemovedSlot(self, compute_id):
"""
Called when a compute is removed to the list of computes
:params url: URL of the compute
"""
if compute_id in self._computes:
self.takeTopLevelItem(self.indexOfTopLevelItem(self._computes[compute_id]))
del self._computes[compute_id]

View File

@@ -19,40 +19,281 @@
Handles commands typed in the GNS3 console.
"""
import os
import sys
import cmd
import logging
import struct
from .qt import sip
from .node import Node
from .qt import QtCore
from .version import __version__
import logging
log = logging.getLogger(__name__)
class ConsoleCmd(cmd.Cmd):
def __init__(self):
def do_env(self, args):
"""
Show the environment variables used by GNS3.
"""
cmd.Cmd.__init__(self)
for key, val in os.environ.items():
print("{}={}".format(key, val))
def do_version(self, args):
"""
Show the version of GNS3 and its dependencies.
"""
print("GNS3 version {}".format(__version__))
compiled = ""
if hasattr(sys, "frozen"):
compiled = "(compiled)"
print("GNS3 version is {} {}".format(__version__, compiled))
print("Python version is {}.{}.{} ({}-bit) with {} encoding".format(sys.version_info[0],
sys.version_info[1],
sys.version_info[2],
struct.calcsize("P") * 8,
sys.getdefaultencoding()))
print("Qt version is {}".format(QtCore.QT_VERSION_STR))
print("PyQt version is {}".format(QtCore.PYQT_VERSION_STR))
print("SIP version is {}".format(sip.SIP_VERSION_STR))
def do_start(self, args):
"""
Start all or a specific device(s)
start {/all | device1 [device2] ...}
"""
if '?' in args or args.strip() == "":
print(self.do_start.__doc__)
return
devices = args.split()
if '/all' in devices:
for node in self._topology.nodes():
if hasattr(node, "start") and node.initialized():
node.start()
else:
for device in devices:
for node in self._topology.nodes():
if node.name() == device:
if hasattr(node, "start") and node.initialized():
node.start()
else:
print("{} cannot be started".format(device))
break
def do_stop(self, args):
"""
Stop all or a specific device(s)
stop {/all | device1 [device2] ...}
"""
if '?' in args or args.strip() == "":
print(self.do_stop.__doc__)
return
devices = args.split()
if '/all' in devices:
for node in self._topology.nodes():
if hasattr(node, "stop") and node.initialized():
node.stop()
else:
for device in devices:
for node in self._topology.nodes():
if node.name() == device:
if hasattr(node, "stop") and node.initialized():
node.stop()
else:
print("{} cannot be stopped".format(device))
break
def do_suspend(self, args):
"""
Suspend all or a specific device(s)
suspend {/all | device1 [device2] ...}
"""
if '?' in args or args.strip() == "":
print(self.do_suspend.__doc__)
return
devices = args.split()
if '/all' in devices:
for node in self._topology.nodes():
if hasattr(node, "suspend") and node.initialized():
node.suspend()
else:
for device in devices:
for node in self._topology.nodes():
if node.name() == device:
if hasattr(node, "suspend") and node.initialized():
node.suspend()
else:
print("{} cannot be suspended".format(device))
break
def do_reload(self, args):
"""
Reload all or a specific device(s)
reload {/all | device1 [device2] ...}
"""
if '?' in args or args.strip() == "":
print(self.do_reload.__doc__)
return
devices = args.split()
if '/all' in devices:
for node in self._topology.nodes():
if hasattr(node, "reload") and node.initialized():
node.reload()
else:
for device in devices:
for node in self._topology.nodes():
if node.name() == device:
if hasattr(node, "reload") and node.initialized():
node.reload()
else:
print("{} cannot be reloaded".format(device))
break
def do_console(self, args):
"""
Console to all or a specific device(s)
console {/all | device1 [device2] ...}
"""
if '?' in args or args.strip() == "":
print(self.do_console.__doc__)
return
devices = args.split()
if '/all' in devices:
for node in self._topology.nodes():
if hasattr(node, "console") and node.initialized() and node.status() == Node.started:
self._start_console(node)
else:
for device in devices:
for node in self._topology.nodes():
if node.name() == device:
if hasattr(node, "console") and node.initialized() and node.status() == Node.started:
self._start_console(node)
else:
print("Cannot console to {}".format(device))
break
def do_log(self, args):
"""
Log a message
log level message
"""
args = args.split()
if len(args) == 0:
return
level = args.pop(0)
if level == "info":
log.info(" ".join(args))
elif level == "warning":
log.warning(" ".join(args))
else:
log.error(" ".join(args))
def _start_console(self, node):
"""
Starts a console application for a specific node.
:param node: Node instance
"""
console_port = node.console()
from .telnet_console import nodeTelnetConsole
nodeTelnetConsole(node, console_port)
def do_debug(self, args):
"""
debug [level] (0 or 1).
Activate or deactivate debugging messages
debug [level] (0, 1 or 2).
"""
if '?' in args or args.strip() == "":
print(self.do_debug.__doc__)
return
root = logging.getLogger()
ch = logging.StreamHandler(sys.stdout)
if len(args) == 1:
try:
level = int(args[0])
if level == 0:
print("Deactivating debugging")
root.removeHandler(ch)
else:
print("Activating debugging")
root.addHandler(ch)
except:
print(self.do_debug.__doc__)
level = int(args[0])
if level == 0:
print("Deactivating debugging")
root.setLevel(logging.INFO)
else:
print("Activating debugging")
root.setLevel(logging.DEBUG)
from .main_window import MainWindow
MainWindow.instance().setSettings({"debug_level": level})
else:
print(self.do_debug.__doc__)
def _show_device(self, params):
"""
Handles the 'show device' command.
:param params: list of parameters
"""
if len(params) == 1:
# print out all the device info
for node in self._topology.nodes():
if hasattr(node, "info"):
print(node.info())
elif len(params) >= 2:
# this is a 'show device <device_name>'
params.pop(0)
for param in params:
node_name = param
found = False
for node in self._topology.nodes():
if hasattr(node, "info") and node.name() == node_name:
print(node.info())
found = True
break
if found is False:
print("{}: no such device".format(node_name))
continue
def do_show(self, args):
"""
Show detail information about every device in current lab:
show device
Show detail information about a device:
show device <device_name>
"""
if '?' in args or args.strip() == "":
print(self.do_show.__doc__)
return
params = args.split()
if params[0] == "device":
self._show_device(params)
else:
print(self.do_show.__doc__)
def do_help(self, args):
"""
Get help on commands
'help' or '?' with no arguments prints a list of commands for which help is available
'help <command>' or '? <command>' gives help on <command>
"""
cmd.Cmd.do_help(self, args)

View File

@@ -15,43 +15,53 @@
# 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 sys
from .qt import sip
import struct
import inspect
import datetime
import platform
from .qt import QtCore, QtWidgets
from .topology import Topology
from .version import __version__
from .console_cmd import ConsoleCmd
from .pycutext import PyCutExt
from .modules import MODULES
from .local_config import LocalConfig
import logging
log = logging.getLogger(__name__)
class ConsoleLogHandler(logging.StreamHandler):
"""
Display log event to the console
"""
def emit(self, record):
if sip.isdeleted(self._console_view):
return
message = self.format(record)
level_no = record.levelno
if level_no >= logging.ERROR:
self._console_view.write_message_signal.emit("{}\n".format(message), "error")
elif level_no >= logging.WARNING:
self._console_view.write_message_signal.emit("{}\n".format(message), "warning")
elif level_no >= logging.INFO:
# To avoid noise on console we display all event only if log level is debug
# or if we force the display in the log record
if "show" in record.__dict__ or logging.getLogger().getEffectiveLevel() == logging.DEBUG:
self._console_view.write_message_signal.emit("{}\n".format(message), "debug")
elif level_no >= logging.DEBUG:
self._console_view.write_message_signal.emit("{}\n".format(message), "debug")
class ConsoleView(PyCutExt, ConsoleCmd):
# list of keywords to color
keywords = set(["aux",
"capture",
"clear",
"console",
"export",
"filter",
"help",
"hist",
"idlepc",
"import",
"list",
"no",
"push",
"reload",
"resume",
"save",
"send",
"show",
"start",
"stop",
"suspend",
"telnet",
"vboxexec",
"qmonitor",
"ver"])
# Emit this signal to write a message on console
write_message_signal = QtCore.Signal(str, str)
def __init__(self, parent):
@@ -60,21 +70,97 @@ class ConsoleView(PyCutExt, ConsoleCmd):
sys.ps1 = '=> '
# Set introduction message
self.intro = "GNS3 management console. Running GNS3 Early Release (ER) version %s.\nCopyright (c) 2006-2014 GNS3 Project." % __version__
bitness = struct.calcsize("P") * 8
current_year = datetime.date.today().year
self.intro = "GNS3 management console.\nRunning GNS3 version {} on {} ({}-bit) with Python {} Qt {} and PyQt {}.\n" \
"Copyright (c) 2006-{} GNS3 Technologies.\n" \
"Use Help -> GNS3 Doctor to detect common issues." \
"".format(__version__, platform.system(), bitness, platform.python_version(), QtCore.QT_VERSION_STR, QtCore.PYQT_VERSION_STR, current_year)
# Parent class initialization
try:
PyCutExt.__init__(self, None, self.intro, parent=parent)
super().__init__(None, self.intro, parent=parent)
# dynamically get all the available commands so we can color them
methods = inspect.getmembers(self, predicate=inspect.ismethod)
commands = []
for method in methods:
method_name = method[0]
if method_name.startswith("do_"):
commands.append(method_name[3:])
# put our own keywords list
self.colorizer.keywords = self.keywords
#self._Dynagen_Console_init()
self.colorizer.keywords = commands
except Exception as e:
sys.stderr.write(e)
self._handleLogs()
if LocalConfig.instance().experimental():
log.warning("WARNING: Experimental features enable. You can use some unfinished features and lost data.")
for module in MODULES:
instance = module.instance()
instance.notification_signal.connect(self.writeNotification)
self.write_message_signal.connect(self._writeMessageSlot)
# required for Cmd module (do_help etc.)
self.stdout = sys.stdout
self._topology = Topology.instance()
def contextMenuEvent(self, event):
"""
Handles all context menu events.
:param event: QContextMenuEvent instance
"""
menu = self.createStandardContextMenu()
delete_all_action = QtWidgets.QAction("Delete All", menu)
delete_all_action.triggered.connect(self._deleteAllActionSlot)
menu.addAction(delete_all_action)
menu.exec_(event.globalPos());
def _deleteAllActionSlot(self):
"""
Delete all action slot
"""
self.clear()
self.write(self.prompt)
self.lines = []
self._clearLine()
def _writeMessageSlot(self, message, level):
"""
Write a message in the console.
"""
if level == "error":
self.write(message, error=True)
elif level == "warning":
self.write(message, warning=True)
else:
self.write(message)
def _handleLogs(self):
"""
Catch log message and display them
"""
log = logging.getLogger()
log_handler = ConsoleLogHandler()
log_handler._console_view = self
log.addHandler(log_handler)
def isatty(self):
"""
For exception handling purposes
(see exception hook in the program entry point).
"""
return False
def onKeyPress_Tab(self):
"""
Imitate cmd.Cmd.complete(self, text, state) function.
@@ -86,7 +172,7 @@ class ConsoleView(PyCutExt, ConsoleCmd):
if len(self.line) > 0:
cmd, args, _ = self.parseline(line)
if cmd == '':
if cmd is None or cmd == '':
compfunc = self.completedefault
else:
try:
@@ -115,9 +201,9 @@ class ConsoleView(PyCutExt, ConsoleCmd):
self.line = newLine
self.point = len(newLine)
# Else, display possible values
else:
elif self.completion_matches:
self.write("\n")
self.columnize(self.completion_matches)
print(" ".join(self.completion_matches))
# In any case, reprint prompt + line
self.write("\n" + sys.ps1 + str(self.line))
@@ -131,70 +217,64 @@ class ConsoleView(PyCutExt, ConsoleCmd):
"""
text = "Server notification: {}".format(message)
self.write(text, error=True)
self.write("\n")
if details:
self.write(details)
self.write("\n")
text += "\n" + details
self.write_message_signal.emit(text, "info")
def writeError(self, node_id, message):
def writeError(self, base_node_id, message):
"""
Write error messages.
:param node_id: node identifier
:param base_node_id: base node identifier
:param message: error message
"""
node = Topology.instance().getNode(node_id)
node = Topology.instance().getNode(base_node_id)
name = ""
if node and node.name():
name = " {}:".format(node.name())
text = "Error:{name} {message}".format(name=name,
message=message)
self.write(text, error=True)
self.write("\n")
self.write_message_signal.emit(text, "error")
def writeWarning(self, node_id, message):
def writeWarning(self, base_node_id, message):
"""
Write warning messages.
:param node_id: node identifier
:param base_node_id: base node identifier
:param message: warning message
"""
node = Topology.instance().getNode(node_id)
node = Topology.instance().getNode(base_node_id)
name = ""
if node and node.name():
name = " {}:".format(node.name())
text = "Warning:{name} {message}".format(name=name,
message=message)
self.write(text, warning=True)
self.write("\n")
self.write_message_signal.emit(text, "warning")
def writeServerError(self, node_id, code, message):
def writeServerError(self, base_node_id, message):
"""
Write server error messages coming from the server.
:param node_id: node identifier
:param base_node_id: Base node identifier
:param code: error code
:param message: error message
"""
node = Topology.instance().getNode(node_id)
node = Topology.instance().getNode(base_node_id)
server = name = ""
if node and node.name():
name = " {}:".format(node.name())
server = "from {}:{}".format(node.server().host,
node.server().port)
if node:
if node.name():
name = " {}:".format(node.name())
server = "from {}".format(node.compute().name())
text = "Server error [{code}] {server}:{name} {message}".format(code=code,
server=server,
name=name,
message=message)
self.write(text, error=True)
self.write("\n")
text = "Server error {server}:{name} {message}".format(server=server,
name=name,
message=message)
self.write_message_signal.emit(text.strip(), "error")
def _run(self):
"""
@@ -206,13 +286,12 @@ class ConsoleView(PyCutExt, ConsoleCmd):
self.pointer = 0
if len(self.line):
self.history.append(self.line)
try:
self.lines.append(self.line)
source = "\n".join(self.lines)
self.more = self.onecmd(source)
except Exception as e:
print("Unknown command")
#print(str(e))
try:
self.lines.append(self.line)
source = "\n".join(self.lines)
self.more = self.onecmd(source)
except Exception as e:
print("Unknown error: {}".format(e))
self.write(self.prompt)
self.lines = []

499
gns3/controller.py Normal file
View File

@@ -0,0 +1,499 @@
#!/usr/bin/env python
#
# Copyright (C) 2016 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 os
import hashlib
import tempfile
import json
import pathlib
from .qt import QtCore, QtNetwork, QtGui, QtWidgets, QtWebSockets, qpartial, qslot
from .symbol import Symbol
from .local_server_config import LocalServerConfig
from .settings import LOCAL_SERVER_SETTINGS
from gns3.utils import parse_version
import logging
log = logging.getLogger(__name__)
class Controller(QtCore.QObject):
"""
An instance of the server controller.
"""
connected_signal = QtCore.Signal()
disconnected_signal = QtCore.Signal()
connection_failed_signal = QtCore.Signal()
project_list_updated_signal = QtCore.Signal()
def __init__(self):
super().__init__()
self._connected = False
self._connecting = False
self._notification_stream = None
self._version = None
self._cache_directory = tempfile.TemporaryDirectory(suffix="-gns3")
self._http_client = None
self._first_error = True
self._error_dialog = None
self._display_error = True
self._projects = []
self._websocket = QtWebSockets.QWebSocket()
# If we do multiple call in order to download the same symbol we queue them
self._static_asset_download_queue = {}
def host(self):
return self._http_client.host()
def version(self):
return self._version
def isRemote(self):
"""
:returns Boolean: True if the controller is remote
"""
settings = LocalServerConfig.instance().loadSettings("Server", LOCAL_SERVER_SETTINGS)
return not settings["auto_start"]
def connecting(self):
"""
:returns: True if connection is in progress
"""
return self._connecting
def connected(self):
"""
Is the controller connected
"""
return self._connected
def httpClient(self):
"""
:returns: HTTP client to connect to the controller
"""
return self._http_client
def setHttpClient(self, http_client):
"""
:param http_client: Instance of HTTP client to communicate with the server
"""
self._http_client = http_client
if self._http_client:
if self.isRemote():
self._http_client.setMaxTimeDifferenceBetweenQueries(120)
self._http_client.connection_connected_signal.connect(self._httpClientConnectedSlot)
self._http_client.connection_disconnected_signal.connect(self._httpClientDisconnectedSlot)
self._connectingToServer()
def getHttpClient(self):
"""
:return: Instance of HTTP client to communicate with the server
"""
return self._http_client
def setDisplayError(self, val):
"""
Allow error to be visible or not
"""
self._display_error = val
self._first_error = True
def _connectingToServer(self):
"""
Connection process as started
"""
self._connected = False
self._connecting = True
status, json_data = self.httpClient().getSynchronous('GET', '/version', timeout=60)
self._versionGetSlot(json_data, status is None or status >= 300)
def _httpClientDisconnectedSlot(self):
if self._connected:
self._connected = False
self.disconnected_signal.emit()
self._connectingToServer()
self.stopListenNotifications()
def _versionGetSlot(self, result, error=False, **kwargs):
"""
Called after the initial version get
"""
if error:
if self._first_error:
self._connecting = False
self.connection_failed_signal.emit()
if self._display_error:
self._error_dialog = QtWidgets.QMessageBox(self.parent())
self._error_dialog.setWindowModality(QtCore.Qt.ApplicationModal)
self._error_dialog.setWindowTitle("Connection to server")
if result and "message" in result:
self._error_dialog.setText("Error when connecting to the GNS3 server:\n{}".format(result["message"]))
else:
self._error_dialog.setText("Cannot connect to the GNS3 server")
self._error_dialog.setIcon(QtWidgets.QMessageBox.Critical)
self._error_dialog.show()
# Try to connect again in 5 seconds
QtCore.QTimer.singleShot(5000, qpartial(self.get, '/version', self._versionGetSlot, showProgress=self._first_error))
self._first_error = False
else:
self._first_error = True
if self._error_dialog:
self._error_dialog.reject()
self._error_dialog = None
self._version = result.get("version")
self._http_client.connection_connected_signal.emit()
def _httpClientConnectedSlot(self):
if not self._connected:
self._connected = True
self._connecting = False
self.connected_signal.emit()
self.refreshProjectList()
self._startListenNotifications()
def post(self, *args, **kwargs):
return self.createHTTPQuery("POST", *args, **kwargs)
def get(self, *args, **kwargs):
return self.createHTTPQuery("GET", *args, **kwargs)
def put(self, *args, **kwargs):
return self.createHTTPQuery("PUT", *args, **kwargs)
def delete(self, *args, **kwargs):
return self.createHTTPQuery("DELETE", *args, **kwargs)
def getCompute(self, path, compute_id, *args, **kwargs):
"""
API get on a specific compute
"""
compute_id = self.__fix_compute_id(compute_id)
path = "/computes/{}{}".format(compute_id, path)
return self.get(path, *args, **kwargs)
def postCompute(self, path, compute_id, *args, **kwargs):
"""
API post on a specific compute
"""
compute_id = self.__fix_compute_id(compute_id)
path = "/computes/{}{}".format(compute_id, path)
return self.post(path, *args, **kwargs)
def __fix_compute_id(self, compute_id):
"""
Support for remote server <= 1.5
This fix should be not require after the 2.1
when all the templates will be managed on server
"""
#FIXME: remove this?
if compute_id.startswith("http:") or compute_id.startswith("https:"):
from .compute_manager import ComputeManager
try:
return ComputeManager.instance().getCompute(compute_id).id()
except KeyError:
return compute_id
return compute_id
def getEndpoint(self, path, compute_id, *args, **kwargs):
"""
API post on a specific compute
"""
compute_id = self.__fix_compute_id(compute_id)
path = "/computes/endpoint/{}{}".format(compute_id, path)
return self.get(path, *args, **kwargs)
def putCompute(self, path, compute_id, *args, **kwargs):
"""
API put on a specific compute
"""
compute_id = self.__fix_compute_id(compute_id)
path = "/computes/{}{}".format(compute_id, path)
return self.put(path, *args, **kwargs)
def createHTTPQuery(self, method, path, *args, **kwargs):
"""
Forward the query to the HTTP client or controller depending of the path
"""
if self._http_client:
return self._http_client.createHTTPQuery(method, path, *args, **kwargs)
@staticmethod
def instance():
"""
Singleton to return only on instance of Controller.
:returns: instance of Controller
"""
if not hasattr(Controller, '_instance') or Controller._instance is None:
Controller._instance = Controller()
return Controller._instance
def getStatic(self, url, callback, fallback=None):
"""
Get a URL from the /static on controller and cache it on disk
:param url: URL without the protocol and host part
:param callback: Callback to call when file is ready
:param fallback: Fallback url in case of error
"""
if not self._http_client:
return
path = self.getStaticCachedPath(url)
if os.path.exists(path):
callback(path)
elif path in self._static_asset_download_queue:
self._static_asset_download_queue[path].append((callback, fallback, ))
else:
self._static_asset_download_queue[path] = [(callback, fallback, )]
self._http_client.createHTTPQuery("GET", url, qpartial(self._getStaticCallback, url, path))
def _getStaticCallback(self, url, path, result, error=False, raw_body=None, **kwargs):
if path not in self._static_asset_download_queue:
return
if error:
fallback_used = False
for callback, fallback in self._static_asset_download_queue[path]:
if fallback:
self.getStatic(fallback, callback)
fallback_used = True
if fallback_used:
log.debug("Error while downloading file: {}".format(url))
del self._static_asset_download_queue[path]
return
try:
with open(path, "wb+") as f:
f.write(raw_body)
except OSError as e:
log.error("Can't write to {}: {}".format(path, str(e)))
return
log.debug("File stored {} for {}".format(path, url))
for callback, fallback in self._static_asset_download_queue[path]:
callback(path)
del self._static_asset_download_queue[path]
def getStaticCachedPath(self, url):
"""
Returns static cached (hashed) path
:param url:
"""
m = hashlib.md5()
m.update(url.encode())
if ".svg" in url:
extension = ".svg"
else:
extension = ".png"
path = os.path.join(self._cache_directory.name, m.hexdigest() + extension)
return path
def clearStaticCache(self):
"""
Clear the cache directory.
"""
for filename in os.listdir(self._cache_directory.name):
if filename.endswith(".svg") or filename.endswith(".png"):
try:
os.remove(os.path.join(self._cache_directory.name, filename))
except OSError as e:
log.debug("Error deleting cached symbol '{}':{}".format(filename, e))
continue
def getSymbolIcon(self, symbol_id, callback, fallback=None):
"""
Get a QIcon for a symbol from the controller
:param symbol_id: Symbol id
:param callback: Callback to call when file is ready
:param fallback: Fallback symbol if not found
"""
if symbol_id is None:
self.getStatic(Symbol(fallback).url(), qpartial(self._getIconCallback, callback))
else:
if fallback:
fallback = Symbol(fallback).url()
self.getStatic(Symbol(symbol_id).url(), qpartial(self._getIconCallback, callback), fallback=fallback)
def _getIconCallback(self, callback, path):
pixmap = QtGui.QPixmap(path)
if pixmap.isNull():
log.debug("Invalid symbol {}".format(path))
path = ":/icons/cancel.svg"
icon = QtGui.QIcon()
icon.addFile(path)
callback(icon)
def uploadSymbol(self, symbol_id, path):
self.post("/symbols/" + symbol_id + "/raw",
qpartial(self._finishSymbolUpload, path),
body=pathlib.Path(path), progressText="Uploading {}".format(symbol_id), timeout=None)
def _finishSymbolUpload(self, path, result, error=False, **kwargs):
if error:
log.error("Error while uploading symbol: {}: {}".format(path, result.get("message", "unknown")))
return
# Refresh the templates list
from .template_manager import TemplateManager
TemplateManager.instance().templates_changed_signal.emit()
def getSymbols(self, callback):
self.get('/symbols', callback=callback)
def deleteProject(self, project_id, callback=None):
Controller.instance().delete("/projects/{}".format(project_id), qpartial(self._deleteProjectCallback, callback=callback, project_id=project_id))
def _deleteProjectCallback(self, result, error=False, project_id=None, callback=None, **kwargs):
if error:
log.error("Error while deleting project: {}".format(result["message"]))
else:
self.refreshProjectList()
self._projects = [p for p in self._projects if p["project_id"] != project_id]
if callback:
callback(result, error=error, **kwargs)
@qslot
def refreshProjectList(self, *args):
self.get("/projects", self._projectListCallback)
def _projectListCallback(self, result, error=False, **kwargs):
if not error:
self._projects = result
self.project_list_updated_signal.emit()
def projects(self):
return self._projects
def _startListenNotifications(self):
if not self.connected():
return
# Due to bug in Qt on some version we need a dedicated network manager
self._notification_network_manager = QtNetwork.QNetworkAccessManager()
self._notification_stream = None
# Qt websocket before Qt 5.6 doesn't support auth
if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.6.0") or parse_version(QtCore.PYQT_VERSION_STR) < parse_version("5.6.0"):
self._notification_stream = Controller.instance().createHTTPQuery("GET", "/notifications", self._endListenNotificationCallback,
downloadProgressCallback=self._event_received,
networkManager=self._notification_network_manager,
timeout=None,
showProgress=False,
ignoreErrors=True)
else:
self._notification_stream = self._http_client.connectWebSocket(self._websocket, "/notifications/ws")
self._notification_stream.textMessageReceived.connect(self._websocket_event_received)
self._notification_stream.error.connect(self._websocket_error)
self._notification_stream.sslErrors.connect(self._sslErrorsSlot)
def stopListenNotifications(self):
if self._notification_stream:
log.debug("Stop listening for notifications from controller")
stream = self._notification_stream
self._notification_stream = None
stream.abort()
self._notification_network_manager = None
def _endListenNotificationCallback(self, result, error=False, **kwargs):
"""
If notification stream disconnect we reconnect to it
"""
if self._notification_stream:
self._notification_stream = None
self._startListenNotifications()
@qslot
def _websocket_error(self, error):
if self._notification_stream:
log.error("Websocket controller notification stream error: {}".format(self._notification_stream.errorString()))
self._notification_stream = None
self._startListenNotifications()
@qslot
def _sslErrorsSlot(self, ssl_errors):
self._http_client.handleSslError(self._notification_stream, ssl_errors)
@qslot
def _websocket_event_received(self, event):
try:
self._event_received(json.loads(event))
except ValueError as e:
log.error("Invalid event received: {}".format(e))
def _event_received(self, result, *args, **kwargs):
# Log only relevant events
if result["action"] not in ("ping", "compute.updated"):
log.debug("Event received from controller stream: {}".format(result))
if result["action"] == "template.created" or result["action"] == "template.updated":
from gns3.template_manager import TemplateManager
TemplateManager.instance().templateDataReceivedCallback(result["event"])
elif result["action"] == "template.deleted":
from gns3.template_manager import TemplateManager
TemplateManager.instance().deleteTemplateCallback(result["event"])
elif result["action"] == "compute.created" or result["action"] == "compute.updated":
from .compute_manager import ComputeManager
ComputeManager.instance().computeDataReceivedCallback(result["event"])
elif result["action"] == "project.closed":
from .topology import Topology
project = Topology.instance().project()
if project and project.id() == result["event"]["project_id"]:
Topology.instance().setProject(None)
elif result["action"] == "project.updated":
from .topology import Topology
project = Topology.instance().project()
if project and project.id() == result["event"]["project_id"]:
project.projectUpdatedCallback(result["event"])
elif result["action"] == "log.error" and result["event"].get("message"):
log.error(result["event"].get("message"))
elif result["action"] == "log.warning" and result["event"].get("message"):
log.warning(result["event"].get("message"))
elif result["action"] == "log.info" and result["event"].get("message"):
log.info(result["event"].get("message"), extra={"show": True})
elif result["action"] == "ping":
pass

163
gns3/crash_report.py Normal file
View File

@@ -0,0 +1,163 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
try:
import sentry_sdk
from sentry_sdk.integrations.logging import LoggingIntegration
SENTRY_SDK_AVAILABLE = True
except ImportError:
# Sentry SDK is not installed with deb package in order to simplify packaging
SENTRY_SDK_AVAILABLE = False
import sys
import os
import platform
import struct
import distro
from .version import __version__, __version_info__
import logging
log = logging.getLogger(__name__)
# Dev build
if __version_info__[3] != 0:
import faulthandler
# Display a traceback in case of segfault crash. Usefull when frozen
# Not enabled by default for security reason
log.debug("Enable catching segfault")
faulthandler.enable()
class CrashReport:
"""
Report crash to a third party service
"""
DSN = "https://235ecbc961abe34327a4a397d8ce427a@o19455.ingest.us.sentry.io/38506"
_instance = None
def __init__(self):
# We don't want sentry making noise if an error is caught when we don't have internet
sentry_errors = logging.getLogger('sentry.errors')
sentry_errors.disabled = True
sentry_uncaught = logging.getLogger('sentry.errors.uncaught')
sentry_uncaught.disabled = True
self._sentry_initialized = False
if SENTRY_SDK_AVAILABLE:
# Don't send log records as events.
sentry_logging = LoggingIntegration(level=logging.INFO, event_level=None)
try:
sentry_sdk.init(dsn=CrashReport.DSN,
release=__version__,
default_integrations=False,
integrations=[sentry_logging])
except Exception as e:
log.error("Crash report could not be sent: {}".format(e))
return
tags = {
"os:name": platform.system(),
"os:release": platform.release(),
"os:win_32": " ".join(platform.win32_ver()),
"os:mac": "{} {}".format(platform.mac_ver()[0], platform.mac_ver()[2]),
"os:linux": distro.name(pretty=True),
}
self._add_qt_information(tags)
with sentry_sdk.configure_scope() as scope:
for key, value in tags.items():
scope.set_tag(key, value)
extra_context = {
"python:version": "{}.{}.{}".format(sys.version_info[0],
sys.version_info[1],
sys.version_info[2]),
"python:bit": struct.calcsize("P") * 8,
"python:encoding": sys.getdefaultencoding(),
"python:frozen": "{}".format(hasattr(sys, "frozen"))
}
# extra controller and compute information
from .controller import Controller
from .compute_manager import ComputeManager
extra_context["controller:version"] = Controller.instance().version()
extra_context["controller:host"] = Controller.instance().host()
extra_context["controller:connected"] = Controller.instance().connected()
for index, compute in enumerate(ComputeManager.instance().computes()):
extra_context["compute{}:id".format(index)] = compute.id()
extra_context["compute{}:name".format(index)] = compute.name(),
extra_context["compute{}:host".format(index)] = compute.host(),
extra_context["compute{}:connected".format(index)] = compute.connected()
extra_context["compute{}:platform".format(index)] = compute.capabilities().get("platform")
extra_context["compute{}:version".format(index)] = compute.capabilities().get("version")
with sentry_sdk.configure_scope() as scope:
for key, value in extra_context.items():
scope.set_extra(key, value)
def captureException(self, exception, value, tb):
from .local_server import LocalServer
from .local_config import LocalConfig
local_server = LocalServer.instance().localServerSettings()
if local_server["report_errors"]:
if not SENTRY_SDK_AVAILABLE:
log.warning("Cannot capture exception: Sentry SDK is not available")
return
if os.path.exists(LocalConfig.instance().runAsRootPath()):
log.warning("User is running application as root. Crash reports disabled.")
return
if not hasattr(sys, "frozen") and os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", ".git")):
log.warning(".git directory detected, crash reporting is turned off for developers.")
return
try:
error = (exception, value, tb)
sentry_sdk.capture_exception(error=error)
log.info("Crash report sent with event ID: {}".format(sentry_sdk.last_event_id()))
except Exception as e:
log.warning("Can't send crash report to Sentry: {}".format(e))
def _add_qt_information(self, tags):
try:
from .qt import QtCore
from .qt import sip
except ImportError:
return tags
tags["pyqt:version"] = QtCore.PYQT_VERSION_STR
tags["qt:version"] = QtCore.QT_VERSION_STR
tags["sip:version"] = sip.SIP_VERSION_STR
return tags
@classmethod
def instance(cls):
if cls._instance is None:
cls._instance = CrashReport()
return cls._instance

View File

@@ -15,19 +15,20 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .qt import QtGui
from .version import __version__
from .ui.about_dialog_ui import Ui_AboutDialog
from ..qt import QtWidgets
from ..version import __version__
from ..ui.about_dialog_ui import Ui_AboutDialog
class AboutDialog(QtGui.QDialog, Ui_AboutDialog):
class AboutDialog(QtWidgets.QDialog, Ui_AboutDialog):
"""
About dialog.
"""
def __init__(self, parent):
QtGui.QDialog.__init__(self, parent)
super().__init__(parent)
self.setupUi(self)
# dynamically add the current version number

View File

@@ -0,0 +1,818 @@
#!/usr/bin/env python
#
# 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 os
from ..qt import sip
import shutil
from ..qt import QtWidgets, QtCore, QtGui, qpartial, qslot
from ..ui.appliance_wizard_ui import Ui_ApplianceWizard
from ..template_manager import TemplateManager
from ..template import Template
from ..modules import Qemu
from ..registry.appliance import Appliance, ApplianceError
from ..registry.registry import Registry
from ..registry.config import Config
from ..registry.appliance_to_template import ApplianceToTemplate
from ..registry.image import Image
from ..utils import human_filesize
from ..utils.wait_for_lambda_worker import WaitForLambdaWorker
from ..utils.progress_dialog import ProgressDialog
from ..compute_manager import ComputeManager
from ..controller import Controller
from ..local_config import LocalConfig
from ..image_upload_manager import ImageUploadManager
from ..image_manager import ImageManager
import logging
log = logging.getLogger(__name__)
class ApplianceWizard(QtWidgets.QWizard, Ui_ApplianceWizard):
images_changed_signal = QtCore.Signal()
versions_changed_signal = QtCore.Signal()
def __init__(self, parent, path):
super().__init__(parent)
self.setupUi(self)
self._refreshing = False
self._server_check = False
self._template_created = False
self._path = path
# count how many images are being uploaded
self._image_uploading_count = 0
# symbols loaded from controller
self._symbols = []
# connect slots
self.images_changed_signal.connect(self._refreshVersions)
self.versions_changed_signal.connect(self._versionRefreshedSlot)
self.uiRefreshPushButton.clicked.connect(self.images_changed_signal.emit)
self.uiDownloadPushButton.clicked.connect(self._downloadPushButtonClickedSlot)
self.uiImportPushButton.clicked.connect(self._importPushButtonClickedSlot)
self.uiApplianceVersionTreeWidget.currentItemChanged.connect(self._applianceVersionCurrentItemChangedSlot)
self.uiCreateVersionPushButton.clicked.connect(self._createVersionPushButtonClickedSlot)
self.allowCustomFiles.clicked.connect(self._allowCustomFilesChangedSlot)
# directories where to search for images
images_directories = list()
for emulator in ("QEMU", "IOU", "DYNAMIPS"):
emulator_images_dir = ImageManager.instance().getDirectoryForType(emulator)
if os.path.exists(emulator_images_dir):
images_directories.append(emulator_images_dir)
images_directories.append(os.path.dirname(self._path))
download_directory = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DownloadLocation)
if download_directory != "" and download_directory != os.path.dirname(self._path):
images_directories.append(download_directory)
# registry to search for images
self._registry = Registry(images_directories)
self._registry.image_list_changed_signal.connect(self.images_changed_signal.emit)
# appliance object
self._appliance = Appliance(self._registry, self._path)
self.setWindowTitle("Install {} appliance".format(self._appliance["name"]))
# add a custom button to show appliance information
if self._appliance["registry_version"] < 8:
# FIXME: show appliance info for v8
self.setButtonText(QtWidgets.QWizard.CustomButton1, "&Appliance info")
self.setOption(QtWidgets.QWizard.HaveCustomButton1, True)
self.customButtonClicked.connect(self._showApplianceInfoSlot)
# customize the server selection
self.uiRemoteRadioButton.toggled.connect(self._remoteServerToggledSlot)
if hasattr(self, "uiVMRadioButton"):
self.uiVMRadioButton.toggled.connect(self._vmToggledSlot)
self.uiLocalRadioButton.toggled.connect(self._localToggledSlot)
if Controller.instance().isRemote():
self.uiLocalRadioButton.setText("Install the appliance on the main server")
else:
if not path.endswith('.builtin.gns3a'):
destination = None
try:
destination = Config().appliances_dir
except OSError as e:
QtWidgets.QMessageBox.critical(self.parent(), "Add appliance", "Could not find configuration file: {}".format(e))
except ValueError as e:
QtWidgets.QMessageBox.critical(self.parent(), "Add appliance", "Invalid configuration file: {}".format(e))
if destination:
try:
os.makedirs(destination, exist_ok=True)
destination = os.path.join(destination, os.path.basename(path))
shutil.copy(path, destination)
except OSError as e:
QtWidgets.QMessageBox.warning(self.parent(), "Cannot copy {} to {}".format(path, destination), str(e))
self.uiServerWizardPage.isComplete = self._uiServerWizardPage_isComplete
def initializePage(self, page_id):
"""
Initialize wizard pages.
:param page_id: page identifier
"""
super().initializePage(page_id)
# add symbol
if self._appliance["category"] == "guest":
symbol = ":/symbols/computer.svg"
else:
symbol = ":/symbols/{}.svg".format(self._appliance["category"])
self.page(page_id).setPixmap(QtWidgets.QWizard.LogoPixmap, QtGui.QPixmap(symbol))
if self.page(page_id) == self.uiServerWizardPage:
Controller.instance().getSymbols(self._getSymbolsCallback)
template_type = self._appliance.template_type()
if not template_type:
raise ApplianceError("No template type found for appliance {}".format(self._appliance["name"]))
is_mac = ComputeManager.instance().localPlatform().startswith("darwin")
is_win = ComputeManager.instance().localPlatform().startswith("win")
self.uiRemoteServersComboBox.clear()
if len(ComputeManager.instance().remoteComputes()) == 0:
self.uiRemoteRadioButton.setEnabled(False)
else:
self.uiRemoteRadioButton.setEnabled(True)
for compute in ComputeManager.instance().remoteComputes():
self.uiRemoteServersComboBox.addItem(compute.name(), compute)
if not ComputeManager.instance().vmCompute():
self.uiVMRadioButton.setEnabled(False)
if ComputeManager.instance().localPlatform() is None:
self.uiLocalRadioButton.setEnabled(False)
elif is_mac or is_win:
if template_type == "qemu":
# disallow usage of the local server because Qemu has issues on OSX and Windows
if not LocalConfig.instance().experimental():
self.uiLocalRadioButton.setEnabled(False)
elif template_type != "dynamips":
self.uiLocalRadioButton.setEnabled(False)
if ComputeManager.instance().vmCompute():
self.uiVMRadioButton.setChecked(True)
elif ComputeManager.instance().localCompute() and self.uiLocalRadioButton.isEnabled():
self.uiLocalRadioButton.setChecked(True)
elif self.uiRemoteRadioButton.isEnabled():
self.uiRemoteRadioButton.setChecked(True)
else:
self.uiRemoteRadioButton.setChecked(False)
if is_mac or is_win:
if not self.uiRemoteRadioButton.isEnabled() and not self.uiVMRadioButton.isEnabled() and not self.uiLocalRadioButton.isEnabled():
QtWidgets.QMessageBox.warning(self, "GNS3 VM", "The GNS3 VM is not available, please configure the GNS3 VM before adding a new appliance.")
elif self.page(page_id) == self.uiFilesWizardPage:
if Controller.instance().isRemote() or self._compute_id != "local":
self._registry.getRemoteImageList(self._appliance.template_type(), self._compute_id)
else:
self.images_changed_signal.emit()
elif self.page(page_id) == self.uiQemuWizardPage:
if self._appliance.template_properties().get('kvm', 'require') == 'require':
self._server_check = False
Qemu.instance().getQemuCapabilitiesFromServer(self._compute_id, qpartial(self._qemuServerCapabilitiesCallback))
else:
self._server_check = True
if self._appliance["registry_version"] >= 8:
qemu_platform = self._appliance.template_properties()["platform"]
else:
qemu_platform = self._appliance.template_properties()["arch"]
Qemu.instance().getQemuBinariesFromServer(self._compute_id, qpartial(self._getQemuBinariesFromServerCallback), [qemu_platform])
elif self.page(page_id) == self.uiInstructionsPage:
installation_instructions = self._appliance.get("installation_instructions", "No installation instructions available")
self.uiInstructionsTextEdit.setText(installation_instructions.strip())
elif self.page(page_id) == self.uiUsageWizardPage:
# TODO: allow taking these info fields at the version level in v8
category = self._appliance["category"].replace("_", " ")
usage = self._appliance.get("usage", "No usage information available")
if self._appliance["registry_version"] >= 8:
default_username = self._appliance.get("default_username")
default_password = self._appliance.get("default_password")
if default_username and default_password:
usage += "\n\nDefault username: {}\nDefault password: {}".format(default_username, default_password)
usage_info = """
The template will be available in the {} category.
Usage: {}
""".format(category, usage)
self.uiUsageTextEdit.setText(usage_info.strip())
def _qemuServerCapabilitiesCallback(self, result, error=None, *args, **kwargs):
"""
Check if the server supports KVM or not
"""
if self._appliance["registry_version"] >= 8:
qemu_platform = self._appliance.template_properties()["platform"]
else:
qemu_platform = self._appliance.template_properties()["arch"]
if error is None and "kvm" in result and qemu_platform in result["kvm"]:
self._server_check = True
else:
if error:
msg = result["message"]
else:
msg = "The selected server does not support KVM. A Linux server or the GNS3 VM running in VMware is required."
QtWidgets.QMessageBox.critical(self, "KVM support", msg)
self._server_check = False
def _uiServerWizardPage_isComplete(self):
return self.uiRemoteRadioButton.isEnabled() or self.uiVMRadioButton.isEnabled() or self.uiLocalRadioButton.isEnabled()
def _imageUploadedCallback(self, result, error=False, context=None, **kwargs):
if context is None:
context = {}
image_path = context.get("image_path", "unknown")
if error:
log.error("Error while uploading image '{}': {}".format(image_path, result["message"]))
else:
log.info("Image '{}' has been successfully uploaded".format(image_path))
self._registry.getRemoteImageList(self._appliance.template_type(), self._compute_id)
def _showApplianceInfoSlot(self):
"""
Shows appliance information.
"""
info = (("Product", "product_name"),
("Vendor", "vendor_name"),
("Availability", "availability"),
("Status", "status"),
("Maintainer", "maintainer"))
if "qemu" in self._appliance:
qemu_info = (("vCPUs", "qemu/cpus"),
("RAM", "qemu/ram"),
("Adapters", "qemu/adapters"),
("Adapter type", "qemu/adapter_type"),
("Console type", "qemu/console_type"),
("Architecture", "qemu/arch"),
("Console type", "qemu/console_type"),
("KVM", "qemu/kvm"))
info = info + qemu_info
elif "docker" in self._appliance:
docker_info = (("Image", "docker/image"),
("Adapters", "docker/adapters"),
("Console type", "docker/console_type"))
info = info + docker_info
elif "iou" in self._appliance:
iou_info = (("RAM", "iou/ram"),
("NVRAM", "iou/nvram"),
("Ethernet adapters", "iou/ethernet_adapters"),
("Serial adapters", "iou/serial_adapters"))
info = info + iou_info
elif "dynamips" in self._appliance:
dynamips_info = (("Platform", "dynamips/platform"),
("Chassis", "dynamips/chassis"),
("Midplane", "dynamips/midplane"),
("NPE", "dynamips/npe"),
("RAM", "dynamips/ram"),
("NVRAM", "dynamips/nvram"),
("slot0", "dynamips/slot0"),
("slot1", "dynamips/slot1"),
("slot2", "dynamips/slot2"),
("slot3", "dynamips/slot3"),
("slot4", "dynamips/slot4"),
("slot5", "dynamips/slot5"),
("slot6", "dynamips/slot6"),
("wic0", "dynamips/wic0"),
("wic1", "dynamips/wic1"),
("wic2", "dynamips/wic2"))
info = info + dynamips_info
text_info = ""
for (name, key) in info:
if "/" in key:
key, subkey = key.split("/")
value = self._appliance.get(key, {}).get(subkey, None)
else:
value = self._appliance.get(key, None)
if value is None:
continue
text_info += "<span style='font-weight:bold;'>{}</span>: {}<br>".format(name, value)
msgbox = QtWidgets.QMessageBox(self)
msgbox.setWindowTitle("Appliance information")
msgbox.setStyleSheet("QLabel{min-width: 600px;}") # TODO: resize details box QTextEdit{min-height: 500px;}
msgbox.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
msgbox.setText(text_info)
msgbox.setDetailedText(self._appliance["description"])
msgbox.exec_()
@qslot
def _refreshVersions(self, *args):
"""
Refresh the list of files for different versions of the appliance
"""
if self._refreshing:
return
self._refreshing = True
self.uiFilesWizardPage.setSubTitle("Please select one version of " + self._appliance["product_name"] + " and import the required files. Files are searched in your downloads and GNS3 images directories by default")
worker = WaitForLambdaWorker(lambda: self._refreshDialogWorker())
progress_dialog = ProgressDialog(worker, "Add appliance", "Scanning directories for files...", None, busy=True, parent=self)
progress_dialog.show()
@qslot
def _versionRefreshedSlot(self, *args):
"""
Called when we finish to scan the disk for new versions
"""
if self._refreshing or self.currentPage() != self.uiFilesWizardPage:
return
self._refreshing = True
self.uiApplianceVersionTreeWidget.clear()
for version in self._appliance["versions"]:
top = QtWidgets.QTreeWidgetItem(self.uiApplianceVersionTreeWidget, ["{} version {}".format(self._appliance["product_name"], version["name"])])
size = 0
status = "Ready to install"
for image in version["images"].values():
if image["status"] == "Missing":
status = "Missing files"
size += image.get("filesize", 0)
image_widget = QtWidgets.QTreeWidgetItem([image["filename"],
human_filesize(image.get("filesize", 0)),
image["status"]])
if image["status"] == "Missing":
image_widget.setForeground(2, QtGui.QBrush(QtGui.QColor("red")))
else:
image_widget.setForeground(2, QtGui.QBrush(QtGui.QColor("green")))
image_widget.setToolTip(2, image["path"])
# Associated data stored are col 0: version, col 1: image
image_widget.setData(0, QtCore.Qt.UserRole, version)
image_widget.setData(1, QtCore.Qt.UserRole, image)
image_widget.setData(2, QtCore.Qt.UserRole, self._appliance)
top.addChild(image_widget)
font = top.font(0)
font.setBold(True)
top.setFont(0, font)
expand = True
if status == "Missing files":
top.setForeground(2, QtGui.QBrush(QtGui.QColor("red")))
else:
expand = False
top.setForeground(2, QtGui.QBrush(QtGui.QColor("green")))
top.setData(1, QtCore.Qt.DisplayRole, human_filesize(size))
top.setData(2, QtCore.Qt.DisplayRole, status)
top.setData(0, QtCore.Qt.UserRole, version)
top.setData(2, QtCore.Qt.UserRole, self._appliance)
self.uiApplianceVersionTreeWidget.addTopLevelItem(top)
if expand:
top.setExpanded(True)
if len(self._appliance["versions"]) > 0:
for column in range(self.uiApplianceVersionTreeWidget.columnCount()):
self.uiApplianceVersionTreeWidget.resizeColumnToContents(column)
self._refreshing = False
def _getSymbolsCallback(self, result, error=False, **kwargs):
"""
Callback to retrieve the appliance symbols.
"""
if error:
log.warning("Cannot load symbols from controller")
else:
self._symbols = result
def _refreshDialogWorker(self):
"""
Scan local directory in order to find images on the disk
"""
# Docker do not have versions
if "versions" not in self._appliance:
return
for version in self._appliance["versions"]:
for image in version["images"].values():
img = self._registry.search_image_file(self._appliance.template_type(),
image["filename"],
image.get("md5sum"),
image.get("filesize"),
strict_md5_check=not self.allowCustomFiles.isChecked())
if img:
if img.location == "local":
image["status"] = "Found locally"
else:
compute = ComputeManager.instance().getCompute(self._compute_id)
image["status"] = "Found on {}".format(compute.name())
image["md5sum"] = img.md5sum
image["filesize"] = img.filesize
image["path"] = img.path
else:
image["status"] = "Missing"
self._refreshing = False
self.versions_changed_signal.emit()
@qslot
def _applianceVersionCurrentItemChangedSlot(self, current, previous):
"""
Called when user select a different item in the list of appliance files
"""
self.uiDownloadPushButton.hide()
self.uiImportPushButton.hide()
if current is None or sip.isdeleted(current):
return
image = current.data(1, QtCore.Qt.UserRole)
if image is not None:
if "direct_download_url" in image or "download_url" in image:
self.uiDownloadPushButton.show()
self.uiImportPushButton.show()
@qslot
def _downloadPushButtonClickedSlot(self, *args):
"""
Called when user wants to download an appliance image.
The file should be selected first.
"""
if self._refreshing:
return False
current = self.uiApplianceVersionTreeWidget.currentItem()
if current is None or sip.isdeleted(current):
return
data = current.data(1, QtCore.Qt.UserRole)
if data is not None:
if "direct_download_url" in data:
QtGui.QDesktopServices.openUrl(QtCore.QUrl(data["direct_download_url"]))
if "compression" in data:
QtWidgets.QMessageBox.warning(self, "Add appliance", "The file is compressed with '{}', it must be uncompressed first".format(data["compression"]))
else:
QtWidgets.QMessageBox.warning(self, "Add appliance", "Download will redirect you where the required file can be downloaded, you may have to be registered with the vendor in order to download the file.")
QtGui.QDesktopServices.openUrl(QtCore.QUrl(data["download_url"]))
@qslot
def _createVersionPushButtonClickedSlot(self, *args):
"""
Allow user to create a new version of an appliance
"""
current = self.uiApplianceVersionTreeWidget.currentItem()
if current is None:
QtWidgets.QMessageBox.critical(self.parent(), "Base version", "Please select a base version")
return
base_version = current.data(0, QtCore.Qt.UserRole)
new_version_name, ok = QtWidgets.QInputDialog.getText(self, "Creating a new version", "Create a new version for this appliance.\nPlease share your experience on the GNS3 community if this version works.\n\nVersion name:", QtWidgets.QLineEdit.Normal, base_version.get("name"))
if ok:
new_version = {"name": new_version_name}
new_version["images"] = {}
for disk_type in base_version["images"]:
base_filename = base_version["images"][disk_type]["filename"]
filename, ok = QtWidgets.QInputDialog.getText(self, "Image", "Disk image filename for {}".format(disk_type), QtWidgets.QLineEdit.Normal, base_filename)
if not ok:
filename = base_filename
new_version["images"][disk_type] = {"filename": filename, "version": new_version_name}
try:
self._appliance.create_new_version(new_version)
except ApplianceError as e:
QtWidgets.QMessageBox.critical(self.parent(), "Create new version", str(e))
return
self.images_changed_signal.emit()
@qslot
def _importPushButtonClickedSlot(self, *args):
"""
Called when user wants to import an appliance images.
The file should be selected first.
"""
if self._refreshing:
return False
current = self.uiApplianceVersionTreeWidget.currentItem()
if not current:
return
disk = current.data(1, QtCore.Qt.UserRole)
path, _ = QtWidgets.QFileDialog.getOpenFileName()
if len(path) == 0:
return
image = Image(self._appliance.template_type(), path, filename=disk["filename"])
try:
if "md5sum" in disk and image.md5sum != disk["md5sum"]:
reply = QtWidgets.QMessageBox.question(self, "Add appliance",
"This is not the correct file. The MD5 sum is {} and should be {}.\nDo you want to accept it at your own risks?".format(image.md5sum, disk["md5sum"]),
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.No:
return
except OSError as e:
QtWidgets.QMessageBox.warning(self.parent(), "Add appliance", "Can't access to the image file {}: {}.".format(path, str(e)))
return
image_upload_manger = ImageUploadManager(image, Controller.instance(), self._compute_id, self._imageUploadedCallback, LocalConfig.instance().directFileUpload())
image_upload_manger.upload()
def _getQemuBinariesFromServerCallback(self, result, error=False, **kwargs):
"""
Callback for getQemuBinariesFromServer.
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
QtWidgets.QMessageBox.critical(self, "Qemu binaries", "{}".format(result["message"]))
else:
self.uiQemuListComboBox.clear()
for qemu in result:
if qemu["version"]:
self.uiQemuListComboBox.addItem("{path} (v{version})".format(path=qemu["path"], version=qemu["version"]), qemu["path"])
else:
self.uiQemuListComboBox.addItem("{path}".format(path=qemu["path"]), qemu["path"])
if self.uiQemuListComboBox.count() == 1:
self.next()
else:
if self._appliance["registry_version"] >= 8:
qemu_platform = self._appliance.template_properties()["platform"]
else:
qemu_platform = self._appliance.template_properties()["arch"]
i = self.uiQemuListComboBox.findData(qemu_platform, flags=QtCore.Qt.MatchEndsWith)
if i != -1:
self.uiQemuListComboBox.setCurrentIndex(i)
def _install(self, version):
"""
Install the appliance in GNS3
:params version: appliance version name
"""
if version is None:
appliance_configuration = self._appliance.copy()
if self._appliance.template_type() != "docker":
# only Docker do not have versions
return False
else:
try:
appliance_configuration = self._appliance.search_images_for_version(version)
except ApplianceError as e:
QtWidgets.QMessageBox.critical(self.parent(), "Add appliance", str(e))
return False
template_manager = TemplateManager().instance()
while len(appliance_configuration["name"]) == 0 or not template_manager.is_name_available(appliance_configuration["name"]):
QtWidgets.QMessageBox.warning(self.parent(), "Add template", "The name \"{}\" is already used by another template".format(appliance_configuration["name"]))
appliance_configuration["name"], ok = QtWidgets.QInputDialog.getText(self.parent(), "Add template", "New name:", QtWidgets.QLineEdit.Normal, appliance_configuration["name"])
if not ok:
return False
appliance_configuration["name"] = appliance_configuration["name"].strip()
if self._appliance["registry_version"] >= 8:
if "settings" in appliance_configuration:
for settings in appliance_configuration["settings"]:
if settings["template_type"] == "qemu":
settings["template_properties"]["path"] = self.uiQemuListComboBox.currentData()
elif "qemu" in appliance_configuration:
appliance_configuration["qemu"]["path"] = self.uiQemuListComboBox.currentData()
new_template = ApplianceToTemplate().new_template(appliance_configuration, self._compute_id, version, self._symbols, parent=self)
TemplateManager.instance().createTemplate(Template(new_template), callback=self._templateCreatedCallback)
return False
#worker = WaitForLambdaWorker(lambda: self._create_template(appliance_configuration, self._compute_id), allowed_exceptions=[ConfigException, OSError])
#progress_dialog = ProgressDialog(worker, "Add template", "Installing a new template...", None, busy=True, parent=self)
#progress_dialog.show()
#if progress_dialog.exec_():
# QtWidgets.QMessageBox.information(self.parent(), "Add template", "{} template has been installed!".format(appliance_configuration["name"]))
# return True
#return False
# worker = WaitForLambdaWorker(lambda: config.save(), allowed_exceptions=[ConfigException, OSError])
# progress_dialog = ProgressDialog(worker, "Add appliance", "Install the appliance...", None, busy=True, parent=self)
# progress_dialog.show()
# if progress_dialog.exec_():
# QtWidgets.QMessageBox.information(self.parent(), "Add appliance", "{} installed!".format(appliance_configuration["name"]))
# return True
def _templateCreatedCallback(self, result, error=False, **kwargs):
if error is True:
QtWidgets.QMessageBox.critical(self.parent(), "Add template", "The template cannot be created: {}".format(result.get("message", "unknown")))
return
QtWidgets.QMessageBox.information(self.parent(), "Add template", "The appliance has been installed and a template named '{}' has been successfully created!".format(result["name"]))
self._template_created = True
self.done(True)
def _uploadImages(self, name, version):
"""
Upload an image the compute.
"""
try:
appliance_configuration = self._appliance.search_images_for_version(version)
except ApplianceError as e:
QtWidgets.QMessageBox.critical(self, "Appliance","Cannot install {} version {}: {}".format(name, version, e))
return
for image in appliance_configuration["images"]:
if image["location"] == "local":
if not Controller.instance().isRemote() and self._compute_id == "local" and image["path"].startswith(ImageManager.instance().getDirectory()):
log.debug("{} is already on the local server".format(image["path"]))
return
image = Image(self._appliance.template_type(), image["path"], filename=image["filename"])
image_upload_manager = ImageUploadManager(image, Controller.instance(), self._compute_id, self._applianceImageUploadedCallback, LocalConfig.instance().directFileUpload())
image_upload_manager.upload()
self._image_uploading_count += 1
def _applianceImageUploadedCallback(self, result, error=False, context=None, **kwargs):
if context is None:
context = {}
image_path = context.get("image_path", "unknown")
if error:
log.error("Error while uploading image '{}': {}".format(image_path, result["message"]))
else:
log.info("Image '{}' has been successfully uploaded".format(image_path))
self._image_uploading_count -= 1
def nextId(self):
if self.currentPage() == self.uiServerWizardPage:
if self._appliance.template_type() == "docker":
# skip Qemu binary selection and files pages if this is a Docker appliance
return super().nextId() + 3
elif self._appliance.template_type() != "qemu":
# skip the Qemu binary selection page if not a Qemu appliance
return super().nextId() + 1
if self.currentPage() == self.uiQemuWizardPage:
if not self._appliance.get("installation_instructions"):
# skip the installation instructions page if there are no instructions
return super().nextId() + 1
return super().nextId()
def validateCurrentPage(self):
"""
Validates the settings.
"""
if self.currentPage() == self.uiFilesWizardPage:
# validate the files page
if self._refreshing:
return False
current = self.uiApplianceVersionTreeWidget.currentItem()
if current is None or sip.isdeleted(current):
return False
version = current.data(0, QtCore.Qt.UserRole)
if version is None:
return False
appliance = current.data(2, QtCore.Qt.UserRole)
try:
self._appliance.search_images_for_version(version["name"])
except ApplianceError as e:
QtWidgets.QMessageBox.critical(self, "Appliance", "Cannot install {} version {}: {}".format(appliance["name"], version["name"], e))
return False
reply = QtWidgets.QMessageBox.question(self, "Appliance", "Would you like to install {} version {}?".format(appliance["name"], version["name"]),
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.No:
return False
self._uploadImages(appliance["name"], version["name"])
elif self.currentPage() == self.uiUsageWizardPage:
# validate the usage page
if self._template_created:
return True
if self._image_uploading_count > 0:
QtWidgets.QMessageBox.critical(self, "Add appliance", "Please wait for appliance files to be uploaded")
return False
current = self.uiApplianceVersionTreeWidget.currentItem()
if current:
version = current.data(0, QtCore.Qt.UserRole)
return self._install(version["name"])
else:
return self._install(None)
elif self.currentPage() == self.uiServerWizardPage:
# validate the server page
if self.uiRemoteRadioButton.isChecked():
if len(ComputeManager.instance().remoteComputes()) == 0:
QtWidgets.QMessageBox.critical(self, "Remote server", "There is no remote servers configured in your preferences")
return False
self._compute_id = self.uiRemoteServersComboBox.itemData(self.uiRemoteServersComboBox.currentIndex()).id()
elif hasattr(self, "uiVMRadioButton") and self.uiVMRadioButton.isChecked():
self._compute_id = "vm"
else:
if ComputeManager.instance().localPlatform():
if (ComputeManager.instance().localPlatform().startswith("darwin") or ComputeManager.instance().localPlatform().startswith("win")):
if "qemu" in self._appliance:
reply = QtWidgets.QMessageBox.question(self, "Appliance", "Qemu on Windows and macOS is not supported by the GNS3 team. Do you want to continue?", QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.No:
return False
self._compute_id = "local"
elif self.currentPage() == self.uiQemuWizardPage:
# validate the Qemu
if self._server_check is False:
QtWidgets.QMessageBox.critical(self, "Checking for KVM support", "Please wait for the server to reply...")
return False
if self.uiQemuListComboBox.currentIndex() == -1:
QtWidgets.QMessageBox.critical(self, "Qemu binary", "No compatible Qemu binary selected")
return False
return True
@qslot
def _vmToggledSlot(self, checked):
"""
Slot for when the VM radio button is toggled.
:param checked: either the button is checked or not
"""
if checked:
self.uiRemoteServersGroupBox.setEnabled(False)
self.uiRemoteServersGroupBox.hide()
@qslot
def _remoteServerToggledSlot(self, checked):
"""
Slot for when the remote server radio button is toggled.
:param checked: either the button is checked or not
"""
if checked:
self.uiRemoteServersGroupBox.setEnabled(True)
self.uiRemoteServersGroupBox.show()
@qslot
def _localToggledSlot(self, checked):
"""
Slot for when the local server radio button is toggled.
:param checked: either the button is checked or not
"""
if checked:
self.uiRemoteServersGroupBox.setEnabled(False)
self.uiRemoteServersGroupBox.hide()
@qslot
def _allowCustomFilesChangedSlot(self, checked):
"""
Slot for when user want to upload images which don't match md5
:param checked: if allows or doesn't allow custom files
:return:
"""
if checked:
reply = QtWidgets.QMessageBox.question(self, "Custom files",
"This option allows files with different MD5 checksums. This feature is only for advanced users and can lead "
"to unexpected problems. Do you want to proceed?",
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.No:
self.allowCustomFiles.setChecked(False)
return False

View File

@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016 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/>.
from gns3.qt import QtWidgets
from gns3.ui.capture_dialog_ui import Ui_CaptureDialog
import logging
log = logging.getLogger(__name__)
class CaptureDialog(QtWidgets.QDialog, Ui_CaptureDialog):
"""
This dialog allow configure the packet capture
"""
def __init__(self, parent, file_name, auto_start, ethernet_link=True):
super().__init__(parent)
self.setupUi(self)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(self._okButtonClickedSlot)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Cancel).clicked.connect(self.reject)
if ethernet_link:
self.uiDataLinkTypeComboBox.addItem("Ethernet", "DLT_EN10MB")
else:
self.uiDataLinkTypeComboBox.addItem("Cisco HDLC", "DLT_C_HDLC")
self.uiDataLinkTypeComboBox.addItem("Cisco PPP", "DLT_PPP_SERIAL")
self.uiDataLinkTypeComboBox.addItem("Frame Relay", "DLT_FRELAY")
self.uiDataLinkTypeComboBox.addItem("ATM", "DLT_ATM_RFC1483")
self.uiCaptureFileNameLineEdit.setText(file_name)
self.uiStartCommandCheckBox.setChecked(auto_start)
def _okButtonClickedSlot(self):
if len(self.fileName()) == 0:
QtWidgets.QMessageBox.warning(self.parent(), "Packet capture", "Please provide a file name for the capture")
return
self.accept()
def fileName(self):
return self.uiCaptureFileNameLineEdit.text()
def dataLink(self):
"""
Type of link for capture
"""
return self.uiDataLinkTypeComboBox.currentData()
def commandAutoStart(self):
return self.uiStartCommandCheckBox.isChecked()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
main = QtWidgets.QMainWindow()
dialog = CaptureDialog(main, "test.pcap")
dialog.show()
exit_code = app.exec_()
print(dialog.dataLink())
print(dialog.fileName())

View File

@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Dialog to configure and update node settings using widget pages.
"""
from ..qt import QtWidgets
from ..ui.configuration_dialog_ui import Ui_configurationDialog
from .node_properties_dialog import ConfigurationError
class ConfigurationDialog(QtWidgets.QDialog, Ui_configurationDialog):
"""
Configuration dialog implementation.
:param name: node template name
:param settings: node template settings
:param configuration_page: QWidget page
:param parent: parent widget
"""
def __init__(self, name, settings, configuration_page, parent):
super().__init__(parent)
self.setupUi(self)
self.uiTitleLabel.setText(name)
self.setWindowTitle(configuration_page.windowTitle())
self.uiConfigStackedWidget.addWidget(configuration_page)
self.uiConfigStackedWidget.setCurrentWidget(configuration_page)
self.setModal(True)
configuration_page.loadSettings(settings)
self._settings = settings
self._configuration_page = configuration_page
def settings(self):
return self._settings
def on_uiButtonBox_clicked(self, button):
"""
Slot called when a button of the uiButtonBox is clicked.
:param button: button that was clicked (QAbstractButton)
"""
if button == self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Cancel):
QtWidgets.QDialog.reject(self)
else:
try:
self._configuration_page.saveSettings(self._settings)
except ConfigurationError:
return
QtWidgets.QDialog.accept(self)

View File

@@ -0,0 +1,138 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016 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 sys
import copy
from gns3.qt import QtWidgets
from gns3.local_config import LocalConfig
from gns3.ui.console_command_dialog_ui import Ui_uiConsoleCommandDialog
from gns3.settings import PRECONFIGURED_TELNET_CONSOLE_COMMANDS, \
PRECONFIGURED_VNC_CONSOLE_COMMANDS, \
PRECONFIGURED_SPICE_CONSOLE_COMMANDS, \
CUSTOM_CONSOLE_COMMANDS_SETTINGS
import logging
log = logging.getLogger(__name__)
class ConsoleCommandDialog(QtWidgets.QDialog, Ui_uiConsoleCommandDialog):
"""
This dialog allow user to select the command used to start a
console.
"""
def __init__(self, parent, console_type="telnet", current=None):
"""
:params console_type: telnet, serial, vnc or spice
:params current: Current console command
"""
super().__init__(parent)
self.setupUi(self)
if console_type == "spice+agent":
# special case for spice+agent, use the spice console type
console_type = "spice"
self._console_type = console_type
self._current = current
self._settings = LocalConfig.instance().loadSectionSettings("CustomConsoleCommands", CUSTOM_CONSOLE_COMMANDS_SETTINGS)
self.uiCommandComboBox.currentIndexChanged.connect(self.commandComboBoxCurrentIndexChangedSlot)
self.uiCommandPlainTextEdit.textChanged.connect(self.textChangedSlot)
self.uiSavePushButton.clicked.connect(self.savePushButtonClickedSlot)
self.uiRemovePushButton.clicked.connect(self.removePushButtonClickedSlot)
self._refreshList()
def _refreshList(self):
if self._console_type == "telnet":
self._consoles = copy.copy(PRECONFIGURED_TELNET_CONSOLE_COMMANDS)
self._consoles.update(self._settings[self._console_type])
elif self._console_type == "vnc":
self._consoles = copy.copy(PRECONFIGURED_VNC_CONSOLE_COMMANDS)
self._consoles.update(self._settings[self._console_type])
elif self._console_type == "spice":
self._consoles = copy.copy(PRECONFIGURED_SPICE_CONSOLE_COMMANDS)
self._consoles.update(self._settings[self._console_type])
self.uiCommandComboBox.clear()
self.uiCommandComboBox.addItem("Custom", "")
for name, cmd in sorted(self._consoles.items(), key=(lambda item: item[0].lower())):
self.uiCommandComboBox.addItem(name, cmd)
if self._current:
self.uiCommandPlainTextEdit.setPlainText(self._current)
else:
self.uiCommandComboBox.setCurrentIndex(1)
def removePushButtonClickedSlot(self):
"""
Remove the custom command from the custom list
"""
self._settings[self._console_type].pop(self.uiCommandComboBox.currentText())
LocalConfig.instance().saveSectionSettings("CustomConsoleCommands", self._settings)
self._current = None
self._refreshList()
def savePushButtonClickedSlot(self):
"""
Save a custom command to the list
"""
name, ok = QtWidgets.QInputDialog.getText(self, "Add a command", "Command name:", QtWidgets.QLineEdit.Normal)
command = self.uiCommandPlainTextEdit.toPlainText().strip()
if ok and len(command) > 0:
if command not in self._consoles.values():
self._settings[self._console_type][name] = command
self._current = command
LocalConfig.instance().saveSectionSettings("CustomConsoleCommands", self._settings)
self._refreshList()
def textChangedSlot(self):
index = self.uiCommandComboBox.findData(self.uiCommandPlainTextEdit.toPlainText())
if index == -1:
index = 0
self.uiCommandComboBox.setCurrentIndex(index)
def commandComboBoxCurrentIndexChangedSlot(self, index):
self.uiRemovePushButton.hide()
# Ignore custom command
if index != 0:
self.uiCommandPlainTextEdit.setPlainText(self.uiCommandComboBox.currentData())
self.uiSavePushButton.hide()
if self.uiCommandComboBox.currentText() in self._settings[self._console_type].keys():
self.uiRemovePushButton.show()
else:
self.uiSavePushButton.show()
@staticmethod
def getCommand(parent, console_type="telnet", current=None):
dialog = ConsoleCommandDialog(parent, console_type=console_type, current=current)
dialog.show()
if dialog.exec_():
return True, dialog.uiCommandPlainTextEdit.toPlainText().replace("\n", " ")
return False, None
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
main = QtWidgets.QMainWindow()
(ok, command) = ConsoleCommandDialog.getCommand(main, console_type="telnet", current=list(PRECONFIGURED_TELNET_CONSOLE_COMMANDS.items())[0][1])
print(ok)
print(command)

View File

@@ -0,0 +1,205 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 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/>.
"""
Custom adapters configuration.
"""
import textwrap
import re
from ..qt import QtCore, QtWidgets
from ..ui.custom_adapters_configuration_dialog_ui import Ui_CustomAdaptersConfigurationDialog
class NoEditDelegate(QtWidgets.QStyledItemDelegate):
def __init__(self, parent=None):
QtWidgets.QStyledItemDelegate.__init__(self, parent=parent)
def createEditor(self, parent, option, index):
return None
class TreeWidgetItem(QtWidgets.QTreeWidgetItem):
def __lt__(self, other):
column = self.treeWidget().sortColumn()
key1 = self.text(column)
key2 = other.text(column)
return self.natural_sort_key(key1) < self.natural_sort_key(key2)
@staticmethod
def natural_sort_key(key):
regex = r'(\d*\.\d+|\d+)'
parts = re.split(regex, key)
return tuple((e if i % 2 == 0 else float(e)) for i, e in enumerate(parts))
class CustomAdaptersConfigurationDialog(QtWidgets.QDialog, Ui_CustomAdaptersConfigurationDialog):
"""
Custom adapters configuration dialog.
:param parent: parent widget
"""
def __init__(self, ports, custom_adapters, default_adapter_type=None, adapter_types=None, base_mac_address=None, parent=None):
super().__init__(parent)
self.setupUi(self)
self._ports = ports
self._default_adapter_type = default_adapter_type
self._adapter_types = adapter_types
self._custom_adapters = custom_adapters
self._base_mac_address = base_mac_address
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self._resetSlot)
if self._default_adapter_type and self._adapter_types:
self.uiAdaptersTreeWidget.setColumnCount(3)
self.uiAdaptersTreeWidget.headerItem().setText(2, "Adapter type")
if self._base_mac_address:
self.uiAdaptersTreeWidget.setColumnCount(4)
self.uiAdaptersTreeWidget.headerItem().setText(3, "MAC address")
self._populateWidgets()
# resize to fit the tree widget
width = 0
for column in range(self.uiAdaptersTreeWidget.columnCount()):
width += 20 + self.uiAdaptersTreeWidget.columnWidth(column)
self.resize(QtCore.QSize(width, self.height()))
def _getCustomAdapterSettings(self, adapter_number):
for custom_adapter in self._custom_adapters:
if custom_adapter["adapter_number"] == adapter_number:
return custom_adapter
return {}
def _MacToInteger(self, mac_address):
"""
Convert a macaddress with the format 00:0c:29:11:b0:0a to a int
:param mac_address: The mac address
:returns: Integer
"""
return int(mac_address.replace(":", ""), 16)
def _IntegerToMac(self, integer):
"""
Convert an integer to a mac address
"""
return ":".join(textwrap.wrap("%012x" % (integer), width=2))
def _populateWidgets(self):
adapter_number = 0
for port_name in self._ports:
item = TreeWidgetItem(self.uiAdaptersTreeWidget)
item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
item.setText(0, "Adapter {}".format(adapter_number))
item.setData(0, QtCore.Qt.UserRole, adapter_number)
item.setData(1, QtCore.Qt.UserRole, port_name)
custom_adapter = self._getCustomAdapterSettings(adapter_number)
item.setText(1, custom_adapter.get("port_name", port_name))
if self._default_adapter_type and self._adapter_types:
combobox = QtWidgets.QComboBox(self)
if type(self._adapter_types) == list:
for adapter_type in self._adapter_types:
combobox.addItem("{}".format(adapter_type))
else:
index = 0
for adapter_type, adapter_description in self._adapter_types.items():
combobox.addItem("{}".format(adapter_type))
combobox.setItemData(index, adapter_description, QtCore.Qt.ToolTipRole)
index += 1
adapter_type_index = combobox.findText(custom_adapter.get("adapter_type", self._default_adapter_type))
combobox.setCurrentIndex(adapter_type_index)
self.uiAdaptersTreeWidget.setItemWidget(item, 2, combobox)
if self._base_mac_address:
self.uiAdaptersTreeWidget.addTopLevelItem(item)
line_edit = QtWidgets.QLineEdit(self)
line_edit.setInputMask("HH:HH:HH:HH:HH:HH;_")
mac_address = self._IntegerToMac(self._MacToInteger(self._base_mac_address) + adapter_number)
line_edit.setText(custom_adapter.get("mac_address", mac_address))
self.uiAdaptersTreeWidget.setItemWidget(item, 3, line_edit)
adapter_number += 1
self.uiAdaptersTreeWidget.setItemDelegateForColumn(0, NoEditDelegate(self))
self.uiAdaptersTreeWidget.sortByColumn(0, QtCore.Qt.AscendingOrder)
self.uiAdaptersTreeWidget.setSortingEnabled(True)
for column in range(self.uiAdaptersTreeWidget.columnCount()):
self.uiAdaptersTreeWidget.resizeColumnToContents(column)
def _resetSlot(self):
self.uiAdaptersTreeWidget.clear()
self._custom_adapters.clear()
self._populateWidgets()
def _updateCustomAdapters(self):
self._custom_adapters.clear()
for row in range(self.uiAdaptersTreeWidget.topLevelItemCount()):
custom_adapter_settings = {}
item = self.uiAdaptersTreeWidget.topLevelItem(row)
port_name = item.text(1)
adapter_number = item.data(0, QtCore.Qt.UserRole)
custom_adapter_settings["adapter_number"] = adapter_number
original_port_name = item.data(1, QtCore.Qt.UserRole)
if not port_name:
QtWidgets.QMessageBox.critical(self, "Port name", "Port name cannot be empty for adapter {}".format(adapter_number))
return False
if original_port_name != port_name:
custom_adapter_settings["port_name"] = port_name
if self._default_adapter_type and self._adapter_types:
adapter_type = self.uiAdaptersTreeWidget.itemWidget(item, 2).currentText()
if self._default_adapter_type != adapter_type:
custom_adapter_settings["adapter_type"] = adapter_type
if self._base_mac_address:
mac_address = self.uiAdaptersTreeWidget.itemWidget(item, 3).text()
if mac_address and mac_address != ":::::":
if not re.search(r"""^([0-9a-fA-F]{2}[:]){5}[0-9a-fA-F]{2}$""", mac_address):
QtWidgets.QMessageBox.critical(self, "MAC address", "Invalid MAC address (format required: hh:hh:hh:hh:hh:hh)")
return False
default_mac_address = self._IntegerToMac(self._MacToInteger(self._base_mac_address) + adapter_number)
if mac_address != default_mac_address:
custom_adapter_settings["mac_address"] = mac_address
if len(custom_adapter_settings) > 1:
# only save if there is more than the adapter_number key
self._custom_adapters.append(custom_adapter_settings.copy())
return True
def done(self, result):
"""
Called when the dialog is closed.
:param result: boolean (accepted or rejected)
"""
if result:
if not self._updateCustomAdapters():
return
super().done(result)

View File

@@ -0,0 +1,226 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016 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 psutil
import platform
import os
import stat
import sys
import struct
from gns3.qt import QtWidgets
from gns3.ui.doctor_dialog_ui import Ui_DoctorDialog
from gns3.local_server import LocalServer
from gns3.local_config import LocalConfig
from gns3 import version
from gns3.modules.vmware import VMware
import logging
log = logging.getLogger(__name__)
class DoctorDialog(QtWidgets.QDialog, Ui_DoctorDialog):
"""
This dialog allow user to detect error in his GNS3 installation.
If you want to add a test add a method starting by check. The
check return a tuple result and a message in case of failure.
"""
def __init__(self, parent, console=False):
super().__init__(parent)
self._console = console
self.setupUi(self)
self.uiOkButton.clicked.connect(self._okButtonClickedSlot)
for method in sorted(dir(self)):
if method.startswith('check'):
try:
self.write(getattr(self, method).__doc__ + "...")
(res, msg) = getattr(self, method)()
if res == 0:
self.write('<span style="color: green"><strong>OK</strong></span>')
elif res == 1:
self.write('<span style="color: orange"><strong>WARNING</strong> {}</span>'.format(msg))
elif res == 2:
self.write('<span style="color: red"><strong>ERROR</strong> {}</span>'.format(msg))
except Exception as e:
log.error("GNS3 doctor exception detected: {}".format(e), exc_info=1)
self.write('<span style="color: red"><strong>FAIL</strong> The doctor failed during this test with error: {} Please check on the forum.</span>'.format(str(e)))
self.write("<br/>")
def write(self, text):
"""
Add text to the text windows
"""
if self._console:
print(text)
self.uiDoctorResultTextEdit.setHtml(self.uiDoctorResultTextEdit.toHtml() + text)
def _okButtonClickedSlot(self):
self.accept()
def checkLocalServerEnabled(self):
"""Checking if the local server is enabled"""
if LocalServer.instance().shouldLocalServerAutoStart() is False:
return (2, "The local server is disabled. Go to Preferences -> Server -> Local Server and enable the local server.")
return (0, None)
def checkDevVersionOfGNS3(self):
"""Checking for stable GNS3 version"""
if version.__version_info__[3] != 0:
return (1, "You are using a unstable version of GNS3.")
return (0, None)
def checkExperimentalFeaturesEnabled(self):
"""Checking if experimental features are not enabled"""
if LocalConfig.instance().experimental():
return (1, "Experimental features are enabled. Turn them off by going to Preferences -> General -> Miscellaneous.")
return (0, None)
def checkAVGInstalled(self):
"""Checking if AVG software is not installed"""
if sys.platform.startswith("win32"):
for proc in psutil.process_iter():
try:
psinfo = proc.as_dict(["exe"])
if psinfo["exe"] and "AVG\\" in psinfo["exe"]:
return (2, "AVG has known issues with GNS3, even after you disable it. You must whitelist dynamips.exe in the AVG preferences.")
except psutil.NoSuchProcess:
pass
return (0, None)
def checkFreeRam(self):
"""Checking for amount of free virtual memory"""
if int(psutil.virtual_memory().available / (1024 * 1024)) < 600:
return (2, "You have less than 600MB of available virtual memory, this could prevent nodes to start")
return (0, None)
def checkVmrun(self):
"""Checking if vmrun is installed"""
vmrun = VMware.instance().findVmrun()
if len(vmrun) == 0:
return (1, "The vmrun executable could not be found, VMware VMs cannot be used")
return (0, None)
def check64Bit(self):
"""Check if processor is 64 bit"""
if platform.architecture()[0] != "64bit":
return (2, "The architecture {} is not supported.".format(platform.architecture()[0]))
return (0, None)
def checkUbridgePermission(self):
"""Check if ubridge has the correct permission"""
if not sys.platform.startswith("win") and os.geteuid() == 0:
# we are root, so we should have privileged access.
return (0, None)
path = LocalServer.instance().localServerSettings().get("ubridge_path")
if path is None:
return (0, None)
if not os.path.exists(path):
return (2, "Ubridge path {path} doesn't exists".format(path=path))
if sys.platform.startswith("linux"):
try:
if "security.capability" not in os.listxattr(path) or not struct.unpack("<IIIII", os.getxattr(path, "security.capability"))[1] & 1 << 13:
return (2, "Ubridge requires CAP_NET_RAW. Run sudo setcap cap_net_admin,cap_net_raw=ep {path}".format(path=path))
except (OSError, AttributeError) as e:
# Due to a Python bug, os.listxattr could be missing: https://github.com/GNS3/gns3-gui/issues/2010
return (1, "Could not determine if CAP_NET_RAW capability is set for uBridge: {}".format(e))
if sys.platform.startswith("darwin"):
if os.stat(path).st_uid != 0 or not os.stat(path).st_mode & stat.S_ISUID:
return (2, "Ubridge should be setuid. Run sudo chown root:admin {path} and sudo chmod 4750 {path}".format(path=path))
return (0, None)
def checkDynamipsPermission(self):
"""Check if dynamips has the correct permission"""
if not sys.platform.startswith("win") and os.geteuid() == 0:
# we are root, so we should have privileged access.
return (0, None)
path = LocalServer.instance().localServerSettings().get("dynamips_path")
if path is None:
return (0, None)
if not os.path.exists(path):
return (2, "Dynamips path {path} doesn't exists".format(path=path))
try:
if sys.platform.startswith("linux") and "security.capability" in os.listxattr(path):
caps = os.getxattr(path, "security.capability")
# test the 2nd byte and check if the 13th bit (CAP_NET_RAW) is set
if not struct.unpack("<IIIII", caps)[1] & 1 << 13:
return (2, "Dynamips requires CAP_NET_RAW. Run sudo setcap cap_net_raw,cap_net_admin+eip {path}".format(path=path))
except AttributeError:
# Due to a Python bug, os.listxattr could be missing: https://github.com/GNS3/gns3-gui/issues/2010
return (1, "Could not determine if CAP_NET_RAW capability is set for Dynamips (Python bug)".format(path=path))
return (0, None)
def checkGNS3InstalledTwice(self):
"""Check if gns3 is not installed twice"""
if not sys.platform.startswith("win"):
return (0, None)
try:
if os.path.exists("/usr/local/bin/gns3server") and os.path.exists("/usr/bin/gns3server"):
return (2, "GNS3 is installed twice please remove it from /usr/local/bin")
except OSError:
pass
return (0, None)
def _checkWindowsService(self, service_name):
import pywintypes
import win32service
import win32serviceutil
try:
if win32serviceutil.QueryServiceStatus(service_name, None)[1] != win32service.SERVICE_RUNNING:
return False
except pywintypes.error as e:
if e.winerror == 1060:
return False
else:
raise
return True
def checkRPFServiceIsRunning(self):
"""Check if the RPF service is running (required to use Ethernet NIOs)"""
if not sys.platform.startswith("win"):
return (0, None)
import pywintypes
try:
if not self._checkWindowsService("npf") and not self._checkWindowsService("npcap"):
return (2, "The NPF or NPCAP service is not installed, please install Winpcap or Npcap and reboot")
except pywintypes.error as e:
return (2, "Could not check if the NPF or Npcap service is running: {}".format(e.strerror))
return (0, None)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
main = QtWidgets.QMainWindow()
dialog = DoctorDialog(main, console=True)
# dialog.show()
#exit_code = app.exec_()

View File

@@ -0,0 +1,124 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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 re
from gns3.qt import QtWidgets
from gns3.compute import Compute
from gns3.ui.edit_compute_dialog_ui import Ui_EditComputeDialog
class EditComputeDialog(QtWidgets.QDialog, Ui_EditComputeDialog):
"""
New compute dialog.
:param parent: parent widget.
"""
def __init__(self, parent, compute=None):
super().__init__(parent)
self.setupUi(self)
self.uiEnableAuthenticationCheckBox.toggled.connect(self._enableAuthenticationSlot)
self._compute = compute
if self._compute:
self.uiServerNameLineEdit.setText(self._compute.name())
self.uiServerHostLineEdit.setText(self._compute.host())
self.uiServerPortSpinBox.setValue(self._compute.port())
index = self.uiServerProtocolComboBox.findText(self._compute.protocol().upper())
self.uiServerProtocolComboBox.setCurrentIndex(index)
if self._compute.user():
self.uiEnableAuthenticationCheckBox.setChecked(True)
self.uiServerUserLineEdit.setText(self._compute.user())
else:
self.uiEnableAuthenticationCheckBox.setChecked(False)
self.uiWarningLabel.setVisible(False)
else:
self.uiEnableAuthenticationCheckBox.setChecked(False)
self.uiWarningLabel.setVisible(False)
self._enableAuthenticationSlot(self.uiEnableAuthenticationCheckBox.isChecked())
def _enableAuthenticationSlot(self, state):
"""
Slot to enable or not the authentication.
"""
if self.uiEnableAuthenticationCheckBox.isChecked():
self.uiServerUserLineEdit.setVisible(True)
self.uiServerPasswordLineEdit.setVisible(True)
self.uiServerUserLabel.setVisible(True)
self.uiServerPasswordLabel.setVisible(True)
else:
self.uiServerUserLineEdit.setVisible(False)
self.uiServerPasswordLineEdit.setVisible(False)
self.uiServerUserLabel.setVisible(False)
self.uiServerPasswordLabel.setVisible(False)
def compute(self):
return self._compute
def accept(self):
"""
Adds a new remote compute.
"""
host = self.uiServerHostLineEdit.text().strip()
name = self.uiServerNameLineEdit.text().strip()
protocol = self.uiServerProtocolComboBox.currentText().lower()
port = self.uiServerPortSpinBox.value()
user = self.uiServerUserLineEdit.text().strip()
password = self.uiServerPasswordLineEdit.text().strip()
if not re.match(r"^[a-zA-Z0-9\.{}-]+$".format("\u0370-\u1CDF\u2C00-\u30FF\u4E00-\u9FBF"), host):
QtWidgets.QMessageBox.critical(self, "Remote compute", "Invalid remote server hostname {}".format(host))
return
if name == "gns3vm":
QtWidgets.QMessageBox.critical(self, "Remote compute", "{} is a reserved name".format(name))
return
if len(name) == 0:
QtWidgets.QMessageBox.critical(self, "Remote compute", "Invalid remote server name {}".format(name))
return
if port is None or port < 1:
QtWidgets.QMessageBox.critical(self, "Remote compute", "Invalid remote server port {}".format(port))
return
if not self._compute:
self._compute = Compute()
self._compute.setName(name)
self._compute.setProtocol(protocol)
self._compute.setHost(host)
self._compute.setPort(port)
if self.uiEnableAuthenticationCheckBox.isChecked():
self._compute.setUser(user)
self._compute.setPassword(password)
else:
self._compute.setUser(None)
self._compute.setPassword(None)
super().accept()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
main = QtWidgets.QMainWindow()
dialog = EditComputeDialog(main)
dialog.show()
exit_code = app.exec_()

View File

@@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
from ..qt import QtWidgets, QtCore, qslot, qpartial
from ..topology import Topology
from ..ui.edit_project_dialog_ui import Ui_EditProjectDialog
class EditProjectDialog(QtWidgets.QDialog, Ui_EditProjectDialog):
"""
Edit current project settings
"""
def __init__(self, parent):
super().__init__(parent)
self.setupUi(self)
self._project = Topology.instance().project()
self.uiProjectNameLineEdit.setText(self._project.name())
self.uiProjectAutoOpenCheckBox.setChecked(self._project.autoOpen())
self.uiProjectAutoCloseCheckBox.setChecked(not self._project.autoClose())
self.uiProjectAutoStartCheckBox.setChecked(self._project.autoStart())
self.uiSceneWidthSpinBox.setValue(self._project.sceneWidth())
self.uiSceneHeightSpinBox.setValue(self._project.sceneHeight())
self.uiNodeGridSizeSpinBox.setValue(self._project.nodeGridSize())
self.uiDrawingGridSizeSpinBox.setValue(self._project.drawingGridSize())
self.uiGlobalVariablesGrid.setAlignment(QtCore.Qt.AlignTop)
self.uiNewVarButton = QtWidgets.QPushButton('Add new variable', self)
self.uiNewVarButton.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
self.uiNewVarButton.clicked.connect(self.onAddNewVariable)
self.uiGlobalVariablesGrid.addWidget(self.uiNewVarButton, 0, 3, QtCore.Qt.AlignRight)
self._variables = self._project.variables()
if not self._variables:
self._variables = [{"name": "", "value": ""}]
self.updateGlobalVariables()
def updateGlobalVariables(self):
while True:
item = self.uiGlobalVariablesGrid.takeAt(1)
if item is None:
break
elif item.widget():
item.widget().deleteLater()
for i, variable in enumerate(self._variables, start=1):
nameLabel = QtWidgets.QLabel()
nameLabel.setText("Name:")
self.uiGlobalVariablesGrid.addWidget(nameLabel, i, 0)
nameEdit = QtWidgets.QLineEdit()
nameEdit.setText(variable.get("name", ""))
nameEdit.textChanged.connect(qpartial(self.onNameChange, variable))
self.uiGlobalVariablesGrid.addWidget(nameEdit, i, 1)
valueLabel = QtWidgets.QLabel()
valueLabel.setText("Value:")
self.uiGlobalVariablesGrid.addWidget(valueLabel, i, 2)
valueEdit = QtWidgets.QLineEdit()
valueEdit.setText(variable.get("value", ""))
valueEdit.textChanged.connect(qpartial(self.onValueChange, variable))
self.uiGlobalVariablesGrid.addWidget(valueEdit, i, 3)
@qslot
def onAddNewVariable(self, event):
self._variables += [{"name": "", "value": ""}]
self.updateGlobalVariables()
def onNameChange(self, variable, text):
variable["name"] = text
def onValueChange(self, variable, text):
variable["value"] = text
def _cleanVariables(self):
return [v for v in self._variables if v.get("name").strip() != ""]
def done(self, result):
"""
Called when the dialog is closed.
:param result: boolean (accepted or rejected)
"""
if result:
node_grid_size = self.uiNodeGridSizeSpinBox.value()
drawing_grid_size = self.uiDrawingGridSizeSpinBox.value()
if node_grid_size % drawing_grid_size != 0:
QtWidgets.QMessageBox.critical(self, "Grid sizes", "Invalid grid sizes which will create overlapping lines")
else:
self._project.setNodeGridSize(node_grid_size)
self._project.setDrawingGridSize(drawing_grid_size)
self._project.setName(self.uiProjectNameLineEdit.text())
self._project.setAutoOpen(self.uiProjectAutoOpenCheckBox.isChecked())
self._project.setAutoClose(not self.uiProjectAutoCloseCheckBox.isChecked())
self._project.setAutoStart(self.uiProjectAutoStartCheckBox.isChecked())
self._project.setSceneHeight(self.uiSceneHeightSpinBox.value())
self._project.setSceneWidth(self.uiSceneWidthSpinBox.value())
self._project.setVariables(self._cleanVariables())
self._project.update()
super().done(result)

View File

@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
from ..qt import QtCore, QtWidgets
from ..ui.exec_command_dialog_ui import Ui_ExecCommandDialog
class ExecCommandDialog(QtWidgets.QDialog, Ui_ExecCommandDialog):
"""
Execute a command and display its output.
"""
def __init__(self, parent, command, params):
super().__init__(parent)
self.setupUi(self)
self.setWindowTitle("Executing {}".format(command))
self._process = QtCore.QProcess(self)
self._process.readyRead.connect(self._dataReadySlot)
self._process.start(command, params, QtCore.QProcess.Unbuffered | QtCore.QProcess.ReadWrite)
def _dataReadySlot(self):
"""
Display the command output when data is ready.
"""
cursor = self.uiOutputTextEdit.textCursor()
cursor.movePosition(cursor.End)
for line in self._process.readAll():
cursor.insertText(line)
for line in self._process.readAllStandardError():
cursor.insertText(line)
self.uiOutputTextEdit.ensureCursorVisible()
def done(self, result):
"""
Called when the dialog is closed.
:param result: boolean (accepted or rejected)
"""
self._process.kill()
self._process.waitForFinished()
super().done(result)

View File

@@ -0,0 +1,143 @@
# -*- 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/>.
from zipfile import ZipFile
import platform
import psutil
import os
from gns3.version import __version__
from gns3.qt import QtWidgets, QtCore
from gns3.ui.export_debug_dialog_ui import Ui_ExportDebugDialog
from gns3.local_config import LocalConfig
from gns3.controller import Controller
import logging
log = logging.getLogger(__name__)
class ExportDebugDialog(QtWidgets.QDialog, Ui_ExportDebugDialog):
"""
This dialog allow user to export useful information
for remote debugging by a GNS3 developers.
"""
def __init__(self, parent, project):
super().__init__(parent)
self._project = project
self.setupUi(self)
self.uiOkButton.clicked.connect(self._okButtonClickedSlot)
def _okButtonClickedSlot(self):
if Controller.instance().isRemote():
QtWidgets.QMessageBox.critical(self, "Debug", "Export debug information from a remote server is not supported")
self.reject()
return
self._path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Export debug file", None, "Zip file (*.zip)", "Zip file (*.zip)")
if len(self._path) == 0:
self.reject()
return
if Controller.instance().connected():
Controller.instance().post("/debug", self._exportDebugCallback)
else:
self._exportDebugCallback({}, error=True)
def _exportDebugCallback(self, result, error=False, **kwargs):
log.debug("Export debug information to %s", self._path)
try:
with ZipFile(self._path, 'w') as zip:
zip.writestr("debug.txt", self._getDebugData())
dir = LocalConfig.instance().configDirectory()
for filename in os.listdir(dir):
path = os.path.join(dir, filename)
if os.path.isfile(path):
zip.write(path, filename)
dir = os.path.join(LocalConfig.instance().configDirectory(), "debug")
if os.path.exists(dir):
for filename in os.listdir(dir):
path = os.path.join(dir, filename)
if os.path.isfile(path):
zip.write(path, filename)
if self._project:
dir = self._project.filesDir()
if dir:
for filename in os.listdir(dir):
path = os.path.join(dir, filename)
if os.path.isfile(path):
zip.write(path, filename)
except OSError as e:
QtWidgets.QMessageBox.critical(self, "Debug", "Can't export debug information: {}".format(str(e)))
self.accept()
def _getDebugData(self):
try:
connections = psutil.net_connections()
# You need to be root for OSX
except psutil.AccessDenied:
connections = None
try:
addrs = ["* {}: {}".format(key, val) for key, val in psutil.net_if_addrs().items()]
except UnicodeDecodeError:
addrs = ["INVALID ADDR WITH UNICODE CHARACTERS"]
data = """Version: {version}
OS: {os}
Python: {python}
Qt: {qt}
PyQt: {pyqt}
CPU: {cpu}
Memory: {memory}
Networks:
{addrs}
Open connections:
{connections}
Processus:
""".format(
version=__version__,
qt=QtCore.QT_VERSION_STR,
pyqt=QtCore.PYQT_VERSION_STR,
os=platform.platform(),
python=platform.python_version(),
memory=psutil.virtual_memory(),
cpu=psutil.cpu_times(),
connections=connections,
addrs="\n".join(addrs)
)
for proc in psutil.process_iter():
try:
psinfo = proc.as_dict(attrs=["name", "exe"])
data += "* {} {}\n".format(psinfo["name"], psinfo["exe"])
except psutil.NoSuchProcess:
pass
return data
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
print(ExportDebugDialog(None)._getDebugData())

View File

@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016 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 os
from gns3.qt import QtWidgets
from gns3.ui.file_editor_dialog_ui import Ui_FileEditorDialog
import logging
log = logging.getLogger(__name__)
class FileEditorDialog(QtWidgets.QDialog, Ui_FileEditorDialog):
"""
This dialog allow user to detect error in his GNS3 installation.
If you want to add a test add a method starting by check. The
check return a tuple result and a message in case of failure.
"""
def __init__(self, target, path, parent=None, default=""):
if parent is None:
from gns3.main_window import MainWindow
parent = MainWindow.instance()
super().__init__(parent)
self.setupUi(self)
self._target = target
self._path = path
self._default = default
self.setWindowTitle(target.name() + " " + os.path.basename(path))
self.uiRefreshButton.pressed.connect(self._refreshSlot)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Save).clicked.connect(self._okButtonClickedSlot)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Cancel).clicked.connect(self.reject)
self._refreshSlot()
def _okButtonClickedSlot(self):
text = self.uiFileTextEdit.toPlainText()
self._target.post("/files/" + self._path, self._saveCallback, body=text)
def _saveCallback(self, result, error=False, **kwargs):
if not error:
self.accept()
def _refreshSlot(self):
self._target.get("/files/" + self._path, self._getCallback)
def _getCallback(self, result, error=False, raw_body=None, **kwargs):
if not error:
self.uiFileTextEdit.setText(raw_body.decode("utf-8", errors="ignore"))
elif result.get("status") == 404:
if self._default:
self.uiFileTextEdit.setText(self._default)

View File

@@ -0,0 +1,178 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
from ..qt import QtGui, QtWidgets, qslot
from ..ui.filter_dialog_ui import Ui_FilterDialog
import logging
log = logging.getLogger(__name__)
class FilterDialog(QtWidgets.QDialog, Ui_FilterDialog):
"""
Filter dialog.
"""
def __init__(self, parent, link):
super().__init__(parent)
self.setupUi(self)
self._link = link
self._filters = {}
self._link.updated_link_signal.connect(self._updateUiSlot)
self._link.listAvailableFilters(self._listAvailableFiltersCallback)
self._initialized = False
self._filter_items = {}
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self._applyPreferencesSlot)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self._helpSlot)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self._resetSlot)
def _listAvailableFiltersCallback(self, result, error=False, *args, **kwargs):
if error:
log.warning("Error while listing information about the link: {}".format(result["message"]))
return
self._filters = result
self._initialized = True
self._updateUiSlot()
@qslot
def _updateUiSlot(self, *args):
# Empty the main layout
while True:
item = self.uiVerticalLayout.takeAt(0)
if item is None:
break
elif item.widget():
item.widget().deleteLater()
if len(self._filters) == 0:
QtWidgets.QMessageBox.critical(self, "Link", "No filter available for this link. Try with a different node type.")
self.reject()
self._tabWidget = QtWidgets.QTabWidget(self)
for i, filter in enumerate(self._filters):
tab = QtWidgets.QWidget()
self._tabWidget.addTab(tab, filter['name'])
self._tabWidget.setTabToolTip(i, filter['description'])
self._tabWidget.setTabIcon(i, QtGui.QIcon(':/icons/led_red.svg'))
vlayout = QtWidgets.QVBoxLayout()
gridLayout = QtWidgets.QGridLayout()
line = 0
filter["spinBoxes"] = []
filter["textEdits"] = []
nb_spin = 0
for param in filter["parameters"]:
label = QtWidgets.QLabel()
label.setText(param["name"] + ":")
gridLayout.addWidget(label, line, 0, 1, 1)
if param["type"] == "int":
spinBox = QtWidgets.QSpinBox()
filter["spinBoxes"].append(spinBox)
spinBox.setMinimum(param["minimum"])
spinBox.setMaximum(param["maximum"])
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(spinBox.sizePolicy().hasHeightForWidth())
spinBox.setSizePolicy(sizePolicy)
try:
value = self._link.filters()[filter["type"]][nb_spin]
spinBox.setValue(value)
if value != 0:
self._tabWidget.setTabIcon(i, QtGui.QIcon(':/icons/led_green.svg'))
except(KeyError, IndexError):
pass
nb_spin += 1
gridLayout.addWidget(spinBox, line, 1, 1, 1)
unit = QtWidgets.QLabel()
unit.setText(param["unit"])
gridLayout.addWidget(unit, line, 2, 1, 1)
elif param["type"] == "text":
textEdit = QtWidgets.QTextEdit()
textEdit.setAcceptRichText(False)
filter["textEdits"].append(textEdit)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
textEdit.setMinimumWidth(300)
textEdit.setSizePolicy(sizePolicy)
try:
text = self._link.filters()[filter["type"]][0]
textEdit.setPlainText(text)
if text:
self._tabWidget.setTabIcon(i, QtGui.QIcon(':/icons/led_green.svg'))
except(KeyError, IndexError):
pass
gridLayout.addWidget(textEdit, line, 1, 1, 1)
line += 1
spacerItem = QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
gridLayout.addItem(spacerItem, line, 0, 1, 1)
vlayout.addLayout(gridLayout)
tab.setLayout(vlayout)
self.uiVerticalLayout.addWidget(self._tabWidget)
@qslot
def _applyPreferencesSlot(self, *args):
new_filters = {}
for filter in self._filters:
new_filters[filter["type"]] = []
for spinBox in filter["spinBoxes"]:
new_filters[filter["type"]].append(spinBox.value())
for spinBox in filter["textEdits"]:
new_filters[filter["type"]].append(spinBox.toPlainText())
self._link.setFilters(new_filters)
self._link.update()
@qslot
def _helpSlot(self, *args):
help_text = "Filters are applied to packets in both direction.\n\n"
filter_nb = 0
for filter in self._filters:
help_text += "{}: {}".format(filter["name"], filter["description"])
filter_nb += 1
if len(self._filters) != filter_nb:
help_text += "\n\n"
QtWidgets.QMessageBox.information(self, "Help for filters", help_text)
@qslot
def _resetSlot(self, *args):
filters = {}
self._link.setFilters(filters)
self._link.update()
def done(self, result):
"""
Called when the dialog is closed.
:param result: boolean (accepted or rejected)
"""
if result and self._initialized:
self._applyPreferencesSlot()
super().done(result)

View File

@@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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 os
import re
from ..qt import QtWidgets
from ..topology import Topology
from ..ui.idlepc_dialog_ui import Ui_IdlePCDialog
class IdlePCDialog(QtWidgets.QDialog, Ui_IdlePCDialog):
"""
Idle-PC dialog.
"""
def __init__(self, router, idlepcs, parent):
super().__init__(parent)
self.setupUi(self)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self._applySlot)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect(self._helpSlot)
self._router = router
self._idlepcs = idlepcs
for value in self._idlepcs:
# validate idle-pc format, e.g. 0x60c09aa0
match = re.search(r"^(0x[0-9a-f]{8})\s+\[(\d+)\]$", value)
if match:
idlepc = match.group(1)
count = int(match.group(2))
if 50 <= count <= 60:
value += "*"
self.uiComboBox.addItem(value, idlepc)
def _helpSlot(self):
"""
Shows the help for Idle-PC.
"""
help_text = """Best Idle-PC values are obtained when IOS is in idle state, after the "Press RETURN to get started" message has appeared on the console, messages have finished displaying on the console and you have have actually pressed the RETURN key.
Finding the right idle-pc value is a trial and error process, consisting of applying different Idle-PC values and monitoring the CPU usage.
Select each value that appears in the list and click Apply, and note the CPU usage a few moments later. When you have found the value that minimises the CPU usage, apply that value.
"""
QtWidgets.QMessageBox.information(self, "Hints for Idle-PC", help_text)
def _applySlot(self, update_template=False):
"""
Applies an Idle-PC value.
"""
if not self.uiComboBox.count():
QtWidgets.QMessageBox.critical(self, "Idle-PC", "Sorry could not find a valid Idle-PC value, please check again with Cisco IOS in a different state")
return
idlepc = self.uiComboBox.itemData(self.uiComboBox.currentIndex())
# apply Idle-PC to all routers with the same IOS image
ios_image = os.path.basename(self._router.settings()["image"])
for node in Topology.instance().nodes():
if hasattr(node, "idlepc") and node.settings()["image"] == ios_image:
node.setIdlepc(idlepc)
if update_template:
# apply the idle-pc to templates with the same IOS image
self._router.module().updateImageIdlepc(ios_image, idlepc)
def done(self, result):
"""
Called when the dialog is closed.
:param result: boolean (accepted or rejected)
"""
if result:
self._applySlot(update_template=True)
super().done(result)

View File

@@ -0,0 +1,288 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 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 sys
import tempfile
import json
import sip
import os
from gns3.qt import QtCore, QtWidgets, qpartial
from gns3.controller import Controller
from gns3.appliance_manager import ApplianceManager
from ..ui.new_template_wizard_ui import Ui_NewTemplateWizard
import logging
log = logging.getLogger(__name__)
class NewTemplateWizard(QtWidgets.QWizard, Ui_NewTemplateWizard):
"""
New template wizard.
"""
def __init__(self, parent):
super().__init__(parent)
self.setupUi(self)
self.setWizardStyle(QtWidgets.QWizard.ModernStyle)
if sys.platform.startswith("darwin"):
# we want to see the cancel button on OSX
self.setOptions(QtWidgets.QWizard.NoDefaultButton)
# add a custom button to show appliance information
self.setButtonText(QtWidgets.QWizard.CustomButton1, "&Update from online registry")
self.setOption(QtWidgets.QWizard.HaveCustomButton1, True)
self.customButtonClicked.connect(self._downloadAppliancesSlot)
self.button(QtWidgets.QWizard.CustomButton1).hide()
self.uiFilterLineEdit.textChanged.connect(self._filterTextChangedSlot)
ApplianceManager.instance().appliances_changed_signal.connect(self._appliancesChangedSlot)
def _downloadAppliancesSlot(self):
"""
Request server to update appliances from online registry.
"""
ApplianceManager.instance().refresh(update=True)
Controller.instance().clearStaticCache()
def _appliancesChangedSlot(self):
"""
Called when the appliances have been updated.
"""
self._get_appliances_from_server()
QtWidgets.QMessageBox.information(self, "Appliances", "Appliances are up-to-date!")
def _filterTextChangedSlot(self, text):
self._get_appliances_from_server(appliance_filter=text)
def _setItemIcon(self, item, icon):
if item is None or sip.isdeleted(item):
return
item.setIcon(0, icon)
def _get_tooltip_text(self, appliance):
"""
Gets the appliance information to be displayed in the tooltip.
"""
info = (("Product", "product_name"),
("Vendor", "vendor_name"),
("Availability", "availability"),
("Status", "status"),
("Maintainer", "maintainer"))
if "qemu" in appliance:
qemu_info = (("vCPUs", "qemu/cpus"),
("RAM", "qemu/ram"),
("Adapters", "qemu/adapters"),
("Adapter type", "qemu/adapter_type"),
("Console type", "qemu/console_type"),
("Architecture", "qemu/arch"),
("Console type", "qemu/console_type"),
("KVM", "qemu/kvm"))
info = info + qemu_info
elif "docker" in appliance:
docker_info = (("Image", "docker/image"),
("Adapters", "docker/adapters"),
("Console type", "docker/console_type"))
info = info + docker_info
elif "iou" in appliance:
iou_info = (("RAM", "iou/ram"),
("NVRAM", "iou/nvram"),
("Ethernet adapters", "iou/ethernet_adapters"),
("Serial adapters", "iou/serial_adapters"))
info = info + iou_info
elif "dynamips" in appliance:
dynamips_info = (("Platform", "dynamips/platform"),
("Chassis", "dynamips/chassis"),
("Midplane", "dynamips/midplane"),
("NPE", "dynamips/npe"),
("RAM", "dynamips/ram"),
("NVRAM", "dynamips/nvram"),
("slot0", "dynamips/slot0"),
("slot1", "dynamips/slot1"),
("slot2", "dynamips/slot2"),
("slot3", "dynamips/slot3"),
("slot4", "dynamips/slot4"),
("slot5", "dynamips/slot5"),
("slot6", "dynamips/slot6"),
("wic0", "dynamips/wic0"),
("wic1", "dynamips/wic1"),
("wic2", "dynamips/wic2"))
info = info + dynamips_info
text_info = ""
for (name, key) in info:
if "/" in key:
key, subkey = key.split("/")
value = appliance.get(key, {}).get(subkey, None)
else:
value = appliance.get(key, None)
if value is None:
continue
text_info += "<span style='font-weight:bold;'>{}</span>: {}<br>".format(name, value)
return text_info
def _get_appliances_from_server(self, appliance_filter=None):
"""
Gets the appliances from the server and display them.
"""
self.uiAppliancesTreeWidget.clear()
parent_routers = QtWidgets.QTreeWidgetItem(self.uiAppliancesTreeWidget)
parent_routers.setText(0, "Routers")
parent_routers.setFlags(parent_routers.flags() & ~QtCore.Qt.ItemIsSelectable)
parent_switches = QtWidgets.QTreeWidgetItem(self.uiAppliancesTreeWidget)
parent_switches.setText(0, "Switches")
parent_switches.setFlags(parent_switches.flags() & ~QtCore.Qt.ItemIsSelectable)
parent_guests = QtWidgets.QTreeWidgetItem(self.uiAppliancesTreeWidget)
parent_guests.setText(0, "Guests")
parent_guests.setFlags(parent_guests.flags() & ~QtCore.Qt.ItemIsSelectable)
parent_firewalls = QtWidgets.QTreeWidgetItem(self.uiAppliancesTreeWidget)
parent_firewalls.setText(0, "Firewalls")
parent_firewalls.setFlags(parent_firewalls.flags() & ~QtCore.Qt.ItemIsSelectable)
self.uiAppliancesTreeWidget.expandAll()
for appliance in ApplianceManager.instance().appliances():
if appliance_filter is None:
appliance_filter = self.uiFilterLineEdit.text().strip()
if appliance_filter and appliance_filter.lower() not in appliance["name"].lower():
continue
if appliance["category"] == "router":
item = QtWidgets.QTreeWidgetItem(parent_routers)
elif appliance["category"].endswith("switch"):
item = QtWidgets.QTreeWidgetItem(parent_switches)
elif appliance["category"] == "firewall":
item = QtWidgets.QTreeWidgetItem(parent_firewalls)
elif appliance["category"] == "guest":
item = QtWidgets.QTreeWidgetItem(parent_guests)
if appliance["builtin"]:
appliance_name = appliance["name"]
else:
appliance_name = "{} (custom)".format(appliance["name"])
item.setText(0, appliance_name)
#item.setText(1, appliance["category"].capitalize().replace("_", " "))
if "qemu" in appliance:
item.setText(1, "Qemu")
elif "iou" in appliance:
item.setText(1, "IOU")
elif "dynamips" in appliance:
item.setText(1, "Dynamips")
elif "docker" in appliance:
item.setText(1, "Docker")
else:
item.setText(1, "N/A")
item.setText(2, appliance["vendor_name"])
item.setData(0, QtCore.Qt.UserRole, appliance)
#item.setSizeHint(0, QtCore.QSize(32, 32))
item.setToolTip(0, self._get_tooltip_text(appliance))
Controller.instance().getSymbolIcon(appliance.get("symbol"), qpartial(self._setItemIcon, item),
fallback=":/symbols/" + appliance["category"] + ".svg")
self.uiAppliancesTreeWidget.sortByColumn(0, QtCore.Qt.AscendingOrder)
self.uiAppliancesTreeWidget.resizeColumnToContents(0)
if not appliance_filter:
self.uiAppliancesTreeWidget.collapseAll()
def initializePage(self, page_id):
"""
Initialize Wizard pages.
:param page_id: page identifier
"""
super().initializePage(page_id)
if self.page(page_id) == self.uiApplianceFromServerWizardPage:
self.button(QtWidgets.QWizard.CustomButton1).show()
self.setButtonText(QtWidgets.QWizard.FinishButton, "&Install")
self._get_appliances_from_server()
else:
self.button(QtWidgets.QWizard.CustomButton1).hide()
def cleanupPage(self, page_id):
"""
Restore button default settings on the first page.
"""
self.button(QtWidgets.QWizard.CustomButton1).hide()
self.setButtonText(QtWidgets.QWizard.FinishButton, "&Finish")
super().cleanupPage(page_id)
def validateCurrentPage(self):
"""
Validates if an appliance can be installed.
"""
if self.currentPage() == self.uiSelectTemplateSourceWizardPage and not Controller.instance().connected():
QtWidgets.QMessageBox.critical(self, "New template", "There is no connection to the server")
return False
elif self.currentPage() == self.uiApplianceFromServerWizardPage:
if not self.uiAppliancesTreeWidget.selectedItems():
QtWidgets.QMessageBox.critical(self, "New template", "Please select an appliance to install!")
return False
return True
def nextId(self):
"""
Wizard rules!
"""
current_id = self.currentId()
if self.page(current_id) == self.uiSelectTemplateSourceWizardPage and \
(self.uiImportApplianceFromFileRadioButton.isChecked() or self.uiCreateTemplateManuallyRadioButton.isChecked()):
self.done(True)
return super().nextId()
def done(self, result):
"""
This dialog is closed.
"""
super().done(result)
if result:
#ApplianceManager.instance().appliances_changed_signal.disconnect(self._appliancesChangedSlot)
from gns3.main_window import MainWindow
if self.currentPage() == self.uiApplianceFromServerWizardPage:
items = self.uiAppliancesTreeWidget.selectedItems()
for item in items:
f = tempfile.NamedTemporaryFile(mode="w+", suffix=".builtin.gns3a", delete=False)
json.dump(item.data(0, QtCore.Qt.UserRole), f)
f.close()
MainWindow.instance().loadPath(f.name)
try:
os.remove(f.name)
except OSError:
pass
elif self.uiCreateTemplateManuallyRadioButton.isChecked():
MainWindow.instance().preferencesActionSlot()
elif self.uiImportApplianceFromFileRadioButton.isChecked():
from gns3.main_window import MainWindow
MainWindow.instance().openApplianceActionSlot()

View File

@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 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/>.
"""
Dialog to show node information.
"""
from ..qt import QtWidgets
from ..ui.node_info_dialog_ui import Ui_NodeInfoDialog
class NodeInfoDialog(QtWidgets.QDialog, Ui_NodeInfoDialog):
"""
Node information dialog.
:param parent: parent widget
"""
def __init__(self, node, parent):
super().__init__(parent)
self.setupUi(self)
general_info = node.info()
usage_info = node.usage()
command_line_info = node.commandLine()
self.setWindowTitle(node.name())
# General tab
self.uiGeneralTextBrowser.setPlainText(general_info)
# Usage tab
if not usage_info:
usage_info = "No usage information has been provided for this node."
self.uiUsageTextBrowser.setPlainText(usage_info)
# Command line tab
if command_line_info is None:
command_line_info = "Command line information is not supported for this type of node."
elif len(command_line_info) == 0:
command_line_info = "Please start the node in order to get the command line information."
self.uiCommandLineTextBrowser.setPlainText(command_line_info)

View File

@@ -19,13 +19,14 @@
Dialog to configure and update node settings using widget pages.
"""
from .qt import QtCore, QtGui
from .ui.node_configurator_ui import Ui_NodeConfiguratorDialog
from ..qt import QtCore, QtGui, QtWidgets
from ..ui.node_properties_dialog_ui import Ui_NodePropertiesDialog
class NodeConfigurator(QtGui.QDialog, Ui_NodeConfiguratorDialog):
class NodePropertiesDialog(QtWidgets.QDialog, Ui_NodePropertiesDialog):
"""
Node configurator implementation.
Node properties implementation.
:param node_items: list of NodeItem instances
:param parent: parent widget
@@ -33,40 +34,44 @@ class NodeConfigurator(QtGui.QDialog, Ui_NodeConfiguratorDialog):
def __init__(self, node_items, parent):
QtGui.QDialog.__init__(self, parent)
super().__init__(parent)
self.setupUi(self)
self._node_items = node_items
self._parent_items = {}
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).setEnabled(False)
self.uiButtonBox.button(QtGui.QDialogButtonBox.Reset).setEnabled(False)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).setEnabled(False)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Reset).setEnabled(False)
self.previousItem = None
self.previousPage = None
# load the empty page widget by default
self.uiEmptyPageWidget = self.uiConfigStackedWidget.findChildren(QtGui.QWidget, "uiEmptyPageWidget")[0]
self.uiEmptyPageWidget = self.uiConfigStackedWidget.findChildren(QtWidgets.QWidget, "uiEmptyPageWidget")[0]
self.uiConfigStackedWidget.setCurrentWidget(self.uiEmptyPageWidget)
self._loadNodeItems()
self.splitter.setSizes([250, 600])
self._loadNodeItems()
self.uiNodesTreeWidget.itemClicked.connect(self.showConfigurationPageSlot)
def _loadNodeItems(self):
"""
Loads the nodes into the Node configurator QTreeWidget
Loads the nodes into the Node properties QTreeWidget
"""
# create the parent (group) items
for node_item in self._node_items:
if not node_item.node().initialized():
continue
# If something of one of the displayed nodes we reload everything
node_item.node().updated_signal.connect(self.resetSettings)
group_name = " {} group".format(str(node_item.node()))
parent = group_name
if not parent in self._parent_items:
item = QtGui.QTreeWidgetItem(self.uiNodesTreeWidget, [group_name])
if parent not in self._parent_items:
item = QtWidgets.QTreeWidgetItem(self.uiNodesTreeWidget, [group_name])
item.setIcon(0, QtGui.QIcon(node_item.node().defaultSymbol()))
item.setExpanded(True)
self._parent_items[parent] = item
@@ -76,11 +81,24 @@ class NodeConfigurator(QtGui.QDialog, Ui_NodeConfiguratorDialog):
if not node_item.node().initialized():
continue
parent = " {} group".format(str(node_item.node()))
item = ConfigurationPageItem(self._parent_items[parent], node_item)
ConfigurationPageItem(self._parent_items[parent], node_item)
# sort the tree
self.uiNodesTreeWidget.sortByColumn(0, QtCore.Qt.AscendingOrder)
if len(self._node_items) == 1:
parent = " {} group".format(str(node_item.node()))
item = self._parent_items[parent].child(0)
item.setSelected(True)
self.uiNodesTreeWidget.setCurrentItem(item)
self.showConfigurationPageSlot(item, 0)
self.splitter.setSizes([0, 600])
elif len(self._parent_items) > 0:
# We have multiple node we select the first group
item = next(iter(self._parent_items.values()))
self.uiNodesTreeWidget.setCurrentItem(item)
self.showConfigurationPageSlot(item, 0)
def showConfigurationPageSlot(self, item, column):
"""
Shows a configuration page widget.
@@ -117,11 +135,19 @@ class NodeConfigurator(QtGui.QDialog, Ui_NodeConfiguratorDialog):
self.uiConfigStackedWidget.setCurrentWidget(page)
if page != self.uiEmptyPageWidget:
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).setEnabled(True)
self.uiButtonBox.button(QtGui.QDialogButtonBox.Reset).setEnabled(True)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).setEnabled(True)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Reset).setEnabled(True)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Help).setEnabled(True)
else:
self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply).setEnabled(False)
self.uiButtonBox.button(QtGui.QDialogButtonBox.Reset).setEnabled(False)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).setEnabled(False)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Reset).setEnabled(False)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Help).setEnabled(False)
# hide the contextual help button if there is no help text
if page.whatsThis():
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Help).show()
else:
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Help).hide()
def on_uiButtonBox_clicked(self, button):
"""
@@ -131,15 +157,17 @@ class NodeConfigurator(QtGui.QDialog, Ui_NodeConfiguratorDialog):
"""
try:
if button == self.uiButtonBox.button(QtGui.QDialogButtonBox.Apply):
if button == self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply):
self.applySettings()
elif button == self.uiButtonBox.button(QtGui.QDialogButtonBox.Reset):
elif button == self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Reset):
self.resetSettings()
elif button == self.uiButtonBox.button(QtGui.QDialogButtonBox.Cancel):
QtGui.QDialog.reject(self)
elif button == self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Help):
self.showHelp()
elif button == self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Cancel):
QtWidgets.QDialog.reject(self)
else:
self.applySettings()
QtGui.QDialog.accept(self)
QtWidgets.QDialog.accept(self)
except ConfigurationError:
pass
@@ -160,12 +188,10 @@ class NodeConfigurator(QtGui.QDialog, Ui_NodeConfiguratorDialog):
# all children for that group
self.previousItem = None
self.previousNode = None
settings = item.child(0).settings().copy()
node = item.child(0).node()
page.saveSettings(settings, node, group=True)
settings = page.saveSettings({}, node, group=True)
for index in range(0, item.childCount()):
child = item.child(index)
#child.node().update(settings) #TODO: delete
child.settings().update(settings)
# update the nodes with the settings
@@ -199,8 +225,17 @@ class NodeConfigurator(QtGui.QDialog, Ui_NodeConfiguratorDialog):
child = item.child(index)
child.setSettings(child.node().settings().copy())
def showHelp(self):
"""
Show contextual help for the current page.
"""
page = self.uiConfigStackedWidget.currentWidget()
if page != self.uiEmptyPageWidget and page.whatsThis():
QtWidgets.QMessageBox.information(self, "{} help".format(page.windowTitle()), page.whatsThis().strip())
class ConfigurationPageItem(QtWidgets.QTreeWidgetItem):
class ConfigurationPageItem(QtGui.QTreeWidgetItem):
"""
Item for the QTreeWidget instance.
Store temporary node settings configured in a page widget.
@@ -212,7 +247,7 @@ class ConfigurationPageItem(QtGui.QTreeWidgetItem):
def __init__(self, parent, node_item):
self._node = node_item.node()
QtGui.QTreeWidgetItem.__init__(self, parent, [self._node.name()])
super().__init__(parent, [self._node.name()])
# return the configuration page widget used to configure the node.
self._page = self._node.configPage()
@@ -233,7 +268,7 @@ class ConfigurationPageItem(QtGui.QTreeWidgetItem):
def page(self):
"""
Returns the page widget to be displayed by the node configurator.
Returns the page widget to be displayed by the node properties dialog.
:returns: QWidget instance
"""
@@ -269,10 +304,11 @@ class ConfigurationPageItem(QtGui.QTreeWidgetItem):
class ConfigurationError(Exception):
"""
Exception to be raised when a configuration error occurs.
"""
def __init__(self):
Exception.__init__(self)
super().__init__()

View File

@@ -0,0 +1,190 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016 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/>.
"""
Display error to the user in an overlay popup
"""
import time
from gns3.qt import QtWidgets, QtCore, qslot
import logging
log = logging.getLogger(__name__)
MAX_ELEMENTS = 3
DISPLAY_DURATION = {
"CRITICAL": 120,
"ERROR": 120,
"WARNING": 20,
"INFO": 5
}
class NotifDialogHandler(logging.StreamHandler):
def __init__(self, dialog):
super().__init__()
self._dialog = dialog
self.setLevel(logging.INFO)
self._dialog.show()
def emit(self, record):
self._dialog.addNotif(record.levelname, record.getMessage())
class NotifDialog(QtWidgets.QWidget):
def __init__(self, parent):
super().__init__(parent)
self._notifs = []
self.setWindowFlags(QtCore.Qt.FramelessWindowHint |
QtCore.Qt.WindowDoesNotAcceptFocus |
QtCore.Qt.SubWindow)
# QtCore.Qt.Tool)
# QtCore.Qt.WindowStaysOnTopHint)
self.setAttribute(QtCore.Qt.WA_ShowWithoutActivating) # | QtCore.Qt.WA_TranslucentBackground)
self._layout = QtWidgets.QVBoxLayout()
self._timer = QtCore.QTimer()
self._timer.setInterval(1000)
self._timer.timeout.connect(self._refreshSlot)
self._timer.start()
for i in range(0, MAX_ELEMENTS):
l = QtWidgets.QLabel()
l.setAlignment(QtCore.Qt.AlignTop)
l.setWordWrap(True)
l.hide()
self._layout.addWidget(l)
self.setLayout(self._layout)
@qslot
def addNotif(self, level, message):
if not self.parent().settings().get("overlay_notifications", True):
return
# This unicode char prevent the wordwrap at /
message = message.replace("/", "\u2060/\u2060")
if len(self._notifs) == MAX_ELEMENTS:
self._notifs.pop(0)
self._notifs.append((level, message, time.time()))
self.update()
@qslot
def _refreshSlot(self):
"""
Hide the notifs after some delay
"""
notifs = []
for (i, (level, message, when)) in enumerate(self._notifs):
if when + DISPLAY_DURATION[level] > time.time():
notifs.append((level, message, when))
if notifs != self._notifs:
self._notifs = notifs
self.update()
elif len(notifs) > 0:
self.resize()
def update(self):
if len(self._notifs) == 0:
self.hide()
else:
for (i, (level, message, when)) in enumerate(self._notifs):
w = self._layout.itemAt(i).widget()
w.setText(message)
if level == "ERROR" or level == "CRITICAL":
w.setStyleSheet("""
color: black;
padding-left: 12px;
background-color: rgb(247, 205, 198);
border-left: 10px solid red;
""")
elif level == "WARNING":
w.setStyleSheet("""
color: black;
padding-left: 12px;
background-color: #f4f2b5;
border-left: 10px solid orange;
""")
elif level == "INFO":
w.setStyleSheet("""
color: black;
padding-left: 12px;
background-color: #cfffc9;
border-left: 10px solid green;
""")
w.show()
for i in range(i + 1, MAX_ELEMENTS):
w = self._layout.itemAt(i).widget()
w.hide()
self.resize()
self.show()
def resize(self):
x = self.parent().width() - self.width() - 10
y = 10
self.setGeometry(x, y, self.sizeHint().width(), self.sizeHint().height())
@qslot
def mousePressEvent(self, event):
self._notifs.clear()
self.update()
if __name__ == '__main__':
"""
A demo main for testing the features
"""
import sys
app = QtWidgets.QApplication(sys.argv)
logging.basicConfig(level=logging.INFO)
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
l1 = QtWidgets.QLabel()
l1.setText("Hello World")
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(l1)
self.setLayout(vbox)
self.setStyleSheet("background-color:blue;")
self._dialog = NotifDialog(self)
log.addHandler(NotifDialogHandler(self._dialog))
log.info("test")
def moveEvent(self, event):
log.error("An error")
log.info("An info with an url http://test")
log.warning("A warning with a long long long longlong longlong longlong longlong longlong longlong longlong long message")
self._dialog.update()
def resizeEvent(self, event):
self._dialog.update()
main = MainWindow()
main.setMinimumWidth(600)
main.setMinimumHeight(600)
main.show()
exit_code = app.exec_()

View File

@@ -0,0 +1,238 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Dialog to load module and built-in preference pages.
"""
from ..qt import QtCore, QtWidgets
from ..ui.preferences_dialog_ui import Ui_PreferencesDialog
from ..pages.server_preferences_page import ServerPreferencesPage
from ..pages.general_preferences_page import GeneralPreferencesPage
from ..pages.packet_capture_preferences_page import PacketCapturePreferencesPage
from ..pages.gns3_vm_preferences_page import GNS3VMPreferencesPage
from ..modules import MODULES
import logging
log = logging.getLogger(__name__)
class PreferencesDialog(QtWidgets.QDialog, Ui_PreferencesDialog):
"""
Preferences dialog implementation.
:param parent: parent widget
"""
def __init__(self, parent):
super().__init__(parent)
self.setupUi(self)
self._modified_pages = set()
# We adapt the max size to the screen resolution
# We need to manually do that otherwise on small screen the windows
# could be bigger than the screen instead of displaying scrollbars
height = QtWidgets.QDesktopWidget().screenGeometry().height() - 100
width = QtWidgets.QDesktopWidget().screenGeometry().width() - 100
# 980 is the default width
if self.width() > width:
self.resize(width, self.height())
# 680 is the default height
if self.height() > height:
self.resize(self.width(), height)
self.uiTreeWidget.currentItemChanged.connect(self._showPreferencesPageSlot)
self._applyButton = self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply)
self._applyButton.clicked.connect(self._applyPreferences)
self._applyButton.setEnabled(False)
self._applyButton.setStyleSheet("QPushButton:disabled {color: gray}")
self._items = []
self._loadPreferencePages()
# select the first available page
self.uiTreeWidget.setCurrentItem(self._items[0])
# set the maximum width based on the content of column 0
self.uiTreeWidget.setMaximumWidth(self.uiTreeWidget.sizeHintForColumn(0) + 10)
# Something has change?
self._modified_pages = set()
def _loadPreferencePages(self):
"""
Loads all preference pages (built-ins and from modules).
"""
# load built-in preference pages
pages = [
GeneralPreferencesPage,
ServerPreferencesPage,
GNS3VMPreferencesPage,
PacketCapturePreferencesPage,
]
for page in pages:
preferences_page = page(self)
preferences_page.loadPreferences()
name = preferences_page.windowTitle()
item = QtWidgets.QTreeWidgetItem(self.uiTreeWidget)
item.setText(0, name)
item.setData(0, QtCore.Qt.UserRole, preferences_page)
self.uiStackedWidget.addWidget(preferences_page)
self._items.append(item)
self._watchForChanges(preferences_page)
# load module preference pages
for module in MODULES:
preference_pages = module.preferencePages()
parent = self.uiTreeWidget
for cls in preference_pages:
preferences_page = cls()
preferences_page.setParent(self)
preferences_page.loadPreferences()
name = preferences_page.windowTitle()
item = QtWidgets.QTreeWidgetItem(parent)
item.setText(0, name)
item.setData(0, QtCore.Qt.UserRole, preferences_page)
self.uiStackedWidget.addWidget(preferences_page)
self._items.append(item)
if cls is preference_pages[0]:
parent = item
self._watchForChanges(preferences_page)
# expand all items by default
self.uiTreeWidget.expandAll()
def _watchForChanges(self, preferences_page):
"""
Connect all the widget of a page to check if something has change
"""
# Class name, changed signal
widget_to_watch = {
QtWidgets.QLineEdit: "textChanged",
QtWidgets.QPlainTextEdit: "textChanged",
# QtWidgets.QTreeWidget: "itemChanged",
QtWidgets.QTreeWidget: "itemDoubleClicked",
QtWidgets.QComboBox: "currentIndexChanged",
QtWidgets.QSpinBox: "valueChanged",
QtWidgets.QAbstractButton: "pressed"
}
for widget, signal in widget_to_watch.items():
for children in preferences_page.findChildren(widget):
getattr(children, signal).connect(self._preferenceChangeSlot)
def _preferenceChangeSlot(self, *args):
"""
Called when something change in the preference dialog
"""
# Found the page with the change
widget = sender = self.sender()
while widget.parent() != self.uiStackedWidget:
widget = widget.parent()
if self.addModifiedPage(widget):
log.debug("%s value has changed", sender.objectName())
def addModifiedPage(self, widget):
"""
:returns: True is the page is initialized and element added
"""
# The widget can trigger signal before the end of init due to async api call
if not hasattr(widget, 'pageInitialized') or widget.pageInitialized():
self._applyButton.setEnabled(True)
self._modified_pages.add(widget)
return True
return False
def _showPreferencesPageSlot(self, current, previous):
"""
Shows a preference page in the current dialog.
:param current: current preference page widget
:param previous: ignored
"""
if current is None:
current = previous
preferences_page = current.data(0, QtCore.Qt.UserRole)
accessible_name = preferences_page.accessibleName()
if accessible_name:
self.uiTitleLabel.setText(accessible_name)
else:
name = preferences_page.windowTitle()
self.uiTitleLabel.setText("{} preferences".format(name))
index = self.uiStackedWidget.indexOf(preferences_page)
widget = self.uiStackedWidget.widget(index)
#self.uiStackedWidget.setMinimumSize(widget.size()) # FIXME: this seems to not work on Windows and OSX
#self.uiStackedWidget.resize(widget.size())
self.uiStackedWidget.setCurrentIndex(index)
for index in range(0, self.uiStackedWidget.count()):
page = self.uiStackedWidget.widget(index)
if self.uiStackedWidget.currentIndex() == index:
page.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
else:
page.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
def _applyPreferences(self):
"""
Saves all the preferences.
"""
success = True
for preferences_page in list(self._modified_pages):
ok = preferences_page.savePreferences()
# if page.savePreferences() returns None, assume success
if ok is not None and not ok:
success = False
if success:
self._applyButton.setEnabled(False)
self._modified_pages = set()
return success
def reject(self):
"""
Closes this dialog.
"""
if len(self._modified_pages) > 0:
# Get the title of pages with modifications
pages_title = ', '.join([page.windowTitle() for page in self._modified_pages])
reply = QtWidgets.QMessageBox.warning(self,
"Preferences",
"You have unsaved preferences in {}.\n\nContinue without saving?".format(pages_title),
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.No:
return
QtWidgets.QDialog.reject(self)
def accept(self):
"""
Saves the preferences and closes this dialog.
"""
if self._applyPreferences():
QtWidgets.QDialog.accept(self)

View File

@@ -0,0 +1,106 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016 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 os
import sys
import shutil
from gns3.qt import QtWidgets
from gns3.local_config import LocalConfig
from gns3.ui.profile_select_dialog_ui import Ui_ProfileSelectDialog
from gns3.version import __version_info__
import logging
log = logging.getLogger(__name__)
class ProfileSelectDialog(QtWidgets.QDialog, Ui_ProfileSelectDialog):
"""
This dialog allow user to choose a profile of settings
"""
def __init__(self, parent=None):
if parent is None:
self._main = QtWidgets.QMainWindow()
self._main.hide()
parent = self._main
super().__init__(parent)
self.setupUi(self)
self.uiNewPushButton.clicked.connect(self._newPushButtonSlot)
self.uiDeletePushButton.clicked.connect(self._deletePushButtonSlot)
# Center on screen
screen = QtWidgets.QApplication.desktop().screenGeometry()
self.move(screen.center() - self.rect().center())
version = "{}.{}".format(__version_info__[0], __version_info__[1])
if sys.platform.startswith("win"):
appdata = os.path.expandvars("%APPDATA%")
path = os.path.join(appdata, "GNS3", version)
else:
home = os.path.expanduser("~")
path = os.path.join(home, ".config", "GNS3", version)
self.profiles_path = os.path.join(path, "profiles")
self.uiShowAtStartupCheckBox.setChecked(LocalConfig.instance().multiProfiles())
self._refresh()
def _refresh(self):
self.uiProfileSelectComboBox.clear()
self.uiProfileSelectComboBox.addItem("default")
try:
if os.path.exists(self.profiles_path):
for profile in sorted(os.listdir(self.profiles_path)):
if not profile.startswith("."):
self.uiProfileSelectComboBox.addItem(profile)
except OSError:
pass
def profile(self):
return self.uiProfileSelectComboBox.currentText()
def accept(self):
LocalConfig.instance().setMultiProfiles(self.uiShowAtStartupCheckBox.isChecked())
super().accept()
def _newPushButtonSlot(self):
profile, ok = QtWidgets.QInputDialog.getText(self, "New profile", "Profile name:")
if ok:
self.uiProfileSelectComboBox.addItem(profile)
self.uiProfileSelectComboBox.setCurrentText(profile)
self.accept()
def _deletePushButtonSlot(self):
profile = self.uiProfileSelectComboBox.currentText()
if profile == "default":
QtWidgets.QMessageBox.critical(self, "Delete profile", "The default profile cannot be deleted")
else:
try:
shutil.rmtree(os.path.join(self.profiles_path, profile))
self._refresh()
except (OSError, PermissionError) as e:
QtWidgets.QMessageBox.critical(self, "Cannot delete profile", str(e))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dialog = ProfileSelectDialog()
dialog.show()
exit_code = app.exec_()

View File

@@ -0,0 +1,318 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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 os
from ..qt import QtCore, QtGui, QtWidgets, qslot, sip_is_deleted
from ..ui.project_dialog_ui import Ui_ProjectDialog
from ..controller import Controller
from ..topology import Topology
import logging
log = logging.getLogger(__name__)
class ProjectDialog(QtWidgets.QDialog, Ui_ProjectDialog):
"""
New project dialog.
"""
def __init__(self, parent, default_project_name="untitled", show_open_options=True):
"""
:param parent: parent widget.
:param default_project_name: Project name by default
:param show_open_options: If true allow to open a project from the dialog
otherwise it's just for create a project
"""
super().__init__(parent)
self.setupUi(self)
self._main_window = parent
self._project_settings = {}
self.uiNameLineEdit.setText(default_project_name)
self.uiLocationLineEdit.setText(os.path.join(Topology.instance().projectsDirPath(), default_project_name))
self.uiNameLineEdit.textEdited.connect(self._projectNameSlot)
self.uiLocationBrowserToolButton.clicked.connect(self._projectPathSlot)
self.uiSettingsPushButton.clicked.connect(self._settingsClickedSlot)
if show_open_options:
self.uiOpenProjectPushButton.clicked.connect(self._openProjectActionSlot)
self._addRecentFilesMenu()
else:
self.uiOpenProjectGroupBox.hide()
self.uiProjectTabWidget.removeTab(1)
# If the controller is remote we hide option for local file system
if Controller.instance().isRemote():
self.uiLocationLabel.setVisible(False)
self.uiLocationLineEdit.setVisible(False)
self.uiLocationBrowserToolButton.setVisible(False)
self.uiOpenProjectPushButton.setVisible(False)
self.uiProjectsTreeWidget.itemDoubleClicked.connect(self._projectsTreeWidgetDoubleClickedSlot)
self.uiDeleteProjectButton.clicked.connect(self._deleteProjectSlot)
self.uiDuplicateProjectPushButton.clicked.connect(self._duplicateProjectSlot)
self.uiRefreshProjectsPushButton.clicked.connect(Controller.instance().refreshProjectList)
Controller.instance().project_list_updated_signal.connect(self._updateProjectListSlot)
self._updateProjectListSlot()
Controller.instance().refreshProjectList()
def _settingsClickedSlot(self):
"""
When the user click on the settings button
"""
self.reject()
self._main_window.preferencesActionSlot()
def _projectsTreeWidgetDoubleClickedSlot(self, item, column):
self.done(True)
@qslot
def _deleteProjectSlot(self, *args):
if len(self.uiProjectsTreeWidget.selectedItems()) == 0:
QtWidgets.QMessageBox.critical(self, "Delete project", "No project selected")
return
projects_to_delete = set()
for project in self.uiProjectsTreeWidget.selectedItems():
if sip_is_deleted(project):
continue
project_id = project.data(0, QtCore.Qt.UserRole)
project_name = project.data(1, QtCore.Qt.UserRole)
reply = QtWidgets.QMessageBox.warning(self,
"Delete project",
'Delete project "{}"?\nThis cannot be reverted.'.format(project_name),
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
projects_to_delete.add(project_id)
for project_id in projects_to_delete:
Controller.instance().deleteProject(project_id)
def _duplicateProjectSlot(self):
if len(self.uiProjectsTreeWidget.selectedItems()) == 0:
QtWidgets.QMessageBox.critical(self, "Duplicate project", "No project selected")
return
if len(self.uiProjectsTreeWidget.selectedItems()) > 1:
QtWidgets.QMessageBox.critical(self, "Duplicate project", "Please select only one project to duplicate")
return
for project in self.uiProjectsTreeWidget.selectedItems():
project_id = project.data(0, QtCore.Qt.UserRole)
project_name = project.data(1, QtCore.Qt.UserRole)
new_project_name = project_name + "-1"
existing_project_name = [p["name"] for p in Controller.instance().projects()]
i = 1
while new_project_name in existing_project_name:
new_project_name = "{}-{}".format(project_name, i)
i += 1
name, reply = QtWidgets.QInputDialog.getText(self,
"Duplicate project",
'Duplicate project "{}"?.'.format(project_name),
QtWidgets.QLineEdit.Normal,
new_project_name)
name = name.strip()
if reply and len(name) > 0:
reset_mac_addresses = self.uiResetMacAddressesCheckBox.isChecked()
if Controller.instance().isRemote():
Controller.instance().post("/projects/{project_id}/duplicate".format(project_id=project_id),
self._duplicateCallback,
body={"name": name, "reset_mac_addresses": reset_mac_addresses},
progressText="Duplicating project '{}'...".format(name),
timeout=None)
else:
project_location = os.path.join(Topology.instance().projectsDirPath(), name)
Controller.instance().post("/projects/{project_id}/duplicate".format(project_id=project_id),
self._duplicateCallback,
body={"name": name, "path": project_location, "reset_mac_addresses": reset_mac_addresses},
progressText="Duplicating project '{}'...".format(name),
timeout=None)
def _duplicateCallback(self, result, error=False, **kwargs):
if error:
log.error("Error while duplicating project: {}".format(result["message"]))
return
Controller.instance().refreshProjectList()
@qslot
def _updateProjectListSlot(self, *args):
self.uiProjectsTreeWidget.clear()
self.uiDeleteProjectButton.setEnabled(False)
self.uiProjectsTreeWidget.setUpdatesEnabled(False)
items = []
for project in Controller.instance().projects():
path = os.path.join(project["path"], project["filename"])
item = QtWidgets.QTreeWidgetItem([project["name"], project["status"], path])
item.setData(0, QtCore.Qt.UserRole, project["project_id"])
item.setData(1, QtCore.Qt.UserRole, project["name"])
item.setData(2, QtCore.Qt.UserRole, path)
items.append(item)
self.uiProjectsTreeWidget.addTopLevelItems(items)
if len(Controller.instance().projects()):
self.uiDeleteProjectButton.setEnabled(True)
self.uiProjectsTreeWidget.header().setResizeContentsPrecision(100) # How many row is checked for the resize for performance reason
self.uiProjectsTreeWidget.resizeColumnToContents(0)
self.uiProjectsTreeWidget.resizeColumnToContents(1)
self.uiProjectsTreeWidget.resizeColumnToContents(2)
self.uiProjectsTreeWidget.sortItems(0, QtCore.Qt.AscendingOrder)
self.uiProjectsTreeWidget.setUpdatesEnabled(True)
def keyPressEvent(self, e):
"""
Event handler in order to properly handle escape.
"""
if e.key() == QtCore.Qt.Key_Escape:
self.close()
def _projectNameSlot(self, text):
project_dir = Topology.instance().projectsDirPath()
if os.path.dirname(self.uiLocationLineEdit.text()) == project_dir:
self.uiLocationLineEdit.setText(os.path.join(project_dir, text))
def _projectPathSlot(self):
"""
Slot to select the a new project location.
"""
path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Project location", os.path.join(Topology.instance().projectsDirPath(),
self.uiNameLineEdit.text()))
if path:
self.uiNameLineEdit.setText(os.path.basename(path))
self.uiLocationLineEdit.setText(path)
def getProjectSettings(self):
return self._project_settings
def _menuTriggeredSlot(self, action):
"""
Closes this dialog when a recent project
has been opened.
:param action: ignored.
"""
self.reject()
def _openProjectActionSlot(self):
"""
Opens a project and closes this dialog.
"""
self._main_window.openProjectActionSlot()
self.reject()
def _addRecentFilesMenu(self):
"""
Add recent projects in a menu.
"""
menu = QtWidgets.QMenu(parent=self)
if Controller.instance().isRemote():
for action in self._main_window.recent_project_actions:
menu.addAction(action)
else:
for action in self._main_window.recent_file_actions:
menu.addAction(action)
menu.triggered.connect(self._menuTriggeredSlot)
self.uiRecentProjectsPushButton.setMenu(menu)
def _overwriteProjectCallback(self, result, error=False, **kwargs):
if error:
# A 404 could arrive if someone else as deleted the project
if "status" not in result or result["status"] != 404:
return
elif "message" in result:
QtWidgets.QMessageBox.critical(self,
"New Project",
"Error while overwrite project: {}".format(result["message"]))
Controller.instance().refreshProjectList()
self.done(True)
def _newProject(self):
self._project_settings["project_name"] = self.uiNameLineEdit.text().strip()
if Controller.instance().isRemote():
self._project_settings.pop("project_path", None)
self._project_settings.pop("project_files_dir", None)
else:
project_location = self.uiLocationLineEdit.text().strip()
if not project_location:
QtWidgets.QMessageBox.critical(self, "New project", "Project location is empty")
return False
self._project_settings["project_path"] = os.path.join(project_location, self._project_settings["project_name"] + ".gns3")
self._project_settings["project_files_dir"] = project_location
if len(self._project_settings["project_name"]) == 0:
QtWidgets.QMessageBox.critical(self, "New project", "Project name is empty")
return False
for existing_project in Controller.instance().projects():
if self._project_settings["project_name"] == existing_project["name"] \
and ("project_files_dir" in self._project_settings and self._project_settings["project_files_dir"] == existing_project["path"]):
if existing_project["status"] == "opened":
QtWidgets.QMessageBox.critical(self,
"New project",
'Project "{}" is opened, it cannot be overwritten'.format(self._project_settings["project_name"]))
return False
reply = QtWidgets.QMessageBox.warning(self,
"New project",
'Project "{}" already exists in location "{}", overwrite it?'.format(existing_project["name"], existing_project["path"]),
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
Controller.instance().deleteProject(existing_project["project_id"], self._overwriteProjectCallback)
# In all cases we cancel the new project and if project success to delete
# we will call done again
return False
return True
def done(self, result):
if result:
if self.uiProjectTabWidget.currentIndex() == 0:
if not self._newProject():
return
else:
current = self.uiProjectsTreeWidget.currentItem()
if current is None:
QtWidgets.QMessageBox.critical(self, "Open project", "No project selected")
return
self._project_settings["project_id"] = current.data(0, QtCore.Qt.UserRole)
self._project_settings["project_name"] = current.data(1, QtCore.Qt.UserRole)
super().done(result)

View File

@@ -0,0 +1,146 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 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 sys
import os
import datetime
from gns3.qt import QtCore, QtWidgets
from ..local_server import LocalServer
from ..utils.progress_dialog import ProgressDialog
from ..utils.export_project_worker import ExportProjectWorker
from ..ui.export_project_wizard_ui import Ui_ExportProjectWizard
import logging
log = logging.getLogger(__name__)
class ExportProjectWizard(QtWidgets.QWizard, Ui_ExportProjectWizard):
"""
Export project wizard.
"""
def __init__(self, project, parent):
super().__init__(parent)
self.setupUi(self)
self._project = project
self._path = None
self.setWizardStyle(QtWidgets.QWizard.ModernStyle)
if sys.platform.startswith("darwin"):
# we want to see the cancel button on OSX
self.setOptions(QtWidgets.QWizard.NoDefaultButton)
self.uiCompressionComboBox.addItem("None", "none")
self.uiCompressionComboBox.addItem("Zip compression (deflate)", "zip")
self.uiCompressionComboBox.addItem("Bzip2 compression", "bzip2")
self.uiCompressionComboBox.addItem("Lzma compression", "lzma")
# set zip compression by default
self.uiCompressionComboBox.setCurrentIndex(1)
self.helpRequested.connect(self._showHelpSlot)
self.uiPathBrowserToolButton.clicked.connect(self._pathBrowserSlot)
self._loadReadme()
def _loadReadme(self):
self._project.get("/files/README.txt", self._loadedReadme)
def _loadedReadme(self, result, error=False, raw_body=None, context={}, **kwargs):
if not error:
self.uiReadmeTextEdit.setPlainText(raw_body.decode("utf-8", errors="replace"))
else:
readme_text = "Project: '{}' created on {}\nAuthor: John Doe <john.doe@example.com>\n\nNo project description was given".format(self._project.name(), datetime.date.today())
self.uiReadmeTextEdit.setPlainText(readme_text)
def _pathBrowserSlot(self):
directory = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DocumentsLocation)
if len(directory) == 0:
directory = LocalServer.instance().localServerSettings()["projects_path"]
path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Export portable project", directory,
"GNS3 Portable Project (*.gns3project *.gns3p)",
"GNS3 Portable Project (*.gns3project *.gns3p)")
if path is None or len(path) == 0:
return
self.uiPathLineEdit.setText(path)
def _showHelpSlot(self):
include_image_help = """Including base images means additional images will not be requested to
import the project on another computer, however the resulting file will be much bigger.
Also, you are responsible to check if you have the right to distribute the image(s) as part of the project.
"""
QtWidgets.QMessageBox.information(self, "Help about export a project", include_image_help)
def validateCurrentPage(self):
"""
Validates if the project can be exported.
"""
if self.currentPage() == self.uiExportOptionsWizardPage:
path = self.uiPathLineEdit.text().strip()
if not path:
QtWidgets.QMessageBox.critical(self, "Export project", "Please select a path where to export the project")
return False
if not path.endswith(".gns3project") and not path.endswith(".gns3p"):
path += ".gns3project"
try:
open(path, 'wb+').close()
except OSError as e:
QtWidgets.QMessageBox.critical(self, "Export project", "Cannot export project to '{}': {}".format(path, e))
return False
self._path = path
elif self.currentPage() == self.uiProjectReadmeWizardPage:
text = self.uiReadmeTextEdit.toPlainText().strip()
if text:
self._project.post("/files/README.txt", self._saveReadmeCallback, body=text)
return True
def _saveReadmeCallback(self, result, error=False, **kwargs):
if error:
QtWidgets.QMessageBox.critical(self, "Export project", "Could not created readme file")
def done(self, result):
"""
This dialog is closed.
"""
if result:
if self.uiIncludeImagesCheckBox.isChecked():
include_images = "yes"
else:
include_images = "no"
if self.uiIncludeSnapshotsCheckBox.isChecked():
include_snapshots = "yes"
else:
include_snapshots = "no"
if self.uiResetMacAddressesCheckBox.isChecked():
reset_mac_addresses = "yes"
else:
reset_mac_addresses = "no"
compression = self.uiCompressionComboBox.currentData()
export_worker = ExportProjectWorker(self._project, self._path, include_images, include_snapshots, reset_mac_addresses, compression)
progress_dialog = ProgressDialog(export_worker, "Exporting project", "Exporting portable project files...", "Cancel", parent=self, create_thread=False)
progress_dialog.show()
progress_dialog.exec_()
super().done(result)

View File

@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 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 copy
from gns3.qt import QtWidgets, QtCore, qpartial
from gns3.ui.project_welcome_dialog_ui import Ui_ProjectWelcomeDialog
import logging
log = logging.getLogger(__name__)
class ProjectWelcomeDialog(QtWidgets.QDialog, Ui_ProjectWelcomeDialog):
"""
This dialog shows when project is imported and global variables assigned to the project are missing.
"""
def __init__(self, parent, project):
super().__init__(parent)
self._project = project
self.setupUi(self)
self.uiOkButton.clicked.connect(self._okButtonClickedSlot)
self.gridLayout.setAlignment(QtCore.Qt.AlignTop)
self.label.setOpenExternalLinks(True)
self._variables = self._getVariables(project)
self._loadReadme()
self._addMisingVariablesEdits()
def _getVariables(self, project):
variables = copy.copy(self._project.variables())
if variables is None:
variables = []
return variables
def _addMisingVariablesEdits(self):
#TODO: refactor this to use a QListWidget
missing = [v for v in self._variables if v.get("name") and v.get("value", "").strip() == ""]
for i, variable in enumerate(missing, start=0):
nameLabel = QtWidgets.QLabel()
nameLabel.setText(variable.get("name") + ":")
self.gridLayout.addWidget(nameLabel, i, 0)
valueEdit = QtWidgets.QLineEdit()
valueEdit.setText(variable.get("value", ""))
valueEdit.textChanged.connect(qpartial(self.onValueChange, variable))
self.gridLayout.addWidget(valueEdit, i, 1)
def _loadReadme(self):
self._project.get("/files/README.txt", self._loadedReadme)
def _loadedReadme(self, result, error=False, raw_body=None, context={}, **kwargs):
if not error:
self.label.setText(raw_body.decode("utf-8"))
def onValueChange(self, variable, text):
variable["value"] = text
def _okButtonClickedSlot(self):
missing = [v for v in self._variables if v.get("name") and v.get("value", "").strip() == ""]
if len(missing) > 0:
reply = QtWidgets.QMessageBox.warning(self,
"Missing values",
"Are you sure you want to continue without providing missing values?",
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.No:
return
self._project.setVariables(self._variables)
self._project.update()
self.accept()

View File

@@ -0,0 +1,439 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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 sys
import os
import shutil
from gns3.qt import QtCore, QtWidgets, QtGui, QtNetwork, qslot
from gns3.controller import Controller
from gns3.local_server import LocalServer
from gns3.utils.interfaces import interfaces
from ..settings import DEFAULT_LOCAL_SERVER_HOST
from ..ui.setup_wizard_ui import Ui_SetupWizard
from ..version import __version__
import logging
log = logging.getLogger(__name__)
class SetupWizard(QtWidgets.QWizard, Ui_SetupWizard):
"""
Base class for VM wizard.
"""
def __init__(self, parent):
super().__init__(parent)
self.setupUi(self)
self.adjustSize()
self._gns3_vm_settings = {
"enable": True,
"headless": False,
"when_exit": "stop",
"engine": "vmware",
"allocate_vcpus_ram": True,
"vcpus": 1,
"ram": 2048,
"vmname": "GNS3 VM",
"port": 80
}
self.setWizardStyle(QtWidgets.QWizard.ModernStyle)
if sys.platform.startswith("darwin"):
# we want to see the cancel button on OSX
self.setOptions(QtWidgets.QWizard.NoDefaultButton)
self.uiLocalServerToolButton.clicked.connect(self._localServerBrowserSlot)
self.uiGNS3VMDownloadLinkUrlLabel.setText("")
self.uiRefreshPushButton.clicked.connect(self._refreshVMListSlot)
self.uiVmwareRadioButton.clicked.connect(self._listVMwareVMsSlot)
self.uiVirtualBoxRadioButton.clicked.connect(self._listVirtualBoxVMsSlot)
settings = parent.settings()
self.uiShowCheckBox.setChecked(settings["hide_setup_wizard"])
# by default all radio buttons are unchecked
self.uiVmwareRadioButton.setAutoExclusive(False)
self.uiVirtualBoxRadioButton.setAutoExclusive(False)
self.uiVmwareRadioButton.setChecked(False)
self.uiVirtualBoxRadioButton.setChecked(False)
# Mandatory fields
self.uiLocalServerWizardPage.registerField("path*", self.uiLocalServerPathLineEdit)
# load all available addresses
for address in QtNetwork.QNetworkInterface.allAddresses():
if address.protocol() in [QtNetwork.QAbstractSocket.IPv4Protocol, QtNetwork.QAbstractSocket.IPv6Protocol]:
address_string = address.toString()
if address_string.startswith("169.254") or address_string.startswith("fe80"):
# ignore link-local addresses, could not use https://doc.qt.io/qt-5/qhostaddress.html#isLinkLocal
# because it was introduced in Qt 5.11
continue
self.uiLocalServerHostComboBox.addItem(address_string, address_string)
self.uiLocalServerHostComboBox.addItem("localhost", "localhost") # local host
self.uiLocalServerHostComboBox.addItem("::", "::") # all IPv6 addresses
self.uiLocalServerHostComboBox.addItem("0.0.0.0", "0.0.0.0") # all IPv4 addresses
if sys.platform.startswith("linux"):
self.uiLocalRadioButton.setChecked(True)
self.uiLocalLabel.setText("Dependencies like Dynamips and Qemu must be manually installed")
Controller.instance().connected_signal.connect(self._refreshLocalServerStatusSlot)
Controller.instance().connection_failed_signal.connect(self._refreshLocalServerStatusSlot)
def _localServerBrowserSlot(self):
"""
Slot to open a file browser and select a local server.
"""
filter = ""
if sys.platform.startswith("win"):
filter = "Executable (*.exe);;All files (*.*)"
server_path = shutil.which("gns3server")
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Select the local server", server_path, filter)
if not path:
return
self.uiLocalServerPathLineEdit.setText(path)
def _listVMwareVMsSlot(self):
"""
Slot to refresh the VMware VMs list.
"""
download_url = "https://github.com/GNS3/gns3-gui/releases/download/v{version}/GNS3.VM.VMware.Workstation.{version}.zip".format(version=__version__)
self.uiGNS3VMDownloadLinkUrlLabel.setText('The GNS3 VM can <a href="{download_url}">downloaded here</a>.<br>Import the VM in your virtualization software and hit refresh.'.format(download_url=download_url))
self.uiVirtualBoxRadioButton.setChecked(False)
from gns3.modules import VMware
settings = VMware.instance().settings()
if not os.path.exists(settings["vmrun_path"]):
QtWidgets.QMessageBox.critical(self, "VMware", "VMware vmrun tool could not be found, VMware or the VIX API (required for VMware player) is probably not installed. You can download it from https://customerconnect.vmware.com/downloads/details?downloadGroup=PLAYER-1400-VIX1170&productId=687. After installation you need to restart GNS3.")
return
self._refreshVMListSlot()
def _listVirtualBoxVMsSlot(self):
"""
Slot to refresh the VirtualBox VMs list.
"""
download_url = "https://github.com/GNS3/gns3-gui/releases/download/v{version}/GNS3.VM.VirtualBox.{version}.zip".format(version=__version__)
self.uiGNS3VMDownloadLinkUrlLabel.setText('If you don\'t have the GNS3 Virtual Machine you can <a href="{download_url}">download it here</a>.<br>And import the VM in the virtualization software and hit refresh.'.format(download_url=download_url))
self.uiVmwareRadioButton.setChecked(False)
from gns3.modules import VirtualBox
settings = VirtualBox.instance().settings()
if not os.path.exists(settings["vboxmanage_path"]):
QtWidgets.QMessageBox.critical(self, "VirtualBox", "VBoxManage could not be found, VirtualBox is probably not installed. After installation you need to restart GNS3.")
return
self._refreshVMListSlot()
def _setPreferencesPane(self, dialog, name):
"""
Finds the first child of the QTreeWidgetItem name.
:param dialog: PreferencesDialog instance
:param name: QTreeWidgetItem name
:returns: current QWidget
"""
pane = dialog.uiTreeWidget.findItems(name, QtCore.Qt.MatchFixedString)[0]
child_pane = pane.child(0)
dialog.uiTreeWidget.setCurrentItem(child_pane)
return dialog.uiStackedWidget.currentWidget()
def _getSettingsCallback(self, result, error=False, **kwargs):
if error:
if "message" in result:
log.error("Error while get gettings: {}".format(result["message"]))
return
self._gns3_vm_settings = result
def initializePage(self, page_id):
"""
Initialize Wizard pages.
:param page_id: page identifier
"""
super().initializePage(page_id)
if self.page(page_id) == self.uiServerWizardPage:
Controller.instance().setDisplayError(False)
Controller.instance().get("/gns3vm", self._getSettingsCallback)
elif self.page(page_id) == self.uiVMWizardPage:
if self._GNS3VMSettings()["engine"] == "vmware":
self.uiVmwareRadioButton.setChecked(True)
self._listVMwareVMsSlot()
elif self._GNS3VMSettings()["engine"] == "virtualbox":
self.uiVirtualBoxRadioButton.setChecked(True)
self._listVirtualBoxVMsSlot()
self.uiCPUSpinBox.setValue(self._GNS3VMSettings()["vcpus"])
self.uiRAMSpinBox.setValue(self._GNS3VMSettings()["ram"])
elif self.page(page_id) == self.uiLocalServerWizardPage:
local_server_settings = LocalServer.instance().localServerSettings()
self.uiLocalServerPathLineEdit.setText(local_server_settings["path"])
index = self.uiLocalServerHostComboBox.findData(local_server_settings["host"])
if index != -1:
self.uiLocalServerHostComboBox.setCurrentIndex(index)
else:
if self.uiVMRadioButton.isChecked():
# Try to bind with the IP address allocated for VMnet1
for interface in interfaces():
if "vmnet1" in interface["name"].lower():
index = self.uiLocalServerHostComboBox.findText(interface["ip_address"])
break
else:
index = self.uiLocalServerHostComboBox.findText(DEFAULT_LOCAL_SERVER_HOST)
if index != -1:
self.uiLocalServerHostComboBox.setCurrentIndex(index)
self.uiLocalServerPortSpinBox.setValue(local_server_settings["port"])
elif self.page(page_id) == self.uiRemoteControllerWizardPage:
local_server_settings = LocalServer.instance().localServerSettings()
if local_server_settings["host"] is None:
self.uiRemoteMainServerHostLineEdit.setText(DEFAULT_LOCAL_SERVER_HOST)
self.uiRemoteMainServerAuthCheckBox.setChecked(False)
self.uiRemoteMainServerUserLineEdit.setText("")
self.uiRemoteMainServerPasswordLineEdit.setText("")
else:
self.uiRemoteMainServerHostLineEdit.setText(local_server_settings["host"])
self.uiRemoteMainServerAuthCheckBox.setChecked(local_server_settings["auth"])
self.uiRemoteMainServerUserLineEdit.setText(local_server_settings["user"])
self.uiRemoteMainServerPasswordLineEdit.setText(local_server_settings["password"])
self.uiRemoteMainServerPortSpinBox.setValue(local_server_settings["port"])
elif self.page(page_id) == self.uiLocalServerStatusWizardPage:
self._refreshLocalServerStatusSlot()
elif self.page(page_id) == self.uiSummaryWizardPage:
self.uiSummaryTreeWidget.clear()
if self.uiLocalRadioButton.isChecked():
local_server_settings = LocalServer.instance().localServerSettings()
self._addSummaryEntry("Server type:", "Local")
self._addSummaryEntry("Path:", local_server_settings["path"])
self._addSummaryEntry("Host:", local_server_settings["host"])
self._addSummaryEntry("Port:", str(local_server_settings["port"]))
elif self.uiRemoteControllerRadioButton.isChecked():
local_server_settings = LocalServer.instance().localServerSettings()
self._addSummaryEntry("Server type:", "Remote")
self._addSummaryEntry("Host:", local_server_settings["host"])
self._addSummaryEntry("Port:", str(local_server_settings["port"]))
self._addSummaryEntry("User:", local_server_settings["user"])
else:
self._addSummaryEntry("Server type:", "GNS3 Virtual Machine")
self._addSummaryEntry("VM engine:", self._GNS3VMSettings()["engine"].capitalize())
self._addSummaryEntry("VM name:", self._GNS3VMSettings()["vmname"])
self._addSummaryEntry("VM vCPUs:", str(self._GNS3VMSettings()["vcpus"]))
self._addSummaryEntry("VM RAM:", str(self._GNS3VMSettings()["ram"]) + " MB")
@qslot
def _refreshLocalServerStatusSlot(self):
"""
Refresh the local server status page
"""
self.uiLocalServerTextEdit.clear()
if Controller.instance().connected():
self.uiLocalServerTextEdit.setText("Connection to the local GNS3 server has been successful!")
Controller.instance().get("/gns3vm", self._getSettingsCallback)
elif Controller.instance().connecting():
self.uiLocalServerTextEdit.setText("Please wait connection to the GNS3 server...")
else:
local_server_settings = LocalServer.instance().localServerSettings()
self.uiLocalServerTextEdit.setText("Connection to local server failed. Please try one of the following:\n\n- Make sure GNS3 is allowed to run by your firewall.\n- Go back and try to change the server host binding and/or the port\n- Check with a browser if you can connect to {protocol}://{host}:{port}.\n- Try to run {path} in a terminal to see if you have an error.".format(protocol=local_server_settings["protocol"], host=local_server_settings["host"], port=local_server_settings["port"], path=local_server_settings["path"]))
def _GNS3VMSettings(self):
return self._gns3_vm_settings
def _setGNS3VMSettings(self, settings):
Controller.instance().put("/gns3vm", self._saveSettingsCallback, settings, timeout=60 * 5)
def _saveSettingsCallback(self, result, error=False, **kwargs):
if error:
if "message" in result:
QtWidgets.QMessageBox.critical(self, "Save settings", "Error while saving settings: {}".format(result["message"]))
return
def _addSummaryEntry(self, name, value):
item = QtWidgets.QTreeWidgetItem(self.uiSummaryTreeWidget, [name, value])
item.setText(0, name)
font = item.font(0)
font.setBold(True)
item.setFont(0, font)
def validateCurrentPage(self):
"""
Validates the settings.
"""
Controller.instance().setDisplayError(True)
if self.currentPage() == self.uiVMWizardPage:
vmname = self.uiVMListComboBox.currentText()
if vmname:
# save the GNS3 VM settings
vm_settings = self._GNS3VMSettings()
vm_settings["enable"] = True
vm_settings["vmname"] = vmname
if self.uiVmwareRadioButton.isChecked():
vm_settings["engine"] = "vmware"
elif self.uiVirtualBoxRadioButton.isChecked():
vm_settings["engine"] = "virtualbox"
# set the vCPU count and RAM
vpcus = self.uiCPUSpinBox.value()
ram = self.uiRAMSpinBox.value()
if ram < 1024:
QtWidgets.QMessageBox.warning(self, "GNS3 VM memory", "It is recommended to allocate a minimum of 1024 MB of memory to the GNS3 VM")
vm_settings["vcpus"] = vpcus
vm_settings["ram"] = ram
self._setGNS3VMSettings(vm_settings)
else:
if not self.uiVmwareRadioButton.isChecked() and not self.uiVirtualBoxRadioButton.isChecked():
QtWidgets.QMessageBox.warning(self, "GNS3 VM", "Please select VMware or VirtualBox")
else:
QtWidgets.QMessageBox.warning(self, "GNS3 VM", "Please select a VM. If no VM is listed, check if the GNS3 VM is correctly imported and press refresh.")
return False
elif self.currentPage() == self.uiLocalServerWizardPage:
local_server_settings = LocalServer.instance().localServerSettings()
local_server_settings["auto_start"] = True
local_server_settings["path"] = self.uiLocalServerPathLineEdit.text().strip()
local_server_settings["host"] = self.uiLocalServerHostComboBox.itemData(self.uiLocalServerHostComboBox.currentIndex())
local_server_settings["port"] = self.uiLocalServerPortSpinBox.value()
if not os.path.isfile(local_server_settings["path"]):
QtWidgets.QMessageBox.critical(self, "Local server", "Could not find local server {}".format(local_server_settings["path"]))
return False
if not os.access(local_server_settings["path"], os.X_OK):
QtWidgets.QMessageBox.critical(self, "Local server", "{} is not an executable".format(local_server_settings["path"]))
return False
LocalServer.instance().updateLocalServerSettings(local_server_settings)
if not LocalServer.instance().localServerAutoStartIfRequired():
return False
elif self.currentPage() == self.uiRemoteControllerWizardPage:
local_server_settings = LocalServer.instance().localServerSettings()
local_server_settings["auto_start"] = False
local_server_settings["host"] = self.uiRemoteMainServerHostLineEdit.text()
local_server_settings["port"] = self.uiRemoteMainServerPortSpinBox.value()
local_server_settings["protocol"] = "http"
local_server_settings["user"] = self.uiRemoteMainServerUserLineEdit.text()
local_server_settings["password"] = self.uiRemoteMainServerPasswordLineEdit.text()
local_server_settings["auth"] = self.uiRemoteMainServerAuthCheckBox.isChecked()
LocalServer.instance().updateLocalServerSettings(local_server_settings)
elif self.currentPage() == self.uiSummaryWizardPage:
if self.uiLocalRadioButton.isChecked():
# deactivate the GNS3 VM if using the local server
vm_settings = self._GNS3VMSettings()
vm_settings["enable"] = False
self._setGNS3VMSettings(vm_settings)
elif self.currentPage() == self.uiLocalServerStatusWizardPage:
if not Controller.instance().connected():
return False
return True
def _refreshVMListSlot(self):
"""
Refresh the list of VM available in VMware or VirtualBox.
"""
if self.uiVmwareRadioButton.isChecked():
Controller.instance().get("/gns3vm/engines/vmware/vms", self._getVMsFromServerCallback, progressText="Retrieving VMware VM list from server...")
elif self.uiVirtualBoxRadioButton.isChecked():
Controller.instance().get("/gns3vm/engines/virtualbox/vms", self._getVMsFromServerCallback, progressText="Retrieving VirtualBox VM list from server...")
def _getVMsFromServerCallback(self, result, error=False, **kwargs):
"""
Callback for getVMsFromServer.
:param progress_dialog: QProgressDialog instance
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
QtWidgets.QMessageBox.critical(self, "VM List", "{}".format(result["message"]))
else:
self.uiVMListComboBox.clear()
for vm in result:
self.uiVMListComboBox.addItem(vm["vmname"])
index = self.uiVMListComboBox.findText(self._GNS3VMSettings()["vmname"])
if index != -1:
self.uiVMListComboBox.setCurrentIndex(index)
else:
index = self.uiVMListComboBox.findText("GNS3 VM")
if index != -1:
self.uiVMListComboBox.setCurrentIndex(index)
else:
QtWidgets.QMessageBox.critical(self, "GNS3 VM", "Could not find a VM named 'GNS3 VM', is it imported in VMware or VirtualBox?")
def done(self, result):
"""
This dialog is closed.
:param result: ignored
"""
Controller.instance().setDisplayError(True)
settings = self.parentWidget().settings()
if result:
settings["hide_setup_wizard"] = True
else:
local_server_settings = LocalServer.instance().localServerSettings()
LocalServer.instance().updateLocalServerSettings(local_server_settings)
settings["hide_setup_wizard"] = not self.uiShowCheckBox.isChecked()
self.parentWidget().setSettings(settings)
super().done(result)
def nextId(self):
"""
Wizard rules!
"""
current_id = self.currentId()
if self.page(current_id) == self.uiLocalServerStatusWizardPage and not self.uiVMRadioButton.isChecked():
return self._pageId(self.uiSummaryWizardPage)
if self.page(current_id) == self.uiServerWizardPage and self.uiRemoteControllerRadioButton.isChecked():
return self._pageId(self.uiRemoteControllerWizardPage)
if self.page(current_id) == self.uiVMWizardPage:
return self._pageId(self.uiSummaryWizardPage)
return QtWidgets.QWizard.nextId(self)
def _pageId(self, page):
"""
Return id of the page
"""
for id in self.pageIds():
if self.page(id) == page:
return id
raise KeyError

View File

@@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Dialog to manage the snapshots.
"""
from ..qt import QtCore, QtWidgets
from ..ui.snapshots_dialog_ui import Ui_SnapshotsDialog
from ..controller import Controller
from datetime import datetime
import logging
log = logging.getLogger(__name__)
class SnapshotsDialog(QtWidgets.QDialog, Ui_SnapshotsDialog):
"""
Snapshots dialog implementation.
:param parent: parent widget
"""
def __init__(self, parent, project):
super().__init__(parent)
self.setupUi(self)
self._project = project
self.uiCreatePushButton.clicked.connect(self._createSnapshotSlot)
self.uiDeletePushButton.clicked.connect(self._deleteSnapshotSlot)
self.uiRestorePushButton.clicked.connect(self._restoreSnapshotSlot)
self.uiSnapshotsList.itemDoubleClicked.connect(self._snapshotDoubleClickedSlot)
self._listSnapshots()
def _listSnapshots(self):
"""
Lists all available snapshots.
"""
self.uiSnapshotsList.clear()
if self._project:
Controller.instance().get("/projects/{}/snapshots".format(self._project.id()), self._listSnapshotsCallback)
def _listSnapshotsCallback(self, result, error=False, server=None, context={}, **kwargs):
if error:
if result:
log.error(result["message"])
return
for snapshot in result:
item = QtWidgets.QListWidgetItem(self.uiSnapshotsList)
item.setText("{} on {}".format(snapshot["name"], datetime.fromtimestamp(snapshot["created_at"]).strftime("%d/%m/%y at %H:%M:%S")))
item.setData(QtCore.Qt.UserRole, snapshot["snapshot_id"])
if self.uiSnapshotsList.count():
self.uiSnapshotsList.setCurrentRow(0)
self.uiDeletePushButton.setEnabled(True)
self.uiRestorePushButton.setEnabled(True)
else:
self.uiDeletePushButton.setEnabled(False)
self.uiRestorePushButton.setEnabled(False)
def _createSnapshotSlot(self):
"""
Slot to create a snapshot.
"""
snapshot_name, ok = QtWidgets.QInputDialog.getText(self, "Snapshot", "Snapshot name:", QtWidgets.QLineEdit.Normal, "Unnamed")
if ok and snapshot_name and self._project:
Controller.instance().post("/projects/{}/snapshots".format(self._project.id()),
self._createSnapshotsCallback,
{"name": snapshot_name},
progressText="Creation of snapshot '{}' in progress...".format(snapshot_name),
timeout=None)
def _createSnapshotsCallback(self, result, error=False, server=None, context={}, **kwargs):
if error:
if result:
log.error(result["message"])
else:
log.error("Cannot create snapshot of project")
return
self._listSnapshots()
def _deleteSnapshotSlot(self):
"""
Slot to delete a snapshot.
"""
item = self.uiSnapshotsList.currentItem()
if item:
snapshot_id = item.data(QtCore.Qt.UserRole)
Controller.instance().delete("/projects/{}/snapshots/{}".format(self._project.id(), snapshot_id), self._deleteSnapshotsCallback)
def _deleteSnapshotsCallback(self, result, error=False, server=None, context={}, **kwargs):
if error:
if result:
log.error(result["message"])
return
self._listSnapshots()
def _restoreSnapshotSlot(self):
"""
Slot to restore a snapshot.
"""
item = self.uiSnapshotsList.currentItem()
if item:
snapshot_id = item.data(QtCore.Qt.UserRole)
self._restoreSnapshot(snapshot_id)
def _restoreSnapshot(self, snapshot_id):
"""
Restores a snapshot.
:param snapshot_id: id of the snapshot
"""
reply = QtWidgets.QMessageBox.question(self, "Snapshots", "This will discard any changes made to your project since the snapshot was taken, would you like to proceed?", QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Cancel)
if reply == QtWidgets.QMessageBox.Cancel:
return
Controller.instance().post("/projects/{}/snapshots/{}/restore".format(self._project.id(), snapshot_id),
self._restoreSnapshotsCallback, progressText="Restoring snapshot...", timeout=None)
def _restoreSnapshotsCallback(self, result, error=False, server=None, context={}, **kwargs):
if error:
if result:
log.error(result["message"])
return
self.accept()
def _snapshotDoubleClickedSlot(self, item):
"""
Slot to restore a snapshot when it is double clicked.
"""
snapshot_id = item.data(QtCore.Qt.UserRole)
self._restoreSnapshot(snapshot_id)

View File

@@ -0,0 +1,162 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Style editor to edit Shape items.
"""
from ..qt import QtCore, QtWidgets, QtGui
from ..ui.style_editor_dialog_ui import Ui_StyleEditorDialog
from ..items.shape_item import ShapeItem
from ..items.rectangle_item import RectangleItem
class StyleEditorDialog(QtWidgets.QDialog, Ui_StyleEditorDialog):
"""
Style editor dialog.
:param parent: parent widget
:param items: list of items
"""
def __init__(self, parent, items):
super().__init__(parent)
self.setupUi(self)
self._items = items
self.uiColorPushButton.clicked.connect(self._setColorSlot)
self.uiBorderColorPushButton.clicked.connect(self._setBorderColorSlot)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self._applyPreferencesSlot)
self.uiBorderStyleComboBox.addItem("Solid", QtCore.Qt.SolidLine)
self.uiBorderStyleComboBox.addItem("Dash", QtCore.Qt.DashLine)
self.uiBorderStyleComboBox.addItem("Dot", QtCore.Qt.DotLine)
self.uiBorderStyleComboBox.addItem("Dash Dot", QtCore.Qt.DashDotLine)
self.uiBorderStyleComboBox.addItem("Dash Dot Dot", QtCore.Qt.DashDotDotLine)
self.uiBorderStyleComboBox.addItem("No border", QtCore.Qt.NoPen)
# use the first item in the list as the model
first_item = items[0]
pen = first_item.pen()
if hasattr(first_item, "brush"): # Line don't have brush
brush = first_item.brush()
self._color = brush.color()
self.uiColorPushButton.setStyleSheet("background-color: rgba({}, {}, {}, {});".format(self._color.red(),
self._color.green(),
self._color.blue(),
self._color.alpha()))
else:
self.uiColorLabel.hide()
self.uiColorPushButton.hide()
self._color = None
self._border_color = pen.color()
self.uiBorderColorPushButton.setStyleSheet("background-color: rgba({}, {}, {}, {});".format(self._border_color.red(),
self._border_color.green(),
self._border_color.blue(),
self._border_color.alpha()))
if isinstance(first_item, RectangleItem):
# use the horizontal corner radius first and then the vertical one if it's not set
# maybe we allow configuring them separately in the future
corner_radius = first_item.horizontalCornerRadius()
if not corner_radius:
corner_radius = first_item.verticalCornerRadius()
self.uiCornerRadiusSpinBox.setValue(corner_radius)
else:
self.uiCornerRadiusLabel.hide()
self.uiCornerRadiusSpinBox.hide()
self.uiRotationSpinBox.setValue(int(first_item.rotation()))
self.uiBorderWidthSpinBox.setValue(pen.width())
if isinstance(first_item, ShapeItem):
rect = first_item.rect()
self.uiWidthSpinBox.setValue(int(rect.width()))
self.uiHeightSpinBox.setValue(int(rect.height()))
else:
self.uiWidthSpinBox.hide()
self.uiWidthLabel.hide()
self.uiHeightSpinBox.hide()
self.uiHeightLabel.hide()
index = self.uiBorderStyleComboBox.findData(pen.style())
if index != -1:
self.uiBorderStyleComboBox.setCurrentIndex(index)
def _setColorSlot(self):
"""
Slot to select the filling color.
"""
color = QtWidgets.QColorDialog.getColor(self._color, self, "Select Color", QtWidgets.QColorDialog.ShowAlphaChannel)
if color.isValid():
self._color = color
self.uiColorPushButton.setStyleSheet("background-color: rgba({}, {}, {}, {});".format(self._color.red(),
self._color.green(),
self._color.blue(),
self._color.alpha()))
def _setBorderColorSlot(self):
"""
Slot to select the border color.
"""
color = QtWidgets.QColorDialog.getColor(self._border_color, self, "Select Color", QtWidgets.QColorDialog.ShowAlphaChannel)
if color.isValid():
self._border_color = color
self.uiBorderColorPushButton.setStyleSheet("background-color: rgba({}, {}, {}, {});".format(self._border_color.red(),
self._border_color.green(),
self._border_color.blue(),
self._border_color.alpha()))
def _applyPreferencesSlot(self):
"""
Applies the new style settings.
"""
border_style = QtCore.Qt.PenStyle(self.uiBorderStyleComboBox.itemData(self.uiBorderStyleComboBox.currentIndex()))
pen = QtGui.QPen(self._border_color, self.uiBorderWidthSpinBox.value(), border_style, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
if self._color:
brush = QtGui.QBrush(self._color)
else:
brush = None
for item in self._items:
item.setPen(pen)
# on multi-selection it's possible to select many type of items
# but brush can be applied only on ShapeItem,
if brush and isinstance(item, ShapeItem):
item.setBrush(brush)
if isinstance(item, RectangleItem):
corner_radius = self.uiCornerRadiusSpinBox.value()
# use the corner radius for both horizontal (rx) and vertical (ry)
# maybe we support setting them separately in the future
item.setHorizontalCornerRadius(corner_radius)
item.setVerticalCornerRadius(corner_radius)
if isinstance(item, ShapeItem):
item.setWidthAndHeight(self.uiWidthSpinBox.value(), self.uiHeightSpinBox.value())
item.setRotation(self.uiRotationSpinBox.value())
def done(self, result):
"""
Called when the dialog is closed.
:param result: boolean (accepted or rejected)
"""
if result:
self._applyPreferencesSlot()
super().done(result)

View File

@@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Pekka Helenius
# Copyright (C) 2014 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/>.
"""
Style editor to edit Link items.
"""
from ..qt import QtCore, QtWidgets, QtGui
from ..ui.style_editor_dialog_ui import Ui_StyleEditorDialog
class StyleEditorDialogLink(QtWidgets.QDialog, Ui_StyleEditorDialog):
"""
Style editor dialog.
:param parent: parent widget
:param link: selected link
"""
def __init__(self, link, parent):
super().__init__(parent)
self.setupUi(self)
self._link = link
self._link_style = {}
self.uiBorderColorPushButton.clicked.connect(self._setBorderColorSlot)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self._applyPreferencesSlot)
self.uiBorderStyleComboBox.addItem("Solid", QtCore.Qt.SolidLine)
self.uiBorderStyleComboBox.addItem("Dash", QtCore.Qt.DashLine)
self.uiBorderStyleComboBox.addItem("Dot", QtCore.Qt.DotLine)
self.uiBorderStyleComboBox.addItem("Dash Dot", QtCore.Qt.DashDotLine)
self.uiBorderStyleComboBox.addItem("Dash Dot Dot", QtCore.Qt.DashDotDotLine)
self.uiBorderStyleComboBox.addItem("Invisible", QtCore.Qt.NoPen)
self.uiColorLabel.hide()
self.uiColorPushButton.hide()
self._color = None
self.uiCornerRadiusLabel.hide()
self.uiCornerRadiusSpinBox.hide()
self.uiRotationLabel.hide()
self.uiRotationSpinBox.hide()
link.setHovered(False) # make sure we use the right style
pen = link.pen()
link.setHovered(True)
self._border_color = pen.color()
self.uiBorderColorPushButton.setStyleSheet("background-color: rgba({}, {}, {}, {});".format(self._border_color.red(),
self._border_color.green(),
self._border_color.blue(),
self._border_color.alpha()))
self.uiBorderWidthSpinBox.setValue(pen.width())
index = self.uiBorderStyleComboBox.findData(pen.style())
if index != -1:
self.uiBorderStyleComboBox.setCurrentIndex(index)
self.adjustSize()
def _setBorderColorSlot(self):
"""
Slot to select the border color.
"""
color = QtWidgets.QColorDialog.getColor(self._border_color, self, "Select Color", QtWidgets.QColorDialog.ShowAlphaChannel)
if color.isValid():
self._border_color = color
self.uiBorderColorPushButton.setStyleSheet("background-color: rgba({}, {}, {}, {});".format(self._border_color.red(),
self._border_color.green(),
self._border_color.blue(),
self._border_color.alpha()))
def _applyPreferencesSlot(self):
"""
Applies the new style settings.
"""
border_style = QtCore.Qt.PenStyle(self.uiBorderStyleComboBox.itemData(self.uiBorderStyleComboBox.currentIndex()))
pen = QtGui.QPen(self._border_color, self.uiBorderWidthSpinBox.value(), border_style, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
self._link.setPen(pen)
new_link_style = {}
new_link_style["color"] = self._border_color.name()
new_link_style["width"] = self.uiBorderWidthSpinBox.value()
new_link_style["type"] = border_style
# Store values
self._link.setLinkStyle(new_link_style)
self._link.setHovered(False) # allow to see the new style
def done(self, result):
"""
Called when the dialog is closed.
:param result: boolean (accepted or rejected)
"""
if result:
self._applyPreferencesSlot()
super().done(result)

View File

@@ -0,0 +1,216 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Dialog to change node symbols.
"""
import os
import pathlib
from ..qt import QtCore, QtGui, QtWidgets, qpartial, sip_is_deleted
from ..qt.qimage_svg_renderer import QImageSvgRenderer
from ..ui.symbol_selection_dialog_ui import Ui_SymbolSelectionDialog
from ..controller import Controller
from ..symbol import Symbol
import logging
log = logging.getLogger(__name__)
class SymbolSelectionDialog(QtWidgets.QDialog, Ui_SymbolSelectionDialog):
"""
Symbol selection dialog.
:param parent: parent widget
:param items: list of items
"""
_symbols_dir = None
def __init__(self, parent, items=None, symbol=None):
super().__init__(parent)
self.setupUi(self)
self._items = items
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self._applyPreferencesSlot)
self.uiSymbolToolButton.clicked.connect(self._symbolBrowserSlot)
self.uiCustomSymbolRadioButton.toggled.connect(self._customSymbolToggledSlot)
self.uiBuiltInSymbolRadioButton.toggled.connect(self._builtInSymbolToggledSlot)
self.uiSearchLineEdit.textChanged.connect(self._searchTextChangedSlot)
if not SymbolSelectionDialog._symbols_dir:
SymbolSelectionDialog._symbols_dir = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.PicturesLocation)
if not self._items:
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).hide()
self.uiBuiltInSymbolRadioButton.setChecked(True)
self.uiSymbolTreeWidget.setFocus()
self.uiSymbolTreeWidget.setIconSize(QtCore.QSize(64, 64))
self._symbol_items = []
self._parents = {}
Controller.instance().clearStaticCache() # TODO: use etag to know when to refresh the cache
Controller.instance().get("/symbols", self._listSymbolsCallback)
def _listSymbolsCallback(self, result, error=False, **kwargs):
if error:
log.error("Error while listing symbols: {}".format(result["message"]))
return
self._symbol_items = []
for symbol in result:
symbol = Symbol(**symbol)
theme = symbol.theme()
if theme not in self._parents:
parent = QtWidgets.QTreeWidgetItem(self.uiSymbolTreeWidget)
parent.setText(0, theme)
font = parent.font(0)
font.setBold(True)
parent.setFont(0, font)
parent.setFlags(parent.flags() & ~QtCore.Qt.ItemIsSelectable)
self._parents[theme] = parent
else:
parent = self._parents[theme]
name = os.path.splitext(symbol.filename())[0]
item = QtWidgets.QTreeWidgetItem(parent)
item.setData(0, QtCore.Qt.UserRole, symbol)
item.setToolTip(0, symbol.id())
self._symbol_items.append(item)
item.setText(0, name)
def render(item, path):
if sip_is_deleted(item):
return
svg_renderer = QImageSvgRenderer(path)
image = QtGui.QImage(64, 64, QtGui.QImage.Format_ARGB32)
# Set the ARGB to 0 to prevent rendering artifacts
image.fill(0x00000000)
svg_renderer.render(QtGui.QPainter(image))
icon = QtGui.QIcon(QtGui.QPixmap.fromImage(image))
item.setIcon(0, icon)
Controller.instance().getStatic(symbol.url(), qpartial(render, item))
for parent in self._parents.values():
parent.sortChildren(0, QtCore.Qt.AscendingOrder)
self.adjustSize()
def _searchTextChangedSlot(self, text):
self._filter()
def _filter(self):
"""
Hide element not matching the search
"""
text = self.uiSearchLineEdit.text()
for item in self._symbol_items:
# if not item.data(0, QtCore.Qt.UserRole).builtin():
# item.setHidden(True)
# else:
if not text.strip() or text.strip().lower() in item.text(0).lower():
item.setHidden(False)
else:
item.setHidden(True)
def _customSymbolToggledSlot(self, checked):
"""
Slot for when the custom symbol radio button is toggled.
:param checked: either the button is checked or not
"""
if checked:
self.uiCustomSymbolGroupBox.setEnabled(True)
self.uiCustomSymbolGroupBox.show()
self.uiBuiltInGroupBox.setEnabled(False)
self.uiBuiltInGroupBox.hide()
self.adjustSize()
def _builtInSymbolToggledSlot(self, checked):
"""
Slot for when the built-in symbol radio button is toggled.
:param checked: either the button is checked or not
"""
if checked:
self.uiCustomSymbolGroupBox.setEnabled(False)
self.uiCustomSymbolGroupBox.hide()
self.uiBuiltInGroupBox.setEnabled(True)
self.uiBuiltInGroupBox.show()
self.adjustSize()
def _applyPreferencesSlot(self):
"""
Applies the selected symbol to the items.
"""
symbol_path = self.getSymbol()
if not symbol_path:
return False
for item in self._items:
item.setSymbol(symbol_path)
return True
def getSymbol(self):
if self.uiSymbolTreeWidget.isEnabled():
current = self.uiSymbolTreeWidget.currentItem()
if current and current.parent():
return current.data(0, QtCore.Qt.UserRole).id()
else:
return os.path.basename(self.uiSymbolLineEdit.text())
return None
def _symbolBrowserSlot(self):
# supported image file formats
file_formats = "Image files (*.svg *.bmp *.jpeg *.jpg *.pbm *.pgm *.png *.ppm *.xbm *.xpm *.gif);;All files (*.*)"
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Image", SymbolSelectionDialog._symbols_dir, file_formats)
if not path:
return
SymbolSelectionDialog._symbols_dir = os.path.dirname(path)
symbol_id = os.path.basename(path)
Controller.instance().post("/symbols/" + symbol_id + "/raw", qpartial(self._finishSymbolUpload, path), body=pathlib.Path(path), progressText="Uploading {}".format(symbol_id), timeout=None)
def _finishSymbolUpload(self, path, result, error=False, **kwargs):
if error:
log.error("Error while uploading symbol: {}: {}".format(path, result.get("message", "unknown")))
return
self.uiSymbolLineEdit.clear()
self.uiSymbolLineEdit.setText(path)
self.uiSymbolLineEdit.setToolTip('<img src="{}"/>'.format(path))
def done(self, result):
"""
Called when the dialog is closed.
:param result: boolean (accepted or rejected)
"""
if result and self._items and not self._applyPreferencesSlot():
result = 0
super().done(result)

View File

@@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Text editor to edit Note items.
"""
from ..qt import QtCore, QtWidgets, qslot, sip_is_deleted
from ..ui.text_editor_dialog_ui import Ui_TextEditorDialog
class TextEditorDialog(QtWidgets.QDialog, Ui_TextEditorDialog):
"""
Text editor dialog.
:param parent: parent widget
:param items: list of items
"""
def __init__(self, parent, items):
super().__init__(parent)
self.setupUi(self)
self._items = items
self.uiFontPushButton.clicked.connect(self._setFontSlot)
self.uiColorPushButton.clicked.connect(self._setColorSlot)
self.uiButtonBox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self._applyPreferencesSlot)
# use the first item in the list as the model
first_item = items[0]
self._setColor(first_item.defaultTextColor())
self.uiRotationSpinBox.setValue(int(first_item.rotation()))
self.uiPlainTextEdit.setPlainText(first_item.toPlainText())
self.uiPlainTextEdit.setFont(first_item.font())
if not first_item.editable():
self.uiPlainTextEdit.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
if len(self._items) == 1:
self.uiApplyColorToAllItemsCheckBox.setChecked(True)
self.uiApplyColorToAllItemsCheckBox.hide()
self.uiApplyRotationToAllItemsCheckBox.setChecked(True)
self.uiApplyRotationToAllItemsCheckBox.hide()
self.uiApplyTextToAllItemsCheckBox.setChecked(True)
self.uiApplyTextToAllItemsCheckBox.hide()
def _setColor(self, color):
self._color = color
self.uiColorPushButton.setStyleSheet("background-color: rgba({}, {}, {}, {});".format(color.red(),
color.green(),
color.blue(),
color.alpha()))
self.uiPlainTextEdit.setStyleSheet("color: rgba({}, {}, {}, {});".format(color.red(),
color.green(),
color.blue(),
color.alpha()))
@qslot
def _setFontSlot(self, *args):
"""
Slot to select the font.
"""
selected_font, ok = QtWidgets.QFontDialog.getFont(self.uiPlainTextEdit.font(), self,
options=QtWidgets.QFontDialog.DontUseNativeDialog)
if ok:
self.uiPlainTextEdit.setFont(selected_font)
@qslot
def _setColorSlot(self, *args):
"""
Slot to select the color.
"""
color = QtWidgets.QColorDialog.getColor(self._color, self, None, QtWidgets.QColorDialog.ShowAlphaChannel)
if color.isValid():
self._setColor(color)
@qslot
def _applyPreferencesSlot(self, *args):
"""
Applies the new text settings.
"""
for item in self._items:
if sip_is_deleted(item):
continue
item.setFont(self.uiPlainTextEdit.font())
if self.uiApplyColorToAllItemsCheckBox.isChecked():
item.setDefaultTextColor(self._color)
if self.uiApplyRotationToAllItemsCheckBox.isChecked():
item.setRotation(self.uiRotationSpinBox.value())
if item.editable() and self.uiApplyTextToAllItemsCheckBox.isChecked():
item.setPlainText(self.uiPlainTextEdit.toPlainText())
def done(self, result):
"""
Called when the dialog is closed.
:param result: boolean (accepted or rejected)
"""
if result:
self._applyPreferencesSlot()
super().done(result)

View File

@@ -0,0 +1,188 @@
#!/usr/bin/env python
#
# 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/>.
from .vm_wizard import VMWizard
from gns3.qt import QtWidgets
from gns3.controller import Controller
class VMWithImagesWizard(VMWizard):
"""
Base class for VM wizard with image management (Qemu, IOU...)
:param devices: List of existing device for this type
:param parent: parent widget
"""
def __init__(self, devices, parent):
# The list of images combo box (Qemu support multiple images)
self._images_combo_boxes = set()
# The list of radio button for existing image or new images
self._radio_existing_images_buttons = set()
super().__init__(devices, parent)
def refreshImageStepsButtons(self):
"""
When changing the server type (remote or local)
Refresh all the image selectors
"""
for radio_button in self._radio_existing_images_buttons:
radio_button.setChecked(radio_button.isChecked())
def _vmToggledSlot(self, checked):
super()._vmToggledSlot(checked)
if checked:
self.refreshImageStepsButtons()
def _remoteServerToggledSlot(self, checked):
super()._remoteServerToggledSlot(checked)
if checked:
self.refreshImageStepsButtons()
def _localToggledSlot(self, checked):
super()._localToggledSlot(checked)
if checked:
self.refreshImageStepsButtons()
def addImageSelector(self, radio_button, combo_box, line_edit, browser, image_selector, create_button=None, create_image_wizard=None, image_suffix=""):
"""
Add a remote image selector
:param radio_button: Radio button which toggle display of the listbox
:param combo_box: The image choice combo box
:param line_edit: The edit for the image
:param browser: file upload browser button
:param image_selector: function which display an image selector and return path
:param create_button: Image create button None if you don't need one
:param create_image_wizard: Wizard Class for creating a new image
"""
combo_box.currentIndexChanged.connect(lambda index: self._imageListIndexChangedSlot(index, combo_box, line_edit))
self._images_combo_boxes.add(combo_box)
browser.clicked.connect(lambda: self._imageBrowserSlot(line_edit, image_selector))
if create_button:
assert create_image_wizard is not None
create_button.clicked.connect(lambda: self._imageCreateSlot(line_edit, create_image_wizard, image_suffix))
self._existingImageToggledSlot(True, combo_box, line_edit, browser, create_button)
radio_button.toggled.connect(lambda checked: self._existingImageToggledSlot(checked, combo_box, line_edit, browser, create_button))
self._radio_existing_images_buttons.add(radio_button)
def _imageCreateSlot(self, line_edit, create_image_wizard, image_suffix):
create_dialog = create_image_wizard(self, self.getSettings()["compute_id"], self.uiNameLineEdit.text() + image_suffix)
if QtWidgets.QDialog.Accepted == create_dialog.exec_():
line_edit.setText(create_dialog.uiLocationLineEdit.text())
def _imageBrowserSlot(self, line_edit, image_selector):
"""
Slot to open a file browser and select an image.
"""
path = image_selector(self, self._compute_id)
if not path:
return
line_edit.clear()
line_edit.setText(path)
def _imageListIndexChangedSlot(self, index, combo_box, line_edit):
"""
User select a different image in the combo box
"""
item = combo_box.itemData(index)
if item and item["path"]:
line_edit.setText(item["path"])
else:
line_edit.setText("")
def _existingImageToggledSlot(self, checked, combo_box, line_edit, browser, create_button):
"""
User select the option of using an existing image
"""
if create_button:
create_button.hide()
if checked:
combo_box.show()
browser.hide()
line_edit.hide()
if combo_box.count() > 0:
line_edit.setText(combo_box.itemData(combo_box.currentIndex())["path"])
else:
combo_box.hide()
line_edit.setText("")
line_edit.show()
browser.show()
if create_button:
create_button.show()
def loadImagesList(self, endpoint):
"""
Fill the list box with available Images"
:param endpoint: server endpoint with the list of Images
"""
Controller.instance().getCompute(endpoint, self._compute_id, self._getImagesFromServerCallback)
def _getImagesFromServerCallback(self, result, error=False, **kwargs):
"""
Callback for loadImagesList.
:param result: server response
:param error: indicates an error (boolean)
"""
if error:
QtWidgets.QMessageBox.critical(self, "Images", "Error while getting the VMs: {}".format(result["message"]))
return
# Wizard is closed
if self.currentPage() is None:
return
if len(result) == 0:
for radio_button in self._radio_existing_images_buttons:
if radio_button.isChecked() and self._widgetOnCurrentPage(radio_button):
for button in radio_button.parent().findChildren(QtWidgets.QRadioButton):
if button != radio_button:
button.setChecked(True)
button.hide()
else:
for radio_button in self._radio_existing_images_buttons:
if self._widgetOnCurrentPage(radio_button):
for button in radio_button.parent().findChildren(QtWidgets.QRadioButton):
if button == radio_button:
button.setChecked(True)
button.show()
for combo_box in self._images_combo_boxes:
if self._widgetOnCurrentPage(combo_box):
combo_box.clear()
for vm in result:
combo_box.addItem(vm["path"], vm)
def _widgetOnCurrentPage(self, widget):
"""
:returns Boolean True if widget is current active Wizard page
"""
return self.currentPage().findChild(widget.__class__, widget.objectName()) is not None

160
gns3/dialogs/vm_wizard.py Normal file
View File

@@ -0,0 +1,160 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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 sys
from gns3.qt import QtWidgets
from gns3.compute_manager import ComputeManager
from gns3.controller import Controller
class VMWizard(QtWidgets.QWizard):
"""
Base class for VM wizard.
:param devices: List of existing device for this type
:param parent: parent widget
"""
def __init__(self, devices, parent):
super().__init__(parent)
self.setupUi(self)
self.setModal(True)
self._devices = devices
self._local_server_disable = False
self.setWizardStyle(QtWidgets.QWizard.ModernStyle)
if sys.platform.startswith("darwin"):
# we want to see the cancel button on OSX
self.setOptions(QtWidgets.QWizard.NoDefaultButton)
self.uiRemoteRadioButton.toggled.connect(self._remoteServerToggledSlot)
if hasattr(self, "uiVMRadioButton"):
self.uiVMRadioButton.toggled.connect(self._vmToggledSlot)
self.uiLocalRadioButton.toggled.connect(self._localToggledSlot)
if Controller.instance().isRemote():
self.uiLocalRadioButton.setText("Run device on the main server")
# By default we use the local server
self._compute_id = "local"
self.uiLocalRadioButton.setChecked(True)
self._localToggledSlot(True)
if len(ComputeManager.instance().computes()) == 1:
# skip the server page if we use the first server
self.setStartId(1)
def _vmToggledSlot(self, checked):
"""
Slot for when the VM radio button is toggled.
:param checked: either the button is checked or not
"""
if checked:
self.uiRemoteServersGroupBox.setEnabled(False)
self.uiRemoteServersGroupBox.hide()
def _remoteServerToggledSlot(self, checked):
"""
Slot for when the remote server radio button is toggled.
:param checked: either the button is checked or not
"""
if checked:
self.uiRemoteServersGroupBox.setEnabled(True)
self.uiRemoteServersComboBox.setEnabled(True)
self.uiRemoteServersGroupBox.show()
def _localToggledSlot(self, checked):
"""
Slot for when the local server radio button is toggled.
:param checked: either the button is checked or not
"""
if checked:
self.uiRemoteServersGroupBox.setEnabled(False)
self.uiRemoteServersGroupBox.hide()
def initializePage(self, page_id):
if self.page(page_id) == self.uiServerWizardPage:
self.uiRemoteServersComboBox.clear()
self.uiRemoteRadioButton.setEnabled(False)
if hasattr(self, "uiVMRadioButton"):
self.uiVMRadioButton.setEnabled(False)
self.uiLocalRadioButton.setEnabled(False)
for compute in ComputeManager.instance().computes():
if compute.id() == "local":
self.uiLocalRadioButton.setEnabled(True)
elif compute.id() == "vm":
if hasattr(self, "uiVMRadioButton"):
self.uiVMRadioButton.setEnabled(True)
else:
self.uiRemoteRadioButton.setEnabled(True)
self.uiRemoteServersComboBox.addItem(compute.name(), compute.id())
if self.uiLocalRadioButton.isEnabled() and not self._local_server_disable:
self.uiLocalRadioButton.setChecked(True)
elif hasattr(self, "uiVMRadioButton") and self.uiVMRadioButton.isEnabled():
self.uiVMRadioButton.setChecked(True)
else:
if self.uiRemoteRadioButton.isEnabled():
self.uiRemoteRadioButton.setChecked(True)
else:
self.uiLocalRadioButton.setChecked(True)
def _disableLocalServer(self):
"""
Turn off the local server
"""
self._local_server_disable = True
self.uiLocalRadioButton.hide()
self.uiLocalRadioButton.setEnabled(False)
self.setStartId(0)
def validateCurrentPage(self):
if hasattr(self, "uiNameWizardPage") and self.currentPage() == self.uiNameWizardPage:
name = self.uiNameLineEdit.text()
for device in self._devices.values():
if device["name"] == name:
QtWidgets.QMessageBox.critical(self, "Name", "{} is already used, please choose another name".format(name))
return False
elif self.currentPage() == self.uiServerWizardPage:
# If the local button is not visible it's because it's not supported
if self.uiLocalRadioButton.isChecked() and self.uiLocalRadioButton.isHidden():
QtWidgets.QMessageBox.critical(self, "New device", "Please configure before the GNS3 VM in order to use this device.")
return False
if self.uiRemoteRadioButton.isChecked():
if self.uiRemoteServersComboBox.count() == 0:
QtWidgets.QMessageBox.critical(self, "Remote server", "There is no remote server registered in your preferences")
return False
self._compute_id = self.uiRemoteServersComboBox.itemData(self.uiRemoteServersComboBox.currentIndex())
elif hasattr(self, "uiVMRadioButton") and self.uiVMRadioButton.isChecked():
self._compute_id = "vm"
else:
if self.uiLocalRadioButton.isEnabled():
self._compute_id = "local"
else:
QtWidgets.QMessageBox.critical(self, "Server", "No available server support this type of node. You probably need to setup the GNS3 VM")
return False
return True

View File

@@ -1,61 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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 re
from .qt import QtGui
from .ui.early_release_dialog_ui import Ui_EarlyReleaseDialog
class EarlyReleaseDialog(QtGui.QDialog, Ui_EarlyReleaseDialog):
"""
Early release dialog.
"""
def __init__(self, parent):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
def isEmail(self, email):
if re.match("([\w\-\.]+@(\w[\w\-]+\.)+[\w\-]+)", email):
return True
else:
return False
def done(self, result):
if not result: # cancelled
QtGui.QApplication.quit()
else:
username = self.uiUsernameLineEdit.text().strip()
if not username:
QtGui.QMessageBox.critical(self, "Username", "Please provide an username")
return
email = self.uiEmailLineEdit.text().strip()
if not email:
QtGui.QMessageBox.critical(self, "Email", "Please provide an email address")
return
if not re.search(r"""^GNS[34]{1}[0-9]{4}$""", username) or not self.isEmail(email):
QtGui.QMessageBox.critical(self, "Invalid membership", "Sorry this is an invalid membership")
return
if not self.uiDisclaimerCheckBox.isChecked():
QtGui.QMessageBox.critical(self, "Disclaimer", "Please read the disclaimer!")
return
# Congratulations, you have found where we check for a GNS3 membership! and yes, it is very simple ;)
# Since you were smart enough to get here, you deserve to use GNS3 without a membership...
QtGui.QDialog.done(self, result)

File diff suppressed because it is too large Load Diff

862
gns3/http_client.py Normal file
View File

@@ -0,0 +1,862 @@
# -*- 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/>.
from .qt import sip
import json
import copy
import uuid
import pathlib
import base64
import ipaddress
import urllib.request
import urllib.parse
from .version import __version__, __version_info__
from .qt import QtCore, QtNetwork, QtWidgets, qpartial, sip_is_deleted
from .utils import parse_version
import logging
log = logging.getLogger(__name__)
class HttpBadRequest(Exception):
"""We raise bad request exception for logging them in Sentry"""
pass
class HTTPClient(QtCore.QObject):
"""
HTTP client.
:param settings: Dictionary with connection information to the server
:param network_manager: A QT network manager
"""
# Callback class used for displaying progress
_progress_callback = None
connection_connected_signal = QtCore.Signal()
connection_disconnected_signal = QtCore.Signal()
def __init__(self, settings, network_manager=None, max_retry_connection=5):
super().__init__()
self._protocol = settings.get("protocol", "http")
self._host = settings["host"]
try:
if self._host is None or self._host == "0.0.0.0":
self._host = "127.0.0.1"
elif ":" in self._host and ipaddress.IPv6Address(self._host) and str(ipaddress.IPv6Address(self._host)) == "::":
self._host = "::1"
except ipaddress.AddressValueError:
log.error("Invalid host name %s", self._host)
self._port = int(settings["port"])
self._user = settings.get("user", None)
self._password = settings.get("password", None)
# How many time we have already retried connection
self._retry = 0
self._max_retry_connection = max_retry_connection
self._connected = False
self._shutdown = False # Shutdown in progress
self._accept_insecure_certificate = settings.get("accept_insecure_certificate", None)
# Add custom CA
# ssl_config = QtNetwork.QSslConfiguration.defaultConfiguration()
# if ssl_config.addCaCertificates("/path/to/rootCA.crt"):
# log.debug("CA certificate added")
# QtNetwork.QSslConfiguration.setDefaultConfiguration(ssl_config)
if self._protocol == "https":
if not QtNetwork.QSslSocket.supportsSsl():
log.error("SSL is not supported")
else:
log.debug(f"SSL is supported, version: {QtNetwork.QSslSocket().sslLibraryBuildVersionString()}")
# In order to detect computer hibernation we detect the date of the last
# query and disconnect if time is too long between two query
self._last_query_timestamp = None
self._max_time_difference_between_queries = None
if network_manager:
self._network_manager = network_manager
else:
self._network_manager = QtNetwork.QNetworkAccessManager()
# A buffer used by progress download
self._buffer = {}
# List of query waiting for the connection
self._query_waiting_connections = []
# To catch SSL errors
self._network_manager.sslErrors.connect(self._sslErrorsSlot)
# Store SSL error exceptions
self._ssl_exceptions = {}
def setMaxTimeDifferenceBetweenQueries(self, value):
self._max_time_difference_between_queries = value
def host(self):
"""
Host display to user
"""
return self._host
def setHost(self, host):
self._host = host
def port(self):
"""
Port display to user
"""
return self._port
def setPort(self, port):
self._port = port
def protocol(self):
"""
Transport protocol
"""
return self._protocol
def setAcceptInsecureCertificate(self, certificate):
"""
Does the server accept this insecure SSL certificate digest
:param: Certificate digest
"""
self._accept_insecure_certificate = certificate
def user(self):
"""
User login display to GNS3 user
"""
return self._user
def url(self):
"""Returns current server url"""
if ":" in self.host():
return "{}://[{}]:{}".format(self.protocol(), self.host(), self.port())
return "{}://{}:{}".format(self.protocol(), self.host(), self.port())
def fullUrl(self):
"""Returns current server url including user and password"""
host = self.host()
if ":" in self.host():
host = "[{}]".format(host)
if self._user:
return "{}://{}:{}@{}:{}".format(self.protocol(), self._user, self._password, host, self.port())
else:
return "{}://{}:{}".format(self.protocol(), host, self.port())
def password(self):
return self._password
def setPassword(self, password):
self._password = password
def shutdown(self):
"""
Stop the server and stop to accept queries
"""
self.createHTTPQuery("POST", "/shutdown", None, showProgress=False)
self._shutdown = True
def getNetworkManager(self):
"""
:return: instance of NetworkManager
"""
return self._network_manager
def setMaxRetryConnection(self, retries):
"""
Sets how many times we need to retry a connection
:param retries: integer
"""
self._max_retry_connection = retries
def getMaxRetryConnection(self):
"""
Returns how many times we need to retry a connection
"""
return self._max_retry_connection
def _notify_progress_start_query(self, query_id, progress_text, response):
"""
Called when a query start
"""
if not sip_is_deleted(HTTPClient._progress_callback):
if progress_text:
HTTPClient._progress_callback.add_query_signal.emit(query_id, progress_text, response)
else:
HTTPClient._progress_callback.add_query_signal.emit(query_id, "Waiting for {}".format(self.url()), response)
def _notify_progress_end_query(cls, query_id):
"""
Called when a query is over
"""
if not sip_is_deleted(HTTPClient._progress_callback):
HTTPClient._progress_callback.remove_query_signal.emit(query_id)
def _notify_progress_upload(self, query_id, sent, total):
"""
Called when a query upload progress
"""
if not sip_is_deleted(HTTPClient._progress_callback):
HTTPClient._progress_callback.progress_signal.emit(query_id, str(abs(sent)), str(abs(total)))
def _notify_progress_download(self, query_id, sent, total):
"""
Called when a query download progress
"""
if not sip_is_deleted(HTTPClient._progress_callback):
# abs() for maximum because sometimes the system send negative
# values
HTTPClient._progress_callback.progress_signal.emit(query_id, str(abs(sent)), str(abs(total)))
@classmethod
def setProgressCallback(cls, progress_callback):
"""
:param progress_callback: A progress callback instance
"""
cls._progress_callback = progress_callback
def connected(self):
"""
Returns if the client is connected.
:returns: True or False
"""
return self._connected
def close(self):
"""
Closes the connection with the server.
"""
self._connected = False
self._progress_callback.reset()
def _request(self, url):
"""
Get a QNetworkRequest object. You can mock this
if you want low level mocking.
:param url: Url of remote ressource (QtCore.QUrl)
:returns: QT Network request (QtNetwork.QNetworkRequest)
"""
return QtNetwork.QNetworkRequest(url)
def _connect(self, query, server):
"""
Initialize the connection
:param query: The query to execute when all network stack is ready
:param query: The Server to connect
"""
def createHTTPQuery(self, method, path, callback, body={}, context={},
downloadProgressCallback=None,
showProgress=True,
ignoreErrors=False,
progressText=None,
timeout=120,
server=None,
prefix="/v2",
params={},
networkManager=None,
eventsHandler=None,
**kwargs):
"""
Call the remote server, if not connected, check connection before
:param method: HTTP method
:param path: Remote path
:param body: params to send (dictionary or pathlib.Path)
:param callback: callback method to call when the server replies
:param context: Pass a context to the response callback
:param downloadProgressCallback: Callback called when received something, it can be an incomplete response
:param showProgress: Display progress to the user
:param progressText: Text display to user in the progress dialog. None for auto generated
:param ignoreErrors: Ignore connection error (usefull to not closing a connection when notification feed is broken)
:param server: The server where the query will run
:param timeout: Delay in seconds before raising a timeout
:param prefix: Prefix to the path
:param networkManager: QNetworkAccessManager None use the default
:param eventsHandler: Handler receiving and triggering events like `updated`, `cancelled`.
If not specified and showProgress is `True` then `ProgressDialog` receives them.
:param params: Query arguments parameters
:returns: QNetworkReply
"""
if "dev" in __version__:
assert QtCore.QThread.currentThread() == self.thread(), "HTTP request not started from the main thread"
# Shutdown in progress do not execute the query
if self._shutdown:
return
# TODO: clean this
# We try to detect computer hibernation
# if time between two query is too long we trigger a disconnect
# if self._max_time_difference_between_queries:
# now = datetime.datetime.now().timestamp()
# if self._last_query_timestamp is not None and now > self._last_query_timestamp + self._max_time_difference_between_queries:
# log.warning("Synchronisation lost with the server.")
# self.disconnect()
# self._last_query_timestamp = None
# return
# self._last_query_timestamp = now
request = qpartial(self._executeHTTPQuery, method, path, qpartial(callback), body, context,
downloadProgressCallback=downloadProgressCallback,
showProgress=showProgress,
ignoreErrors=ignoreErrors,
progressText=progressText,
networkManager=networkManager,
server=server,
timeout=timeout,
prefix=prefix,
eventsHandler=eventsHandler,
params=params)
if self._connected:
return request()
else:
self._query_waiting_connections.append((request, callback))
# enqueue the first query and open the connection if we are not connected
if len(self._query_waiting_connections) == 1:
log.debug("Connection to {}".format(self.url()))
self._executeHTTPQuery("GET", "/version", self._callbackConnect, {}, server=server, timeout=10, showProgress=False)
def _connectionError(self, callback, msg="", server=None):
"""
Return an error to user if connection failed
:param callback: User callback
:param msg: An optional additional message for the callback
:param server: Server where the query is execute
"""
if len(msg) > 0:
msg = "Cannot connect to server {}: {}".format(self.url(), msg)
else:
msg = "Cannot connect to {}. Please check if GNS3 is allowed in your antivirus and firewall. And that server version is {}.".format(self.url(), __version__)
for request, callback in self._query_waiting_connections:
if callback is not None:
callback({"message": msg}, error=True, server=server, connection_error=True)
self._query_waiting_connections = []
def _retryConnection(self, server=None):
log.debug("Retry connection to {}".format(self.url()))
self._retry += 1
QtCore.QTimer.singleShot(1000, qpartial(self._executeHTTPQuery, "GET", "/version", self._callbackConnect, {}, server=server, timeout=5))
def _callbackConnect(self, params, error=False, server=None, **kwargs):
"""
Callback after /version response. Continue execution of query
:param method: HTTP method
:param path: Remote path
:param body: params to send (dictionary or pathlib.Path)
:param original_context: Original context
:param callback: callback method to call when the server replies
"""
if error is not False:
if self._retry < self.getMaxRetryConnection():
self._retryConnection(server=server)
return
for request, callback in self._query_waiting_connections:
if callback is not None:
self._connectionError(callback)
return
if "version" not in params or "local" not in params:
if self._retry < self.getMaxRetryConnection():
self._retryConnection(server=server)
return
msg = "The remote server {} is not a GNS3 server".format(self.url())
log.error(msg)
for request, callback in self._query_waiting_connections:
if callback is not None:
callback({"message": msg}, error=True, server=server)
self._query_waiting_connections = []
return
if params["version"].split("+")[0] != __version__.split("+")[0]:
msg = "Client version {} is not the same as server (controller) version {}".format(__version__, params["version"])
# We don't allow different versions to interact even with dev build
# (excepting post release corrections e.g 2.2.32.1, occassionally done when fixing a packaging problem)
# TODO: we should probably follow this standard starting with v3.0: https://semver.org/
if parse_version(__version__)[:3] != parse_version(params["version"])[:3]:
log.error(msg)
for request, callback in self._query_waiting_connections:
if callback is not None:
callback({"message": msg}, error=True, server=server)
return
log.warning("{}\nUsing different versions may result in unexpected problems. Please upgrade or use at your own risk.".format(msg))
self._connected = True
self._retry = 0
self.connection_connected_signal.emit()
for request, callback in self._query_waiting_connections:
if request:
request()
self._query_waiting_connections = []
def _addBodyToRequest(self, body, request):
"""
Add the require headers for sending the body.
It detect the type of body for sending the corresponding headers
and methods.
:param body: The body
:returns: The body compatible with Qt
"""
if body is None:
return None
if isinstance(body, dict):
body = json.dumps(body)
request.setRawHeader(b"Content-Type", b"application/json")
request.setRawHeader(b"Content-Length", str(len(body)).encode())
data = QtCore.QByteArray(body.encode())
body = QtCore.QBuffer(self)
body.setData(data)
body.open(QtCore.QIODevice.ReadOnly)
return body
elif isinstance(body, pathlib.Path):
body = QtCore.QFile(str(body), self)
body.open(QtCore.QFile.ReadOnly)
request.setRawHeader(b"Content-Type", b"application/octet-stream")
# QT is smart and will compute the Content-Lenght for us
return body
elif isinstance(body, str):
request.setRawHeader(b"Content-Type", b"application/octet-stream")
data = QtCore.QByteArray(body.encode())
body = QtCore.QBuffer(self)
body.setData(data)
body.open(QtCore.QIODevice.ReadOnly)
return body
else:
return None
def _addAuth(self, request):
"""
If require add basic auth header
"""
if self._user:
auth_string = "{}:{}".format(self._user, self._password)
auth_string = base64.b64encode(auth_string.encode("utf-8"))
auth_string = "Basic {}".format(auth_string.decode())
request.setRawHeader(b"Authorization", auth_string.encode())
return request
def connectWebSocket(self, websocket, path, prefix="/v2"):
"""
Path of the websocket endpoint
"""
host = self._getHostForQuery()
request = websocket.request()
ws_protocol = "ws"
if self._protocol == "https":
ws_protocol = "wss"
ws_url = "{protocol}://{host}:{port}{prefix}{path}".format(protocol=ws_protocol,
host=host,
port=self._port,
path=path,
prefix=prefix)
log.debug("Connecting to WebSocket endpoint: {}".format(ws_url))
request.setUrl(QtCore.QUrl(ws_url))
self._addAuth(request)
websocket.open(request)
return websocket
def _getHostForQuery(self):
"""
Get hostname that could be use by Qt
"""
try:
ip = self._host.rsplit('%', 1)[0]
ipaddress.IPv6Address(ip) # remove any scope ID
# this is an IPv6 address, we must surround it with brackets to be used with QUrl.
host = "[{}]".format(ip)
except ipaddress.AddressValueError:
host = self._host
return host
def _paramsToQueryString(self, params):
"""
:param params: Dictionary of query string parameters
:returns: String of the query string
"""
if params == {}:
query_string = ""
else:
query_string = "?"
params = params.copy()
for key, value in params.copy().items():
if value is None:
del params[key]
query_string += urllib.parse.urlencode(params)
return query_string
def _executeHTTPQuery(self, method, path, callback, body, context={}, downloadProgressCallback=None, showProgress=True, ignoreErrors=False, progressText=None, server=None, timeout=120, prefix="/v2", params={}, networkManager=None, eventsHandler=None, **kwargs):
"""
Call the remote server
:param method: HTTP method
:param path: Remote path
:param body: params to send (dictionary)
:param callback: callback method to call when the server replies
:param context: Pass a context to the response callback
:param downloadProgressCallback: Callback called when received something, it can be an incomplete response
:param showProgress: Display progress to the user
:param networkManager: The network manager to use. If None use default
:param progressText: Text display to user in progress dialog. None for auto generated
:param ignoreErrors: Ignore connection error (usefull to not closing a connection when notification feed is broken)
:param server: The server where the query is executed
:param timeout: Delay in seconds before raising a timeout
:param eventsHandler: Handler receiving and triggering events like `updated`, `cancelled`.
If not specified and showProgress is `True` then `ProgressDialog` receives them.
:param params: Query arguments parameters
:returns: QNetworkReply
"""
host = self._getHostForQuery()
query_string = self._paramsToQueryString(params)
log.debug("{method} {protocol}://{host}:{port}{prefix}{path} {body}{query_string}".format(method=method, protocol=self._protocol, host=host, port=self._port, path=path, body=body, prefix=prefix, query_string=query_string))
url = QtCore.QUrl("{protocol}://{host}:{port}{prefix}{path}{query_string}".format(protocol=self._protocol, host=host, port=self._port, path=path, prefix=prefix, query_string=query_string))
if self._user:
url.setUserName(self._user)
request = self._request(url)
request = self._addAuth(request)
request.setRawHeader(b"User-Agent", "GNS3 QT Client v{version}".format(version=__version__).encode())
# By default QT doesn't support GET with body even if it's in the RFC that's why we need to use sendCustomRequest
body = self._addBodyToRequest(body, request)
if not networkManager:
networkManager = self._network_manager
try:
response = networkManager.sendCustomRequest(request, method.encode(), body)
except SystemError as e:
log.error("Can't send query: {}".format(str(e)))
return
context = copy.copy(context)
context["query_id"] = str(uuid.uuid4())
response.finished.connect(qpartial(self._processResponse, response, server, callback, context, body, ignoreErrors))
response.error.connect(qpartial(self._processError, response, server, callback, context, body, ignoreErrors))
if downloadProgressCallback is not None:
response.readyRead.connect(qpartial(self._readyReadySlot, response, downloadProgressCallback, context, server))
request_canceled = qpartial(self._requestCanceled, response, context)
if eventsHandler is not None:
eventsHandler.canceled.connect(request_canceled)
elif not sip_is_deleted(HTTPClient._progress_callback) and HTTPClient._progress_callback.progress_dialog():
HTTPClient._progress_callback.progress_dialog().canceled.connect(request_canceled)
if showProgress:
response.uploadProgress.connect(qpartial(self._notify_progress_upload, context["query_id"]))
response.downloadProgress.connect(qpartial(self._notify_progress_download, context["query_id"]))
# Should be the last operation otherwise we have race condition in Qt
# where query start before finishing connect to everything
self._notify_progress_start_query(context["query_id"], progressText, response)
if timeout is not None:
QtCore.QTimer.singleShot(timeout * 1000, qpartial(self._timeoutSlot, response, timeout))
return response
def _readyReadySlot(self, response, callback, context, server, *args):
"""
Process a packet receive on the notification feed.
The feed can contains qpartial JSON. If we found a
part of a JSON we keep it for the next packet
"""
if response.error() != QtNetwork.QNetworkReply.NoError:
return
# HTTP error
status = response.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute)
if status >= 300:
return
content = bytes(response.readAll())
content_type = response.header(QtNetwork.QNetworkRequest.ContentTypeHeader)
if content_type == "application/json":
content = content.decode("utf-8")
if context["query_id"] in self._buffer:
content = self._buffer[context["query_id"]] + content
try:
while True:
content = content.lstrip(" \r\n\t")
answer, index = json.JSONDecoder().raw_decode(content)
callback(answer, server=server, context=context)
content = content[index:]
except ValueError: # Partial JSON
self._buffer[context["query_id"]] = content
else:
callback(content, server=server, context=context)
def _timeoutSlot(self, response, timeout):
"""
Beware it's call for all request you need to check the status of the response
"""
# We check if we received HTTP headers
if not sip.isdeleted(response) and response.isRunning() and not len(response.rawHeaderList()) > 0:
if not response.error() != QtNetwork.QNetworkReply.NoError:
log.warning("Timeout after {} seconds for request {}. Please check the connection is not blocked by a firewall or an anti-virus.".format(timeout, response.url().toString()))
response.abort()
def disconnect(self):
"""
Disconnect from the remote server
"""
self.connection_disconnected_signal.emit()
self.close()
def _requestCanceled(self, response, context):
if response.isRunning() and not response.error() != QtNetwork.QNetworkReply.NoError:
log.warning("Aborting request for {}".format(response.url().toString()))
response.abort()
if "query_id" in context:
self._notify_progress_end_query(context["query_id"])
def _processError(self, response, server, callback, context, request_body, ignore_errors, error_code):
if error_code != QtNetwork.QNetworkReply.NoError:
error_message = "{} ({}:{})".format(response.errorString(), self._host, self._port)
if not ignore_errors:
log.debug("Response error: %s for %s (error: %d)", error_message, response.url().toString(), error_code)
if "query_id" in context:
self._notify_progress_end_query(context["query_id"])
if error_code < 200 or error_code == 403:
if error_code == QtNetwork.QNetworkReply.OperationCanceledError: # It's legit to cancel do not disconnect
error_message = "Operation timeout" # It's clearer than cancel because cancel is triggered by us when we timeout
elif error_code == QtNetwork.QNetworkReply.NetworkSessionFailedError:
# ignore the network session failed error to let the network manager recover from it
return
elif not ignore_errors:
self.disconnect()
if callback is not None:
callback({"message": error_message}, error=True, server=server, context=context)
return
else:
status = response.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute)
if status == 401:
log.error(error_message)
try:
body = bytes(response.readAll()).decode("utf-8").strip("\0")
# Some time antivirus intercept our query and reply with garbage content
except UnicodeError:
body = None
content_type = response.header(QtNetwork.QNetworkRequest.ContentTypeHeader)
if callback is not None:
if not body or content_type != "application/json":
callback({"message": error_message}, error=True, server=server, context=context)
else:
# log.debug(body)
try:
callback(json.loads(body), error=True, server=server, context=context)
except ValueError:
# It happens when an antivirus catch the communication and send is error page without changing the Content Type
callback({"message": error_message}, error=True, server=server, context=context)
else:
# Because nothing is configured to handle the error we display it to the user
try:
log.error(json.loads(body)["message"])
except (ValueError, KeyError):
log.error(error_message)
def _processResponse(self, response, server, callback, context, request_body, ignore_errors):
if request_body is not None:
request_body.close()
if "query_id" in context:
self._notify_progress_end_query(context["query_id"])
if response.error() == QtNetwork.QNetworkReply.NoError:
status = response.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute)
log.debug("Decoding response from {} response {}".format(response.url().toString(), status))
try:
raw_body = bytes(response.readAll())
body = raw_body.decode("utf-8").strip("\0")
# Some time anti-virus intercept our query and reply with garbage content
except UnicodeDecodeError:
body = None
content_type = response.header(QtNetwork.QNetworkRequest.ContentTypeHeader)
if body and len(body.strip(" \n\t")) > 0 and content_type == "application/json":
try:
params = json.loads(body)
except ValueError: # Partial JSON
params = {}
status = 504
else:
params = {}
if callback is not None:
if status >= 400:
callback(params, error=True, server=server, context=context)
else:
callback(params, server=server, context=context, raw_body=raw_body)
if status == 400:
try:
params = json.loads(body)
e = HttpBadRequest(body)
e.fingerprint = params["path"]
# If something goes wrong for a any reason just raise the bad request
except Exception:
e = HttpBadRequest(body)
raise e
def getSynchronous(self, method, endpoint, prefix="/v2", timeout=5):
"""
Synchronous check if a server is running
:returns: Tuple (Status code, json of answer). Status 0 is a non HTTP error
"""
host = self._getHostForQuery()
log.debug("{method} {protocol}://{host}:{port}{prefix}{endpoint}".format(method=method, protocol=self._protocol, host=host, port=self._port, prefix=prefix, endpoint=endpoint))
url = QtCore.QUrl("{protocol}://{host}:{port}{prefix}{endpoint}".format(protocol=self._protocol, host=host, port=self._port, prefix=prefix, endpoint=endpoint))
if self._user:
url.setUserName(self._user)
request = self._request(url)
request = self._addAuth(request)
request.setRawHeader(b"User-Agent", "GNS3 QT Client v{version}".format(version=__version__).encode())
try:
response = self._network_manager.sendCustomRequest(request, method.encode())
except SystemError as e:
log.error("Can't send query: {}".format(str(e)))
return
loop = QtCore.QEventLoop()
response.finished.connect(loop.quit)
if timeout is not None:
QtCore.QTimer.singleShot(timeout * 1000, qpartial(self._timeoutSlot, response, timeout))
if not loop.isRunning():
loop.exec_()
status = response.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute)
if response.error() != QtNetwork.QNetworkReply.NoError:
log.debug("Error while connecting to local server {}".format(response.errorString()))
else:
content_type = response.header(QtNetwork.QNetworkRequest.ContentTypeHeader)
if status == 200 and content_type == "application/json":
content = bytes(response.readAll())
try:
json_data = json.loads(content.decode("utf-8"))
except (UnicodeEncodeError, ValueError) as e:
log.warning("Could not read JSON data returned from {}: {}".format(url, e))
else:
return status, json_data
return status, None
def _sslErrorsSlot(self, response, ssl_errors):
self.handleSslError(response, ssl_errors)
def handleSslError(self, response, ssl_errors):
if self._accept_insecure_certificate:
response.ignoreSslErrors()
return
url = response.request().url()
host_port_key = f"{url.host()}:{url.port()}"
# get the certificate digest
ssl_config = response.sslConfiguration()
peer_cert = ssl_config.peerCertificate()
digest = peer_cert.digest()
if host_port_key in self._ssl_exceptions:
if self._ssl_exceptions[host_port_key] == digest:
response.ignoreSslErrors()
return
from gns3.main_window import MainWindow
main_window = MainWindow.instance()
msgbox = QtWidgets.QMessageBox(main_window)
msgbox.setWindowTitle("SSL error detected")
msgbox.setText(f"This server could not prove that it is {url.host()}:{url.port()}. Please carefully examine the certificate to make sure the server can be trusted.")
msgbox.setInformativeText(f"{ssl_errors[0].errorString()}")
msgbox.setDetailedText(peer_cert.toText())
msgbox.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
connect_button = QtWidgets.QPushButton(f"&Connect to {url.host()}:{url.port()}", msgbox)
msgbox.addButton(connect_button, QtWidgets.QMessageBox.YesRole)
abort_button = QtWidgets.QPushButton("&Abort", msgbox)
msgbox.addButton(abort_button, QtWidgets.QMessageBox.RejectRole)
msgbox.setDefaultButton(abort_button)
msgbox.setIcon(QtWidgets.QMessageBox.Critical)
msgbox.exec_()
if msgbox.clickedButton() == connect_button:
self._ssl_exceptions[host_port_key] = digest
response.ignoreSslErrors()
else:
for error in ssl_errors:
log.error(f"SSL error detected: {error.errorString()}")
main_window.close()
@classmethod
def fromUrl(cls, url, network_manager=None, base_settings=None):
"""
Returns HttpClient instance based on the url
:param url: Url to parse
:param network_manager: Optional network_manager
:param base_settings: Source of the settings, if necessary
:return: HttpClient
"""
settings = {}
if base_settings is not None:
settings.update(**base_settings)
parse_results = urllib.parse.urlparse(url)
settings['protocol'] = parse_results.scheme
settings['host'] = parse_results.hostname
settings['port'] = parse_results.port
settings['user'] = parse_results.username
settings['password'] = parse_results.password
return cls(settings, network_manager)

191
gns3/image_manager.py Normal file
View File

@@ -0,0 +1,191 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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 os
import copy
import pathlib
from gns3.qt import QtWidgets
from gns3.local_server_config import LocalServerConfig
from gns3.settings import LOCAL_SERVER_SETTINGS
from gns3.controller import Controller
from gns3.utils.file_copy_worker import FileCopyWorker
from gns3.utils.progress_dialog import ProgressDialog
from gns3.registry.image import Image
class ImageManager:
def __init__(self):
# Remember if we already ask the user about this image for this server
self._asked_for_this_image = {}
def _getUniqueDestinationPath(self, source_image, node_type, path):
"""
Get a unique destination path (with counter).
"""
if not os.path.exists(path):
return path
path, extension = os.path.splitext(path)
counter = 1
new_path = "{}-{}{}".format(path, counter, extension)
while os.path.exists(new_path):
destination_image = Image(node_type, new_path, filename=os.path.basename(new_path))
try:
if source_image.md5sum == destination_image.md5sum:
# the source and destination images are identical
return new_path
except OSError:
continue
counter += 1
new_path = "{}-{}{}".format(path, counter, extension)
return new_path
def askCopyUploadImage(self, parent, source_path, server, node_type):
"""
Ask user for copying the image to the default directory or upload
it to remote server.
:param parent: Parent window
:param path: File path on computer
:param server: The server where the images should be located
:param node_type: Remote upload endpoint
:returns path: Final path
"""
if (server and server != "local") or Controller.instance().isRemote():
return self._uploadImageToRemoteServer(source_path, server, node_type)
else:
destination_directory = self.getDirectoryForType(node_type)
destination_path = os.path.join(destination_directory, os.path.basename(source_path))
source_filename = os.path.basename(source_path)
destination_filename = os.path.basename(destination_path)
if os.path.normpath(os.path.dirname(source_path)) != destination_directory:
# the image is not in the default images directory
if source_filename == destination_filename:
# the filename already exists in the default images directory
source_image = Image(node_type, source_path, filename=source_filename)
destination_image = Image(node_type, destination_path, filename=destination_filename)
try:
if source_image.md5sum == destination_image.md5sum:
# the source and destination images are identical
return source_path
except OSError as e:
QtWidgets.QMessageBox.critical(parent, 'Image', 'Cannot compare image file {} with {}: {}.'.format(source_path, destination_path, str(e)))
return source_path
# find a new unique path to avoid overwriting existing destination file
destination_path = self._getUniqueDestinationPath(source_image, node_type, destination_path)
reply = QtWidgets.QMessageBox.question(parent,
'Image',
'Would you like to copy {} to the default images directory'.format(source_filename),
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
try:
os.makedirs(destination_directory, exist_ok=True)
except OSError as e:
QtWidgets.QMessageBox.critical(parent, 'Image', 'Could not create destination directory {}: {}'.format(destination_directory, str(e)))
return source_path
worker = FileCopyWorker(source_path, destination_path)
progress_dialog = ProgressDialog(worker, 'Image', 'Copying {}'.format(source_filename), 'Cancel', busy=True, parent=parent)
progress_dialog.show()
progress_dialog.exec_()
errors = progress_dialog.errors()
if errors:
QtWidgets.QMessageBox.critical(parent, 'Image', '{}'.format(''.join(errors)))
return source_path
else:
source_path = destination_path
return source_path
def _uploadImageToRemoteServer(self, path, server, node_type):
"""
Upload image to remote server
:param path: File path on computer
:param server: The server where the images should be located
:param node_type: Image node_type
:returns path: Final path
"""
if node_type == 'QEMU':
upload_endpoint = '/qemu/images'
elif node_type == 'IOU':
upload_endpoint = '/iou/images'
elif node_type == 'DYNAMIPS':
upload_endpoint = '/dynamips/images'
else:
raise Exception('Invalid node type')
filename = self._getRelativeImagePath(path, node_type).replace("\\", "/")
Controller.instance().postCompute('{}/{}'.format(upload_endpoint, filename), server, None, body=pathlib.Path(path), progressText="Uploading {}".format(filename), timeout=None)
return filename
def _getRelativeImagePath(self, path, node_type):
"""
Get a path relative to images directory path
or just filename if the path is not located inside
image directory
:param path: file path
:param node_type: Type of vm
:return: file path
"""
if not path:
return ""
img_directory = self.getDirectoryForType(node_type)
path = os.path.abspath(path)
if os.path.commonprefix([img_directory, path]) == img_directory:
return os.path.relpath(path, img_directory)
return os.path.basename(path)
def getDirectory(self):
"""
Returns the images directory path.
:returns: path to the default images directory
"""
return copy.copy(LocalServerConfig.instance().loadSettings("Server", LOCAL_SERVER_SETTINGS)['images_path'])
def getDirectoryForType(self, node_type):
"""
Return the path of local directory of the images
of a specific node_type
:param node_type: Type of vm
"""
if node_type == 'DYNAMIPS':
return os.path.join(self.getDirectory(), 'IOS')
else:
return os.path.join(self.getDirectory(), node_type.upper())
@staticmethod
def instance():
"""
Singleton to return only on instance of ImageManager.
:returns: instance of ImageManager
"""
if not hasattr(ImageManager, '_instance') or ImageManager._instance is None:
ImageManager._instance = ImageManager()
return ImageManager._instance

View File

@@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2017 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 os
import pathlib
import urllib.parse
from gns3.http_client import HTTPClient
import logging
log = logging.getLogger(__name__)
class ImageUploadManager(object):
"""
Manager over the image upload. Encapsulates file uploads to computes or via controller.
"""
def __init__(self, image, controller, compute_id, callback=None, directFileUpload=False):
self._image = image
self._compute_id = compute_id
self._callback = callback
self._directFileUpload = directFileUpload
self._controller = controller
def upload(self):
if not os.path.exists(self._image.path):
log.error("Image '{}' could not be found".format(self._image.path))
return
if self._directFileUpload:
# first obtain endpoint and know when target request
self._controller.getEndpoint(self._getComputePath(), self._compute_id, self._onLoadEndpointCallback, showProgress=False)
else:
self._fileUploadToController()
def _getComputePath(self):
return '/{emulator}/images/{filename}'.format(emulator=self._image.emulator, filename=self._image.filename)
def _onLoadEndpointCallback(self, result, error=False, **kwargs):
if error:
if "message" in result:
log.error("Error while getting endpoint: {}".format(result["message"]))
return
# we know where is the endpoint and we trying to post there a file
endpoint = result['endpoint']
self._fileUploadToCompute(endpoint)
def _checkIfSuccessfulCallback(self, result, error=False, **kwargs):
if error:
connection_error = kwargs.get('connection_error', False)
if connection_error:
log.debug("During direct file upload compute is not visible. Fallback to upload via controller.")
# there was an issue with connection, probably we don't have a direct access to compute
# we need to fallback to uploading files via controller
self._fileUploadToController()
else:
if "message" in result:
log.error("Error while direct file upload: {}".format(result["message"]))
return
self._callback(result, error, **kwargs)
def _fileUploadToCompute(self, endpoint):
log.debug("Uploading image '{}' to compute".format(self._image.path))
parse_results = urllib.parse.urlparse(endpoint)
network_manager = self._controller.getHttpClient().getNetworkManager()
client = HTTPClient.fromUrl(endpoint, network_manager=network_manager)
# We don't retry connection as in case of fail we try direct file upload
client.setMaxRetryConnection(0)
client.createHTTPQuery('POST', parse_results.path, self._checkIfSuccessfulCallback, body=pathlib.Path(self._image.path),
context={"image_path": self._image.path}, progressText="Uploading {}".format(self._image.filename), timeout=None, prefix="")
def _fileUploadToController(self):
log.debug("Uploading image '{}' to controller".format(self._image.path))
self._controller.postCompute(self._getComputePath(), self._compute_id, self._callback, body=pathlib.Path(self._image.path),
context={"image_path": self._image.path}, progressText="Uploading {}".format(self._image.filename), timeout=None)

311
gns3/items/drawing_item.py Normal file
View File

@@ -0,0 +1,311 @@
#!/usr/bin/env python
#
# Copyright (C) 2016 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/>.
from ..qt import QtCore, QtWidgets, qslot, QtGui
from .utils import colorFromSvg
import uuid
import logging
import binascii
log = logging.getLogger(__name__)
class DrawingItem:
# Map QT stroke to SVG style
QT_DASH_TO_SVG = {
QtCore.Qt.SolidLine: "",
QtCore.Qt.NoPen: None,
QtCore.Qt.DashLine: "25, 25",
QtCore.Qt.DotLine: "5, 25",
QtCore.Qt.DashDotLine: "5, 25, 25",
QtCore.Qt.DashDotDotLine: "25, 25, 5, 25, 5"
}
show_layer = False
"""
Base class for non emulation item
"""
def __init__(self, project=None, pos=None, drawing_id=None, svg=None, z=0, locked=False, rotation=0, **kws):
self._id = drawing_id
self._deleting = False
self._allow_snap_to_grid = True
self._locked = locked
if self._id is None:
self._id = str(uuid.uuid4())
self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable | QtWidgets.QGraphicsItem.ItemIsFocusable | QtWidgets.QGraphicsItem.ItemIsSelectable | QtWidgets.QGraphicsItem.ItemSendsGeometryChanges)
from ..main_window import MainWindow
self._graphics_view = MainWindow.instance().uiGraphicsView
self._main_window = MainWindow.instance()
self._project = project
# Store a hash of the SVG to avoid him
# to be send if he doesn't change
self._hash_svg = None
if pos:
self.setPos(pos)
if z:
self.setZValue(z)
if rotation:
self.setRotation(rotation)
self.setLocked(locked)
def drawing_id(self):
return self._id
def create(self):
if self._project:
self._project.post("/drawings", self._createDrawingCallback, body=self.__json__())
def _createDrawingCallback(self, result, error=False, **kwargs):
"""
Callback for create.
:param result: server response
:param error: indicates an error (boolean)
:returns: Boolean success or not
"""
if error:
log.error("Error while creating drawing: {}".format(result["message"]))
return False
self._id = result["drawing_id"]
self.updateDrawingCallback(result)
def updateDrawing(self):
if self._id and not self.deleting() and self._project:
self._project.put("/drawings/" + self._id, self.updateDrawingCallback, body=self.__json__(), showProgress=False)
@qslot
def updateDrawingCallback(self, result, error=False, **kwargs):
"""
Callback for update.
:param result: server response
:param error: indicates an error (boolean)
:returns: Boolean success or not
"""
if error:
log.error("Error while updating drawing: {}".format(result["message"]))
return False
self.setPos(QtCore.QPoint(result["x"], result["y"]))
self.setZValue(result["z"])
self.setLocked(result["locked"])
self.setRotation(result["rotation"])
if "svg" in result:
self.fromSvg(result["svg"])
def handleKeyPressEvent(self, event):
"""
Handles all key press events
:param event: QKeyEvent
:return: Boolean True the event has been captured
"""
key = event.key()
modifiers = event.modifiers()
if key in (QtCore.Qt.Key_P, QtCore.Qt.Key_Plus, QtCore.Qt.Key_Equal) and modifiers & QtCore.Qt.AltModifier \
or key == QtCore.Qt.Key_Plus and modifiers & QtCore.Qt.AltModifier and modifiers & QtCore.Qt.KeypadModifier:
if self.rotation() == 0:
self.setRotation(359)
else:
self.setRotation(self.rotation() - 1)
return True
elif key in (QtCore.Qt.Key_M, QtCore.Qt.Key_Minus) and modifiers & QtCore.Qt.AltModifier \
or key == QtCore.Qt.Key_Minus and modifiers & QtCore.Qt.AltModifier and modifiers & QtCore.Qt.KeypadModifier:
if self.rotation() < 360.0:
self.setRotation(self.rotation() + 1)
return True
elif modifiers & QtCore.Qt.AltModifier:
self._allow_snap_to_grid = False
return True
return False
def keyPressEvent(self, event):
"""
Handles all key press events
:param event: QKeyEvent
"""
if not self.handleKeyPressEvent(event):
QtWidgets.QGraphicsItem.keyPressEvent(self, event)
def keyReleaseEvent(self, event):
"""
Handles all key release events
:param event: QKeyEvent
"""
self._allow_snap_to_grid = True
def __json__(self):
data = {
"drawing_id": self._id,
"x": int(self.pos().x()),
"y": int(self.pos().y()),
"z": int(self.zValue()),
"locked": self._locked,
"rotation": int(self.rotation())
}
svg = self.toSvg()
hash_svg = binascii.crc32(svg.encode())
if hash_svg != self._hash_svg:
data["svg"] = svg
self._hash_svg = hash_svg
return data
def locked(self):
"""
Is the drawing locked
"""
return self._locked
def setLocked(self, locked):
"""
Sets the locked value.
:param value: Z value
"""
if locked is True:
self.setFlag(self.ItemIsMovable, False)
else:
self.setFlag(self.ItemIsMovable, True)
self._locked = locked
def deleting(self):
"""
Is the drawing being deleted
"""
return self._deleting
def setDeleting(self):
"""
Mark this drawing as being deleted
"""
self._deleting = True
def delete(self, skip_controller=False):
"""
Deletes this drawing.
:param skip_controller: Do not replicate change on the controller (usefull when it's already deleted on controller)
"""
self.setDeleting()
self.scene().removeItem(self)
from ..topology import Topology
Topology.instance().removeDrawing(self)
if self._id and not skip_controller:
self._project.delete("/drawings/" + self._id, None, body=self.__json__())
def itemChange(self, change, value):
if change == QtWidgets.QGraphicsItem.ItemPositionChange and self._main_window.uiSnapToGridAction.isChecked() \
and self._allow_snap_to_grid:
grid_size = self._graphics_view.drawingGridSize()
mid_x = self.boundingRect().width() / 2
value.setX((grid_size * round((value.x() + mid_x) / grid_size)) - mid_x)
mid_y = self.boundingRect().height() / 2
value.setY((grid_size * round((value.y()+mid_y)/grid_size)) - mid_y)
if change == QtWidgets.QGraphicsItem.ItemSelectedChange:
if not value:
self.updateDrawing()
return QtWidgets.QGraphicsItem.itemChange(self, change, value)
def updateNode(self):
self.updateDrawing()
def drawLayerInfo(self, painter):
"""
Draws the layer position.
:param painter: QPainter instance
"""
if self.show_layer is False:
return
brect = self.boundingRect()
# don't draw anything if the object is too small
if brect.width() < 20 or brect.height() < 20:
return
center = self.mapFromItem(self, brect.width() / 2.0, brect.height() / 2.0)
painter.setBrush(QtCore.Qt.red)
painter.setPen(QtCore.Qt.red)
painter.drawRect(QtCore.QRectF((brect.width() / 2.0) - 10, (brect.height() / 2.0) - 10, 20, 20))
painter.setPen(QtCore.Qt.black)
zval = str(int(self.zValue()))
painter.drawText(QtCore.QPointF(center.x() - 4, center.y() + 4), zval)
def _styleSvg(self, element):
"""
Add style from the shape item to the SVG element that we will
export
"""
style = ""
pen = self.pen()
if hasattr(self, "brush"): # Line don't have a brush
element.set("fill", "#{}".format(hex(self.brush().color().rgba())[4:]))
element.set("fill-opacity", str(self.brush().color().alphaF()))
dasharray = self.QT_DASH_TO_SVG[pen.style()]
if dasharray is None: # No border to the element
return element
elif dasharray == "":
pass # Solid line
else:
element.set("stroke-dasharray", dasharray)
element.set("stroke-width", str(pen.width()))
element.set("stroke", "#" + hex(pen.color().rgba())[4:])
return element
def _penFromSVGElement(self, svg):
"""
Get a pen from a SVG element
:param svg:
"""
pen = QtGui.QPen()
if svg.get("stroke-width"):
pen.setWidth(int(svg.get("stroke-width")))
if svg.get("stroke"):
pen.setColor(colorFromSvg(svg.get("stroke")))
# Map SVG stroke style (border of the element to the Qt version)
if not svg.get("stroke"):
pen.setStyle(QtCore.Qt.NoPen)
else:
pen.setStyle(QtCore.Qt.SolidLine)
stroke = svg.get("stroke-dasharray")
if stroke:
for (qt_stroke, svg_stroke) in self.QT_DASH_TO_SVG.items():
if svg_stroke == stroke:
pen.setStyle(qt_stroke)
return pen

View File

@@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Graphical representation of an ellipse on the QGraphicsScene.
"""
import math
import xml.etree.ElementTree as ET
from ..qt import QtWidgets
from .shape_item import ShapeItem
class EllipseItem(QtWidgets.QGraphicsEllipseItem, ShapeItem):
"""
Class to draw an ellipse on the scene.
"""
def __init__(self, width=200, height=200, **kws):
super().__init__(width=width, height=height, **kws)
def paint(self, painter, option, widget=None):
"""
Paints the contents of an item in local coordinates.
:param painter: QPainter instance
:param option: QStyleOptionGraphicsItem instance
:param widget: QWidget instance
"""
super().paint(painter, option, widget)
self.drawLayerInfo(painter)
def toSvg(self):
"""
Return an SVG version of the shape
"""
svg = ET.Element("svg")
svg.set("width", str(self.rect().width()))
svg.set("height", str(self.rect().height()))
ellipse = ET.SubElement(svg, "ellipse")
ellipse.set("cx", str(math.floor(self.rect().width() / 2)))
ellipse.set("rx", str(math.ceil(self.rect().width() / 2)))
ellipse.set("cy", str(math.floor(self.rect().height() / 2)))
ellipse.set("ry", str(math.ceil(self.rect().height() / 2)))
ellipse = self._styleSvg(ellipse)
return ET.tostring(svg, encoding="utf-8").decode("utf-8")

View File

@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Pekka Helenius
# Copyright (C) 2014 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
@@ -19,12 +20,14 @@
Graphical representation of an Ethernet link for QGraphicsScene.
"""
from ..qt import QtCore, QtGui
from ..qt import QtCore, QtGui, QtWidgets
from .link_item import LinkItem
from .label_item import LabelItem
from ..ports.port import Port
class EthernetLinkItem(LinkItem):
"""
Ethernet link for the scene.
@@ -34,13 +37,11 @@ class EthernetLinkItem(LinkItem):
:param destination_port: destination Port instance
:param link: Link instance (contains back-end stuff for this link)
:param adding_flag: indicates if this link is being added (no destination yet)
:param multilink: used to draw multiple link between the same source and destination
"""
def __init__(self, source_item, source_port, destination_item, destination_port, link=None, adding_flag=False, multilink=0):
def __init__(self, source_item, source_port, destination_item, destination_port, link=None, adding_flag=False):
LinkItem.__init__(self, source_item, source_port, destination_item, destination_port, link, adding_flag, multilink)
self.setPen(QtGui.QPen(QtCore.Qt.black, self._pen_width, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
super().__init__(source_item, source_port, destination_item, destination_port, link, adding_flag)
self._source_collision_offset = 0.0
self._destination_collision_offset = 0.0
@@ -51,10 +52,21 @@ class EthernetLinkItem(LinkItem):
LinkItem.adjust(self)
try:
if self._hovered:
self.setPen(QtGui.QPen(QtCore.Qt.red, self._link._link_style["width"] + 1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
else:
self.setPen(QtGui.QPen(QtGui.QColor(self._link._link_style["color"]), self._link._link_style["width"], self._link._link_style["type"], QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
except:
if self._hovered:
self.setPen(QtGui.QPen(QtCore.Qt.red, self._pen_width + 1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
else:
self.setPen(QtGui.QPen(QtGui.QColor("#000000"), self._pen_width, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
# draw a line between nodes
self.path = QtGui.QPainterPath(self.source)
self.path.lineTo(self.destination)
self.setPath(self.path)
path = QtGui.QPainterPath(self.source)
path.lineTo(self.destination)
self.setPath(path)
# offset on the line for status points
if self.length == 0:
@@ -69,7 +81,7 @@ class EthernetLinkItem(LinkItem):
:returns: QPainterPath instance
"""
path = QtGui.QGraphicsPathItem.shape(self)
path = QtWidgets.QGraphicsPathItem.shape(self)
offset = self._point_size / 2
if not self._adding_flag:
if self.length:
@@ -100,24 +112,26 @@ class EthernetLinkItem(LinkItem):
:param widget: QWidget instance.
"""
QtGui.QGraphicsPathItem.paint(self, painter, option, widget)
if not self._adding_flag and self._settings["draw_link_status_points"]:
QtWidgets.QGraphicsPathItem.paint(self, painter, option, widget)
if not self._adding_flag:
# points disappears if nodes are too close to each others.
if self.length < 100:
return
if self._source_port.status() == Port.started:
if self._link.suspended() or self._source_port.status() == Port.suspended:
# link or port is suspended
color = QtCore.Qt.yellow
shape = QtCore.Qt.RoundCap
elif self._source_port.status() == Port.started:
# port is active
color = QtCore.Qt.green
elif self._source_port.status() == Port.suspended:
# port is suspended
color = QtCore.Qt.yellow
shape = QtCore.Qt.RoundCap
else:
color = QtCore.Qt.red
shape = QtCore.Qt.SquareCap
painter.setPen(QtGui.QPen(color, self._point_size, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.MiterJoin))
painter.setPen(QtGui.QPen(color, self._point_size, QtCore.Qt.SolidLine, shape, QtCore.Qt.MiterJoin))
point1 = QtCore.QPointF(self.source + self.edge_offset) + QtCore.QPointF((self.dx * self._source_collision_offset) / self.length, (self.dy * self._source_collision_offset) / self.length)
# avoid any collision of the status point with the source node
@@ -131,49 +145,36 @@ class EthernetLinkItem(LinkItem):
if not self._source_item.contains(self.mapFromScene(self.mapToItem(self._source_item, check_point))) and self._source_collision_offset > 0:
self._source_collision_offset -= 10
#TODO: draw port labels
# if self._show_port_names:
# if self.labelSouceIf == None:
#
# if globals.interfaceLabels.has_key(self.source.hostname + ' ' + self.srcIf):
# self.labelSouceIf = Annotation(self.source)
# annotation = globals.interfaceLabels[self.source.hostname + ' ' + self.srcIf]
# self.labelSouceIf.setZValue(annotation.zValue())
# self.labelSouceIf.setDefaultTextColor(annotation.defaultTextColor())
# self.labelSouceIf.setFont(annotation.font())
# self.labelSouceIf.setPlainText(annotation.toPlainText())
# self.labelSouceIf.setPos(annotation.x(), annotation.y())
# self.labelSouceIf.rotation = annotation.rotation
# self.labelSouceIf.rotate(annotation.rotation)
# del globals.interfaceLabels[self.source.hostname + ' ' + self.srcIf]
# elif not globals.GApp.workspace.flg_showOnlySavedInterfaceNames:
# self.labelSouceIf = Annotation(self.source)
# self.labelSouceIf.setPlainText(self.srcIf)
# self.labelSouceIf.setPos(self.mapToItem(self.source, point1))
# #self.labelSouceIf.autoGenerated = True
#
# if self.labelSouceIf:
# self.labelSouceIf.deviceName = self.source.hostname
# self.labelSouceIf.deviceIf = self.srcIf
#
# if self.labelSouceIf and not self.labelSouceIf.isVisible():
# self.labelSouceIf.show()
#
# elif self.labelSouceIf and globals.GApp.workspace.flg_showInterfaceNames == False:
# self.labelSouceIf.hide()
source_port_label = self._source_port.label()
painter.drawPoint(point1)
if source_port_label is None:
source_port_label = LabelItem(self._source_item)
source_port_label.setPlainText(self._source_port.shortName())
source_port_label.setPos(self.mapToItem(self._source_item, point1))
self._source_port.setLabel(source_port_label)
if self._destination_port.status() == Port.started:
if self._draw_port_labels:
source_port_label.setFlag(source_port_label.ItemIsMovable, not self._source_item.locked())
source_port_label.show()
else:
source_port_label.hide()
if self._settings["draw_link_status_points"] and self.pen().style() != QtCore.Qt.NoPen:
painter.drawPoint(point1)
if self._link.suspended() or self._destination_port.status() == Port.suspended:
# link or port is suspended
color = QtCore.Qt.yellow
shape = QtCore.Qt.RoundCap
elif self._destination_port.status() == Port.started:
# port is active
color = QtCore.Qt.green
elif self._destination_port.status() == Port.suspended:
# port is suspended
color = QtCore.Qt.yellow
shape = QtCore.Qt.RoundCap
else:
color = QtCore.Qt.red
shape = QtCore.Qt.SquareCap
painter.setPen(QtGui.QPen(color, self._point_size, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.MiterJoin))
painter.setPen(QtGui.QPen(color, self._point_size, QtCore.Qt.SolidLine, shape, QtCore.Qt.MiterJoin))
point2 = QtCore.QPointF(self.destination - self.edge_offset) - QtCore.QPointF((self.dx * self._destination_collision_offset) / self.length, (self.dy * self._destination_collision_offset) / self.length)
# avoid any collision of the status point with the destination node
@@ -187,35 +188,21 @@ class EthernetLinkItem(LinkItem):
if not self._destination_item.contains(self.mapFromScene(self.mapToItem(self._destination_item, check_point))) and self._destination_collision_offset > 0:
self._destination_collision_offset -= 10
#TODO: draw port labels
# if globals.GApp.workspace.flg_showInterfaceNames:
# if self.labelDestIf == None:
#
# if globals.interfaceLabels.has_key(self.dest.hostname + ' ' + self.destIf):
# self.labelDestIf = Annotation(self.dest)
# annotation = globals.interfaceLabels[self.dest.hostname + ' ' + self.destIf]
# self.labelDestIf.setZValue(annotation.zValue())
# self.labelDestIf.setDefaultTextColor(annotation.defaultTextColor())
# self.labelDestIf.setFont(annotation.font())
# self.labelDestIf.setPlainText(annotation.toPlainText())
# self.labelDestIf.setPos(annotation.x(), annotation.y())
# self.labelDestIf.rotation = annotation.rotation
# self.labelDestIf.rotate(annotation.rotation)
# del globals.interfaceLabels[self.dest.hostname + ' ' + self.destIf]
# elif not globals.GApp.workspace.flg_showOnlySavedInterfaceNames:
# self.labelDestIf = Annotation(self.dest)
# self.labelDestIf.setPlainText(self.destIf)
# self.labelDestIf.setPos(self.mapToItem(self.dest, point2))
# #self.labelDestIf.autoGenerated = True
#
# if self.labelDestIf:
# self.labelDestIf.deviceName = self.dest.hostname
# self.labelDestIf.deviceIf = self.destIf
#
# if self.labelDestIf and not self.labelDestIf.isVisible():
# self.labelDestIf.show()
#
# elif self.labelDestIf and globals.GApp.workspace.flg_showInterfaceNames == False:
# self.labelDestIf.hide()
destination_port_label = self._destination_port.label()
painter.drawPoint(point2)
if destination_port_label is None:
destination_port_label = LabelItem(self._destination_item)
destination_port_label.setPlainText(self._destination_port.shortName())
destination_port_label.setPos(self.mapToItem(self._destination_item, point2))
self._destination_port.setLabel(destination_port_label)
if self._draw_port_labels:
destination_port_label.setFlag(destination_port_label.ItemIsMovable, not self._destination_item.locked())
destination_port_label.show()
else:
destination_port_label.hide()
if self._settings["draw_link_status_points"] and self.pen().style() != QtCore.Qt.NoPen:
painter.drawPoint(point2)
self._drawSymbol()

78
gns3/items/image_item.py Normal file
View File

@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Graphical representation of an image on the QGraphicsScene.
"""
from ..qt import QtSvg
from ..qt.qimage_svg_renderer import QImageSvgRenderer
from .drawing_item import DrawingItem
class ImageItem(QtSvg.QGraphicsSvgItem, DrawingItem):
"""
Class to insert an image on the scene.
"""
def __init__(self, image_path=None, pos=None, svg=None, **kws):
self._image_path = image_path
# Because we call the Qt C++ code we need to handle the case of pos is None otherwise we will get a conversion error
if pos:
super().__init__(pos=pos, **kws)
else:
super().__init__(**kws)
if self._image_path:
renderer = QImageSvgRenderer(image_path)
self.setSharedRenderer(renderer)
# By default center the image
if pos is None:
x = self.pos().x() - (self.boundingRect().width() / 2)
y = self.pos().y() - (self.boundingRect().height() / 2)
self.setPos(x, y)
if svg:
svg = self.fromSvg(svg)
if 'z' in kws.keys():
self.setZValue(kws['z'])
def paint(self, painter, option, widget=None):
"""
Paints the contents of an item in local coordinates.
:param painter: QPainter instance
:param option: QStyleOptionGraphicsItem instance
:param widget: QWidget instance
"""
super().paint(painter, option, widget)
self.drawLayerInfo(painter)
def fromSvg(self, svg):
renderer = QImageSvgRenderer(svg)
self.setSharedRenderer(renderer)
def toSvg(self):
"""
Return an SVG version of the shape
"""
return self.renderer().svg()

254
gns3/items/label_item.py Normal file
View File

@@ -0,0 +1,254 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
from ..qt import QtCore, QtWidgets, QtGui
from .utils import colorFromSvg
class LabelItem(QtWidgets.QGraphicsTextItem):
"""
Label for links and nodes.
:param parent: optional parent
"""
item_unselected_signal = QtCore.Signal()
show_layer = False
def __init__(self, parent=None):
super().__init__(parent)
from ..main_window import MainWindow
main_window = MainWindow.instance()
view_settings = main_window.uiGraphicsView.settings()
qt_font = QtGui.QFont()
qt_font.fromString(view_settings["default_label_font"])
self.setDefaultTextColor(QtGui.QColor(view_settings["default_label_color"]))
self.setFont(qt_font)
self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable | QtWidgets.QGraphicsItem.ItemIsSelectable)
self.setZValue(2)
self._editable = True
def delete(self):
"""
Deletes this note.
"""
if not self.scene():
# object already deleted by its parent
return
self.scene().removeItem(self)
from ..topology import Topology
Topology.instance().removeNote(self)
def editable(self):
"""
Returns either the note is editable or not.
:return: boolean
"""
return self._editable
def setEditable(self, value):
"""
Sets the note has editable or not.
:param value: boolean
"""
self._editable = value
# if not self._editable:
# self.setFlag(self.ItemIsSelectable, enabled=False)
# else:
# self.setFlag(self.ItemIsSelectable)
def keyPressEvent(self, event):
"""
Handles all key press events
:param event: QKeyEvent
"""
key = event.key()
modifiers = event.modifiers()
if key in (QtCore.Qt.Key_P, QtCore.Qt.Key_Plus, QtCore.Qt.Key_Equal) and modifiers & QtCore.Qt.AltModifier \
or key == QtCore.Qt.Key_Plus and modifiers & QtCore.Qt.AltModifier and modifiers & QtCore.Qt.KeypadModifier:
if self.rotation() > -360.0:
self.setRotation(self.rotation() - 1)
elif key in (QtCore.Qt.Key_M, QtCore.Qt.Key_Minus) and modifiers & QtCore.Qt.AltModifier \
or key == QtCore.Qt.Key_Minus and modifiers & QtCore.Qt.AltModifier and modifiers & QtCore.Qt.KeypadModifier:
if self.rotation() < 360.0:
self.setRotation(self.rotation() + 1)
else:
super().keyPressEvent(event)
def editText(self):
"""
Edit mode for this note.
"""
self.setTextInteractionFlags(QtCore.Qt.TextEditorInteraction)
self.setSelected(True)
self.setFocus()
cursor = self.textCursor()
cursor.select(QtGui.QTextCursor.Document)
self.setTextCursor(cursor)
def mouseDoubleClickEvent(self, event):
"""
Handles all mouse double click events.
:param event: QMouseEvent instance
"""
if self._editable:
self.editText()
def focusOutEvent(self, event):
"""
Handles all focus out events.
:param event: QFocusEvent instance
"""
self.setFlag(QtWidgets.QGraphicsItem.ItemIsFocusable, False)
cursor = self.textCursor()
if cursor.hasSelection():
cursor.clearSelection()
self.setTextCursor(cursor)
self.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
if not self.toPlainText():
# delete the note if empty
self.delete()
return
return super().focusOutEvent(event)
def paint(self, painter, option, widget=None):
"""
Paints the contents of an item in local coordinates.
:param painter: QPainter instance
:param option: QStyleOptionGraphicsItem instance
:param widget: QWidget instance
"""
super().paint(painter, option, widget)
if self.show_layer is False or self.parentItem():
return
brect = self.boundingRect()
# don't draw anything if the object is too small
if brect.width() < 20 or brect.height() < 20:
return
center = self.mapFromItem(self, brect.width() / 2.0, brect.height() / 2.0)
painter.setBrush(QtCore.Qt.red)
painter.setPen(QtCore.Qt.red)
painter.drawRect(QtCore.QRectF((brect.width() / 2.0) - 10, (brect.height() / 2.0) - 10, 20, 20))
painter.setPen(QtCore.Qt.black)
zval = str(int(self.zValue()))
painter.drawText(QtCore.QPointF(center.x(), center.y()), zval)
def setStyle(self, new_style):
"""
Set text style using a SVG style
"""
font = QtGui.QFont()
for style in new_style.split(";"):
if ":" in style:
key, val = style.split(":")
key = key.strip()
val = val.strip()
if key == "font-size":
font.setPointSizeF(float(val))
elif key == "font-family":
font.setFamily(val)
elif key == "font-style" and val == "italic":
font.setItalic(True)
elif key == "font-weight" and val == "bold":
font.setBold(True)
elif key == "text-decoration" and val == "underline":
font.setUnderline(True)
elif key == "text-decoration" and val == "line-through":
font.setStrikeOut(True)
elif key == "fill":
new_color = colorFromSvg(val)
color = self.defaultTextColor()
color.setBlue(new_color.blue())
color.setRed(new_color.red())
color.setGreen(new_color.green())
self.setDefaultTextColor(color)
elif key == "fill-opacity":
color = self.defaultTextColor()
color.setAlphaF(float(val))
self.setDefaultTextColor(color)
self.setFont(font)
def itemChange(self, change, value):
"""
Notifies this node item that some part of the item's state changes.
:param change: GraphicsItemChange type
:param value: value of the change
"""
if change == QtWidgets.QGraphicsItem.ItemSelectedChange:
if value == 0:
self.item_unselected_signal.emit()
return super().itemChange(change, value)
def dump(self):
"""
Returns a representation of this note.
:returns: dictionary
"""
note_info = {"text": self.toPlainText(),
"x": int(self.x()),
"y": int(self.y()),
"rotation": int(self.rotation())}
style = ""
style += "font-family: {};".format(self.font().family())
style += "font-size: {};".format(self.font().pointSizeF())
if self.font().italic():
style += "font-style: italic;"
if self.font().bold():
style += "font-weight: bold;"
if self.font().strikeOut():
style += "text-decoration: line-through;"
elif self.font().underline():
style += "text-decoration: underline;"
style += "fill: {};".format("#" + hex(self.defaultTextColor().rgba())[4:])
style += "fill-opacity: {};".format(self.defaultTextColor().alphaF())
note_info["style"] = style
return note_info

216
gns3/items/line_item.py Normal file
View File

@@ -0,0 +1,216 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Graphical representation of a rectangle on the QGraphicsScene.
"""
import xml.etree.ElementTree as ET
from ..qt import QtCore, QtGui, QtWidgets
from .drawing_item import DrawingItem
class LineItem(QtWidgets.QGraphicsLineItem, DrawingItem):
"""
Class to draw a rectangle on the scene.
"""
def __init__(self, dst=None, svg=None, **kws):
super().__init__(svg=svg, **kws)
self.setAcceptHoverEvents(True)
self._edge = None
self._border = 20
if svg is None:
if dst is not None:
self.setLine(0,
0,
dst.x(),
dst.y())
pen = QtGui.QPen(QtCore.Qt.black, 2, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
self.setPen(pen)
else:
self.fromSvg(svg)
if self._id is None:
self.create()
def paint(self, painter, option, widget=None):
"""
Paints the contents of an item in local coordinates.
:param painter: QPainter instance
:param option: QStyleOptionGraphicsItem instance
:param widget: QWidget instance
"""
super().paint(painter, option, widget)
self.drawLayerInfo(painter)
def toSvg(self):
"""
Return an SVG version of the shape
"""
svg = ET.Element("svg")
width = abs(self.line().x1() - self.line().x2())
height = abs(self.line().y1() - self.line().y2())
svg.set("width", str(int(width)))
svg.set("height", str(int(height)))
line = ET.SubElement(svg, "line")
line.set("x1", str(int(self.line().x1())))
line.set("x2", str(int(self.line().x2())))
line.set("y1", str(int(self.line().y1())))
line.set("y2", str(int(self.line().y2())))
line = self._styleSvg(line)
return ET.tostring(svg, encoding="utf-8").decode("utf-8")
def fromSvg(self, svg):
"""
Import element informations from an SVG
"""
svg = ET.fromstring(svg)
width = float(svg.get("width", 0))
height = float(svg.get("height", 0))
# Backup the pos and restore it
pos = self.pos()
y1 = self.line().y1()
self.setLine(0, 0, width, height)
pen = QtGui.QPen()
if len(svg):
pen = self._penFromSVGElement(svg[0])
self.setLine(
float(svg[0].get("x1")),
float(svg[0].get("y1")),
float(svg[0].get("x2")),
float(svg[0].get("y2"))
)
self.setPos(pos)
self.setPen(pen)
self.update()
def _isHorizontalLine(self):
return abs(self.line().x1() - self.line().x2()) > abs(self.line().y1() - self.line().y2())
def hoverMoveEvent(self, event):
"""
Handles all hover move events.
:param event: QGraphicsSceneHoverEvent instance
"""
# locked objects don't need cursors
if not self.locked():
if self._isHorizontalLine():
if event.pos().x() > (self.line().x2() - self._border):
self._graphics_view.setCursor(QtCore.Qt.SizeHorCursor)
elif event.pos().x() < self._border:
self._graphics_view.setCursor(QtCore.Qt.SizeHorCursor)
else:
self._graphics_view.setCursor(QtCore.Qt.SizeAllCursor)
# Vertical line
else:
if event.pos().y() > (self.line().y2() - self._border):
self._graphics_view.setCursor(QtCore.Qt.SizeVerCursor)
elif event.pos().y() < self._border:
self._graphics_view.setCursor(QtCore.Qt.SizeVerCursor)
else:
self._graphics_view.setCursor(QtCore.Qt.SizeAllCursor)
def mouseMoveEvent(self, event):
"""
Handles all mouse move events.
:param event: QMouseEvent instance
"""
self.update()
if self._edge:
scenePos = event.scenePos()
if self._edge == "left" or self._edge == "bottom":
diff_x = self.x() - scenePos.x()
diff_y = self.y() - scenePos.y()
self.setPos(scenePos.x(), scenePos.y())
self.setLine(
0,
0,
self.line().x2() + diff_x,
self.line().y2() + diff_y)
elif self._edge == "right" or self._edge == "top":
pos = self.mapFromScene(scenePos)
self.setLine(
0,
0,
pos.x(),
pos.y())
self.setPos(self.x(), self.y())
super().mouseMoveEvent(event)
def mousePressEvent(self, event):
"""
Handles all mouse press events.
:param event: QMouseEvent instance
"""
self.update()
if self._isHorizontalLine():
if event.pos().x() > (self.line().x2() - self._border):
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
self._edge = "right"
elif event.pos().x() < (self.line().x1() + self._border):
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
self._edge = "left"
else:
if event.pos().y() > (self.line().y2() - self._border):
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
self._edge = "top"
elif event.pos().y() < (self.line().y1() + self._border):
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
self._edge = "bottom"
super().mousePressEvent(event)
def mouseReleaseEvent(self, event):
"""
Handles all mouse release events.
:param: QMouseEvent instance
"""
self.update()
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
self._edge = None
super().mouseReleaseEvent(event)
def hoverLeaveEvent(self, event):
"""
Handles all hover leave events.
:param event: QGraphicsSceneHoverEvent instance
"""
# locked objects don't need cursors
if not self.locked():
self._graphics_view.setCursor(QtCore.Qt.ArrowCursor)

View File

@@ -21,10 +21,29 @@ Link items are graphical representation of a link on the QGraphicsScene
"""
import math
from ..qt import QtCore, QtGui
from ..qt import QtCore, QtGui, QtWidgets, QtSvg, qslot, sip_is_deleted
from ..packet_capture import PacketCapture
from ..dialogs.filter_dialog import FilterDialog
from ..dialogs.style_editor_dialog_link import StyleEditorDialogLink
from ..utils.get_icon import get_icon
class LinkItem(QtGui.QGraphicsPathItem):
class SvgIconItem(QtSvg.QGraphicsSvgItem):
def __init__(self, symbol, parent):
QtSvg.QGraphicsSvgItem.__init__(self, symbol, parent)
def mousePressEvent(self, event):
if self.parentItem():
self.parentItem().mousePressEvent(event)
event.accept()
class LinkItem(QtWidgets.QGraphicsPathItem):
"""
Base class for link items.
@@ -34,17 +53,21 @@ class LinkItem(QtGui.QGraphicsPathItem):
:param destination_port: destination Port instance
:param link: Link instance (contains back-end stuff for this link)
:param adding_flag: indicates if this link is being added (no destination yet)
:param multilink: used to draw multiple link between the same source and destination
"""
def __init__(self, source_item, source_port, destination_item, destination_port, link=None, adding_flag=False, multilink=0):
_draw_port_labels = False
delete_link_item_signal = QtCore.pyqtSignal(str)
QtGui.QGraphicsPathItem.__init__(self)
self.setZValue(-1)
def __init__(self, source_item, source_port, destination_item, destination_port, link=None, adding_flag=False):
super().__init__()
self.setAcceptHoverEvents(True)
self.setZValue(-0.5)
self._link = None
from ..main_window import MainWindow
self._settings = MainWindow.instance().uiGraphicsView.settings()
self._main_window = MainWindow.instance()
self._settings = self._main_window.uiGraphicsView.settings()
# indicates link is being added:
# source has been chosen but not its destination yet
@@ -56,48 +79,33 @@ class LinkItem(QtGui.QGraphicsPathItem):
# default pen size
self._pen_width = 2.0
# indicates the link position when there are multiple links
# between the same source and destination
self._multilink = multilink
# source & destination items and ports
self._source_item = source_item
self._destination_item = destination_item
self._source_port = source_port
self._destination_port = destination_port
# indicates if the link is being hovered
self._hovered = False
# QGraphicsSvgItem to indicate a capture
self._capturing_item = None
# QGraphicsSvgItem to indicate a filter is applied
self._filter_item = None
# QGraphicsSvgItem to indicate we suspend a link
self._suspend_item = None
# QGraphicsSvgItem to indicate a filter is applied and a capture is active
self._filter_capturing_item = None
if not self._adding_flag:
# there is a destination
self._link = link
# links must always be below node items on the scene
min_zvalue = min([source_item.zValue(), destination_item.zValue()])
self.setZValue(min_zvalue - 1)
self._link.updated_link_signal.connect(self._drawSymbol)
self._link.delete_link_signal.connect(self._linkDeletedSlot)
self.setFlag(self.ItemIsFocusable)
source_item.addLink(self)
destination_item.addLink(self)
#TODO: capture support
# source_item.node.nio_signal.connect(self.newNIOSlot)
# destination_item.node.nio_signal.connect(self.newNIOSlot)
# self._source_item.setCustomToolTip()
# self._destination_item.setCustomToolTip()
# self.capturing = False
# self.capfile = None
# self.captureInfo = None
# self.tailProcess = None
# self.capturePipeThread = None
# # Set default tooltip
# self.encapsulationTransform = { 'ETH': 'EN10MB',
# 'FR': 'FRELAY',
# 'HDLC': 'C_HDLC',
# 'PPP': 'PPP_SERIAL'}
self.setCustomToolTip()
else:
source_rect = self._source_item.boundingRect()
self.source = self.mapFromItem(self._source_item, source_rect.width() / 2.0, source_rect.height() / 2.0)
@@ -105,16 +113,60 @@ class LinkItem(QtGui.QGraphicsPathItem):
self.adjust()
@qslot
def _linkDeletedSlot(self, link_id, *args):
# first delete the port labels if any
if self._source_port.label():
self._source_port.label().setParentItem(None)
self.scene().removeItem(self._source_port.label())
if self._destination_port.label():
self._destination_port.label().setParentItem(None)
self.scene().removeItem(self._destination_port.label())
if self.scene():
if self in self.scene().items():
self.scene().removeItem(self)
@qslot
def _filterActionSlot(self, *args):
dialog = FilterDialog(self._main_window, self._link)
dialog.show()
dialog.exec_()
@qslot
def _suspendActionSlot(self, *args):
self._link.toggleSuspend()
@qslot
def _styleActionSlot(self, *args):
style_dialog = StyleEditorDialogLink(self, self._main_window)
style_dialog.show()
style_dialog.exec_()
def setLinkStyle(self, link_style):
self._link._link_style["color"] = link_style["color"]
self._link._link_style["width"] = link_style["width"]
self._link._link_style["type"] = link_style["type"]
# This refers to functions in link.py!
self._link.setLinkStyle(link_style)
self._link.update()
def delete(self):
"""
Delete this link
"""
self._source_item.removeLink(self)
self._destination_item.removeLink(self)
self._link.deleteLink()
if self in self.scene().items():
self.scene().removeItem(self)
def link(self):
"""
Returns the link attached to this link item.
:returns: Link instance
"""
return self._link
def setCustomToolTip(self):
"""
@@ -122,7 +174,7 @@ class LinkItem(QtGui.QGraphicsPathItem):
"""
if self._link:
self.setToolTip(self._link.description())
self.setToolTip(str(self._link))
def sourceItem(self):
"""
@@ -160,6 +212,89 @@ class LinkItem(QtGui.QGraphicsPathItem):
return self._destination_port
@classmethod
def showPortLabels(cls, state):
"""
Shows or hides port labels.
:param state: boolean
"""
cls._draw_port_labels = state
def resetPortLabels(self):
"""
Resets the port label positions.
"""
self._source_port.deleteLabel()
self._destination_port.deleteLabel()
def populateLinkContextualMenu(self, menu):
"""
Adds device actions to the link contextual menu.
:param menu: QMenu instance
"""
if not self._link.capturing():
# start capture
start_capture_action = QtWidgets.QAction("Start capture", menu)
start_capture_action.setIcon(get_icon('capture-start.svg'))
start_capture_action.triggered.connect(self._startCaptureActionSlot)
menu.addAction(start_capture_action)
if self._link.capturing():
# stop capture
stop_capture_action = QtWidgets.QAction("Stop capture", menu)
stop_capture_action.setIcon(get_icon('capture-stop.svg'))
stop_capture_action.triggered.connect(self._stopCaptureActionSlot)
menu.addAction(stop_capture_action)
# start wireshark
start_wireshark_action = QtWidgets.QAction("Start Wireshark", menu)
start_wireshark_action.setIcon(QtGui.QIcon(":/icons/wireshark.png"))
start_wireshark_action.triggered.connect(self._startWiresharkActionSlot)
menu.addAction(start_wireshark_action)
if PacketCapture.instance().packetAnalyzerAvailable():
analyze_action = QtWidgets.QAction("Analyze capture", menu)
analyze_action.setIcon(QtGui.QIcon(':/icons/rtv.png'))
analyze_action.triggered.connect(self._analyzeCaptureActionSlot)
menu.addAction(analyze_action)
if self._link.suspended() is False:
# Edit filters
filter_action = QtWidgets.QAction("Packet filters", menu)
filter_action.setIcon(get_icon('filter.svg'))
filter_action.triggered.connect(self._filterActionSlot)
menu.addAction(filter_action)
# Suspend link
suspend_action = QtWidgets.QAction("Suspend", menu)
suspend_action.setIcon(get_icon('pause.svg'))
suspend_action.triggered.connect(self._suspendActionSlot)
menu.addAction(suspend_action)
else:
# Resume link
resume_action = QtWidgets.QAction("Resume", menu)
resume_action.setIcon(get_icon('start.svg'))
resume_action.triggered.connect(self._suspendActionSlot)
menu.addAction(resume_action)
# style
style_action = QtWidgets.QAction("Style", menu)
style_action.setIcon(get_icon("node_conception.svg"))
style_action.triggered.connect(self._styleActionSlot)
menu.addAction(style_action)
# delete
delete_action = QtWidgets.QAction("Delete", menu)
delete_action.setIcon(get_icon('delete.svg'))
delete_action.triggered.connect(self._deleteActionSlot)
menu.addAction(delete_action)
@qslot
def mousePressEvent(self, event):
"""
Called when the link is clicked and shows a contextual menu.
@@ -167,21 +302,43 @@ class LinkItem(QtGui.QGraphicsPathItem):
:param: QGraphicsSceneMouseEvent instance
"""
if (event.button() == QtCore.Qt.RightButton):
if self._adding_flag:
# send a escape key to the main window to cancel the link addition
from ..main_window import MainWindow
key = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Escape, QtCore.Qt.NoModifier)
QtGui.QApplication.sendEvent(MainWindow.instance(), key)
return
if event.button() == QtCore.Qt.RightButton and self._adding_flag:
# send a escape key to the main window to cancel the link addition
from ..main_window import MainWindow
key = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Escape, QtCore.Qt.NoModifier)
QtWidgets.QApplication.sendEvent(MainWindow.instance(), key)
return
else:
super().mousePressEvent(event)
def contextMenuEvent(self, event):
"""
Handles all context menu events.
:param event: QContextMenuEvent instance
"""
if not sip_is_deleted(self):
# create the contextual menu
menu = QtGui.QMenu()
delete_action = QtGui.QAction("Delete", menu)
delete_action.setIcon(QtGui.QIcon(':/icons/delete.svg'))
delete_action.triggered.connect(self._deleteActionSlot)
menu.addAction(delete_action)
self.setHovered(True)
self.setAcceptHoverEvents(False)
menu = QtWidgets.QMenu()
self.populateLinkContextualMenu(menu)
menu.exec_(QtGui.QCursor.pos())
self.setAcceptHoverEvents(True)
self.setHovered(False)
def keyPressEvent(self, event):
"""
Handles all key press events
:param event: QKeyEvent
"""
# On pressing backspace or delete key, the selected link gets deleted
if event.key() == QtCore.Qt.Key_Delete or event.key() == QtCore.Qt.Key_Backspace:
self._deleteActionSlot()
return
def _deleteActionSlot(self):
"""
@@ -191,12 +348,84 @@ class LinkItem(QtGui.QGraphicsPathItem):
self.delete()
def _startCaptureActionSlot(self):
"""
Slot to receive events from the start capture action in the
contextual menu.
"""
PacketCapture.instance().startCapture(self._link)
def _stopCaptureActionSlot(self):
"""
Slot to receive events from the stop capture action in the
contextual menu.
"""
PacketCapture.instance().stopCapture(self._link)
def _startWiresharkActionSlot(self):
"""
Slot to receive events from the start Wireshark action in the
contextual menu.
"""
PacketCapture.instance().startPacketCaptureReader(self._link)
def _analyzeCaptureActionSlot(self):
"""
Slot to receive events from the analyze capture action in the
contextual menu.
"""
try:
PacketCapture.instance().startPacketCaptureAnalyzer(self._link)
except OSError as e:
QtWidgets.QMessageBox.critical(self._main_window, "Capture analyzer", "Cannot start the packet capture analyzer program: {}".format(e))
def setHovered(self, value):
"""
Sets the link as hovered or not.
:param value: boolean
"""
if value:
self._hovered = True
else:
self._hovered = False
self.adjust()
def hoverEnterEvent(self, event):
"""
Handles all hover enter events for this item.
:param event: QGraphicsSceneHoverEvent instance
"""
self.setHovered(True)
def hoverLeaveEvent(self, event):
"""
Handles all hover leave events for this item.
:param event: QGraphicsSceneHoverEvent instance
"""
self.setHovered(False)
@qslot
def adjust(self):
"""
Computes the source point and destination point.
Must be overloaded.
"""
# links must always be below node items on the scene
if not self._adding_flag:
min_zvalue = min([self._source_item.zValue(), self._destination_item.zValue()])
self.setZValue(min_zvalue - 0.5)
self.prepareGeometryChange()
source_rect = self._source_item.boundingRect()
self.source = self.mapFromItem(self._source_item, source_rect.width() / 2.0, source_rect.height() / 2.0)
@@ -213,15 +442,54 @@ class LinkItem(QtGui.QGraphicsPathItem):
# compute the length of the line
self.length = math.sqrt(self.dx * self.dx + self.dy * self.dy)
multilink = self._computeMultiLink()
# multi-link management
if not self._adding_flag and self._multilink and self.length:
if not self._adding_flag and multilink and self.length:
angle = math.radians(90)
self.dxrot = math.cos(angle) * self.dx - math.sin(angle) * self.dy
self.dyrot = math.sin(angle) * self.dx + math.cos(angle) * self.dy
offset = QtCore.QPointF((self.dxrot * (self._multilink * 5)) / self.length, (self.dyrot * (self._multilink * 5)) / self.length)
offset = QtCore.QPointF((self.dxrot * (multilink * 5)) / self.length, (self.dyrot * (multilink * 5)) / self.length)
self.source = QtCore.QPointF(self.source + offset)
self.destination = QtCore.QPointF(self.destination + offset)
def _computeMultiLink(self):
# Multi-link management
#
# multi is the offset of the link
# +------+ multi = -1 Link 2 +-------+
# | +-----------------------------+ |
# | R1 | | R2 |
# | | multi = 0 Link 1 | |
# | +-----------------------------+ |
# | | multi = 1 Link 3 | |
# +------+-----------------------------+-------+
if self._source_item == self._destination_item:
multi = 0
elif not hasattr(self._destination_item, "node"): # Could be temporary a qpointf during link creation
multi = 0
else:
multi = 0
link_items = self._source_item.links()
for link_item in link_items:
if link_item == self:
break
if link_item.destinationItem().node().id() == self._destination_item.node().id():
multi += 1
if link_item.sourceItem().node().id() == self._destination_item.node().id():
multi += 1
# MAX 7 links on the scene between 2 nodes
if multi > 7:
multi = 0
# Pair item represent the bottom links
elif multi % 2 == 0:
multi = multi // 2
else:
multi = -multi // 2
return multi
def setMousePoint(self, scene_point):
"""
Sets new mouse point coordinates.
@@ -233,3 +501,92 @@ class LinkItem(QtGui.QGraphicsPathItem):
self.destination = scene_point
self.adjust()
self.update()
@qslot
def _drawSymbol(self, *args):
"""
Draws a symbol in the middle of the link to indicate a capture, a suspend or a filter is active.
"""
#FIXME: refactor ugly symbol management
if not self._adding_flag:
if self._link.suspended():
if self.length >= 150:
link_center = QtCore.QPointF(self.source.x() + self.dx / 2.0 - 11, self.source.y() + self.dy / 2.0 - 11)
if self._suspend_item is None:
self._suspend_item = SvgIconItem(':/icons/pause.svg', self)
self._suspend_item.setScale(0.6)
if not self._suspend_item.isVisible():
self._suspend_item.show()
self._suspend_item.setPos(link_center)
if self._filter_item:
self._filter_item.hide()
elif self._suspend_item:
self._suspend_item.hide()
if self._filter_capturing_item:
self._filter_capturing_item.hide()
if self._capturing_item:
self._capturing_item.hide()
if self._filter_item:
self._filter_item.hide()
elif self._link.capturing() and len(self._link.filters()) > 0:
if self.length >= 150:
link_center = QtCore.QPointF(self.source.x() + self.dx / 2.0 - 11, self.source.y() + self.dy / 2.0 - 11)
if self._filter_capturing_item is None:
self._filter_capturing_item = SvgIconItem(':/icons/filter-capture.svg', self)
self._filter_capturing_item.setScale(0.6)
if not self._filter_capturing_item.isVisible():
self._filter_capturing_item.show()
self._filter_capturing_item.setPos(link_center)
elif self._filter_capturing_item:
self._filter_capturing_item.hide()
if self._capturing_item:
self._capturing_item.hide()
if self._filter_item:
self._filter_item.hide()
if self._suspend_item:
self._suspend_item.hide()
elif self._link.capturing():
if self.length >= 150:
link_center = QtCore.QPointF(self.source.x() + self.dx / 2.0 - 11, self.source.y() + self.dy / 2.0 - 11)
if self._capturing_item is None:
self._capturing_item = SvgIconItem(':/icons/inspect.svg', self)
self._capturing_item.setScale(0.6)
self._capturing_item.setPos(link_center)
if not self._capturing_item.isVisible():
self._capturing_item.show()
elif self._capturing_item:
self._capturing_item.hide()
if self._filter_capturing_item:
self._filter_capturing_item.hide()
if self._suspend_item:
self._suspend_item.hide()
elif len(self._link.filters()) > 0:
if self.length >= 150:
link_center = QtCore.QPointF(self.source.x() + self.dx / 2.0 - 11, self.source.y() + self.dy / 2.0 - 11)
if self._filter_item is None:
self._filter_item = SvgIconItem(':/icons/filter.svg', self)
self._filter_item.setScale(0.6)
if not self._filter_item.isVisible():
self._filter_item.show()
self._filter_item.setPos(link_center)
elif self._filter_item:
self._filter_item.hide()
if self._filter_capturing_item:
self._filter_capturing_item.hide()
if self._suspend_item:
self._suspend_item.hide()
else:
if self._capturing_item:
self._capturing_item.hide()
if self._suspend_item:
self._suspend_item.hide()
if self._filter_item:
self._filter_item.hide()
if self._filter_capturing_item:
self._filter_capturing_item.hide()

136
gns3/items/logo_item.py Normal file
View File

@@ -0,0 +1,136 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 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 urllib.parse
from ..qt import QtCore, QtGui, QtWidgets, QtSvg
from ..qt.qimage_svg_renderer import QImageSvgRenderer
from ..controller import Controller
import logging
log = logging.getLogger(__name__)
class LogoItem(QtSvg.QGraphicsSvgItem):
"""
Margin for the logo
"""
MARGIN = 20
"""
Logo for the scene.
:param logo_path: Path to the logo (remote)
:param logo_url: URL which needs to be open user clicks on the logo
:param project: Current project
"""
def __init__(self, logo_path, logo_url, project):
super().__init__()
self._logo_path = logo_path
self._logo_url = logo_url
self._project = project
# Temporary symbol during loading
renderer = QImageSvgRenderer(":/icons/reload.svg")
renderer.setObjectName("symbol_loading")
self.setSharedRenderer(renderer)
effect = QtWidgets.QGraphicsColorizeEffect()
effect.setColor(QtGui.QColor("black"))
effect.setStrength(0.8)
self.setGraphicsEffect(effect)
self.graphicsEffect().setEnabled(False)
# set graphical settings for this item
self.setFlag(QtWidgets.QGraphicsItem.ItemIsFocusable)
self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges)
self.setAcceptHoverEvents(True)
from ..main_window import MainWindow
self._main_window = MainWindow.instance()
self._settings = self._main_window.uiGraphicsView.settings()
self.updatePosition()
self._main_window.uiGraphicsView.viewport().installEventFilter(self)
remote_file = urllib.parse.quote('project-files/images/{}'.format(logo_path))
Controller.instance().getStatic(
'/projects/{}/files/{}'.format(project.id(), remote_file),
self.updateImage
)
# make it the last one
self.setZValue(-2)
def eventFilter(self, source, event):
if event.type() == QtCore.QEvent.Paint:
self.updatePosition()
return QtWidgets.QWidget.eventFilter(self, source, event)
def updateImage(self, local_path):
renderer = QImageSvgRenderer(local_path)
renderer.setObjectName("project_logo")
self.setSharedRenderer(renderer)
def updatePosition(self):
"""
Updates position to be located in the right bottom corner
"""
logo_rect = self.boundingRect()
width = self._main_window.uiGraphicsView.viewport().width()
height = self._main_window.uiGraphicsView.viewport().height()
rect = self._main_window.uiGraphicsView.mapToScene(QtCore.QRect(0, 0, width, height)).boundingRect()
x = rect.x() + rect.width() - self.MARGIN - logo_rect.width()
y = rect.y() + rect.height() - self.MARGIN - logo_rect.height()
# update only when changes
if [int(self.x()), int(self.y())] != [int(x), int(y)]:
self.setX(x)
self.setY(y)
self.update()
def hoverEnterEvent(self, event):
"""
Handles all hover enter events for this item.
:param event: QGraphicsSceneHoverEvent instance
"""
if self._logo_url is not None:
self.graphicsEffect().setEnabled(True)
def hoverLeaveEvent(self, event):
"""
Handles all hover leave events for this item.
:param event: QGraphicsSceneHoverEvent instance
"""
self.graphicsEffect().setEnabled(False)
def mousePressEvent(self, event):
url = QtCore.QUrl(self._logo_url)
if not QtGui.QDesktopServices.openUrl(url):
QtWidgets.QMessageBox.warning(self, 'Open Url', 'Could not open url')

View File

@@ -19,35 +19,70 @@
Graphical representation of a node on the QGraphicsScene.
"""
from ..qt import QtCore, QtGui, QtSvg
from ..qt import sip
from ..qt import QtCore, QtGui, QtWidgets, QtSvg, qslot
from ..qt.qimage_svg_renderer import QImageSvgRenderer
from .label_item import LabelItem
from ..symbol import Symbol
from ..controller import Controller
import logging
log = logging.getLogger(__name__)
class NodeItem(QtSvg.QGraphicsSvgItem):
"""
Node for the scene.
:param node: Node instance.
:param node: Node instance
"""
def __init__(self, node):
show_layer = False
QtSvg.QGraphicsSvgItem.__init__(self)
def __init__(self, node):
super().__init__()
# attached node
self._node = node
# link items connected to this node item.
self._links = []
self._symbol = None
self._locked = False
self._allow_snap_to_grid = True
# says if the attached node has been initialized
# by the server.
self._initialized = False
# node label
self._node_label = None
self.setPos(QtCore.QPoint(self._node.x(), self._node.y()))
# Temporary symbol during loading
renderer = QImageSvgRenderer(":/icons/reload.svg")
renderer.setObjectName("symbol_loading")
self.setSharedRenderer(renderer)
effect = QtWidgets.QGraphicsColorizeEffect()
effect.setColor(QtGui.QColor("black"))
effect.setStrength(0.8)
self.setGraphicsEffect(effect)
self.graphicsEffect().setEnabled(False)
# set graphical settings for this node
self.setFlag(QtSvg.QGraphicsSvgItem.ItemIsMovable)
self.setFlag(QtSvg.QGraphicsSvgItem.ItemIsSelectable)
self.setFlag(QtSvg.QGraphicsSvgItem.ItemIsFocusable)
self.setFlag(QtSvg.QGraphicsSvgItem.ItemSendsGeometryChanges)
self.setAcceptsHoverEvents(True)
self.setZValue(1)
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable)
self.setFlag(QtWidgets.QGraphicsItem.ItemIsFocusable)
self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges)
self.setAcceptHoverEvents(True)
# create renderers using symbols paths/resources
self._default_renderer = QtSvg.QSvgRenderer(node.defaultSymbol())
self._hover_renderer = QtSvg.QSvgRenderer(node.hoverSymbol())
self.setSharedRenderer(self._default_renderer)
# update z value and locked state
self.setLocked(self._node.locked())
self.setZValue(self._node.z())
# connect signals to know about some events
# e.g. when the node has been started, stopped or suspended etc.
@@ -57,32 +92,70 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
node.suspended_signal.connect(self.suspendedSlot)
node.updated_signal.connect(self.updatedSlot)
node.deleted_signal.connect(self.deletedSlot)
node.delete_links_signal.connect(self.deleteLinksSlot)
node.error_signal.connect(self.errorSlot)
node.server_error_signal.connect(self.serverErrorSlot)
# link items connected to this node item.
self._links = []
# used when a port has been selected from the contextual menu
self._selected_port = None
# says if the attached node has been initialized
# by the server.
self._initialized = False
# contains the last error message received
# from the server.
self._last_error = None
def setUnsavedState(self):
from ..main_window import MainWindow
self._main_window = MainWindow.instance()
self._settings = self._main_window.uiGraphicsView.settings()
if node.initialized():
self.createdSlot(node.id())
if self._main_window.uiSnapToGridAction.isChecked():
self.setPos(QtCore.QPointF(self._node.x() + 0.1, self._node.y()))
def updateNode(self):
"""
Indicates the project is in a unsaved state.
Sync change to the node
"""
from ..main_window import MainWindow
main_window = MainWindow.instance()
main_window.setUnsavedState()
self._node.setGraphics(self)
@qslot
def setSymbol(self, symbol):
"""
:param symbol: Change the symbol path
"""
# create renderer using symbols path/resource
if symbol is None:
symbol = self._node.defaultSymbol()
if self._symbol != symbol:
self._symbol = symbol
# Temporary symbol during loading
renderer = QImageSvgRenderer(":/icons/reload.svg")
renderer.setObjectName("symbol_loading")
self.setSharedRenderer(renderer)
Controller.instance().getStatic(Symbol(symbol_id=symbol).url(), self._symbolLoadedCallback)
def symbol(self):
return self._symbol
@qslot
def _symbolLoadedCallback(self, path, *args):
renderer = QImageSvgRenderer(path, fallback=":/icons/cancel.svg")
renderer.setObjectName(path)
self.setSharedRenderer(renderer)
if self._settings["limit_size_node_symbols"] is True and renderer.defaultSize().height() > 80:
# resize the SVG
renderer.resize(80)
self.setSharedRenderer(renderer)
if self._node.settings().get("symbol") != self._symbol:
self.updateNode()
if not self._initialized:
self._showLabel()
self._initialized = True
self.updateNode()
def node(self):
"""
@@ -93,27 +166,44 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
return self._node
def addLink(self, link):
def setPos(self, *args):
super().setPos(*args)
self._node.setSettingValue("x", int(self.x()))
self._node.setSettingValue("y", int(self.y()))
@qslot
def addLink(self, link_item, *args):
"""
Adds a link items to this node item.
:param link: LinkItem instance
"""
self._links.append(link)
self._node.updated_signal.emit()
self.setUnsavedState()
if not sip.isdeleted(link_item):
self._links.append(link_item)
link_item.link().delete_link_signal.connect(self._removeLink)
link_item.link().updated_link_signal.connect(self._linkUpdatedSlot)
self._node.updated_signal.emit()
def removeLink(self, link):
@qslot
def _linkUpdatedSlot(self, *args):
"""
When a link change we also notify the listener of the node
"""
self._node.updated_signal.emit()
@qslot
def _removeLink(self, link_id, *args):
"""
Removes a link items from this node item.
:param link: LinkItem instance
"""
if link in self._links:
self._links.remove(link)
self.setUnsavedState()
for link_item in self._links:
if link_item.link().id() == link_id:
self._links.remove(link_item)
return
def links(self):
"""
@@ -124,19 +214,21 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
return self._links
def createdSlot(self, node_id):
@qslot
def createdSlot(self, base_node_id, *args):
"""
Slot to receive events from the attached Node instance
when a the node has been created/initialized.
:param node_id: node identifier (integer)
:param base_node_id: base node identifier (integer)
"""
self._initialized = True
self.setPos(QtCore.QPoint(self._node.x(), self._node.y()))
self.setSymbol(self._node.symbol())
self.update()
self.showName()
def startedSlot(self):
@qslot
def startedSlot(self, *args):
"""
Slot to receive events from the attached Node instance
when a the node has started.
@@ -145,7 +237,8 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
for link in self._links:
link.update()
def stoppedSlot(self):
@qslot
def stoppedSlot(self, *args):
"""
Slot to receive events from the attached Node instance
when a the node has stopped.
@@ -154,7 +247,8 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
for link in self._links:
link.update()
def suspendedSlot(self):
@qslot
def suspendedSlot(self, *args):
"""
Slot to receive events from the attached Node instance
when a the node has suspended.
@@ -163,48 +257,55 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
for link in self._links:
link.update()
def updatedSlot(self):
self.textItem.setPlainText(self._node.name())
self.setUnsavedState()
def deleteLinksSlot(self):
@qslot
def updatedSlot(self, *args):
"""
Slot to receive events from the attached Node instance
when a all the links must be deleted.
when a the node has been updated.
"""
for link in self._links.copy():
link.delete()
self.setSymbol(self._node.settings().get("symbol"))
self.setPos(self._node.settings().get("x", 0), self._node.settings().get("y", 0))
self.setZValue(self._node.settings().get("z", 0))
self.setLocked(self._node.settings().get("locked", False))
self._updateLabel()
def deletedSlot(self):
# update the link tooltips in case the
# node name has changed
for link in self._links:
link.setCustomToolTip()
@qslot
def deletedSlot(self, *args):
"""
Slot to receive events from the attached Node instance
when the node has been deleted.
"""
if not self.scene():
return
if self in self.scene().items():
self.scene().removeItem(self)
self.setUnsavedState()
def serverErrorSlot(self, node_id, code, message):
@qslot
def serverErrorSlot(self, base_node_id, message, *args):
"""
Slot to receive events from the attached Node instance
when the node has received an error from the server.
:param node_id: node identifier
:param code: error code
:param base_node_id: base node identifier
:param message: error message
"""
self._last_error = "{message}".format(message=message)
def errorSlot(self, node_id, message):
@qslot
def errorSlot(self, base_node_id, message, *args):
"""
Slot to receive events from the attached Node instance
when the node wants to report an error.
:param node_id: node identifier
:param base_node_id: base node identifier
:param message: error message
"""
@@ -224,24 +325,74 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
else:
self.setToolTip(self._node.info())
def showName(self):
def label(self):
"""
Shows the node name on the scene.
Returns the node label.
:return: NoteItem instance.
"""
#TODO: possibility to change the Font size etc.
self.textItem = QtGui.QGraphicsTextItem(self._node.name(), self)
self.textItem.setFont(QtGui.QFont("TypeWriter", 10, QtGui.QFont.Bold))
self.textItem.setFlag(self.textItem.ItemIsMovable)
textrect = self.textItem.boundingRect()
textmiddle = textrect.topRight() / 2
noderect = self.boundingRect()
nodemiddle = noderect.topRight() / 2
self.default_name_xpos = nodemiddle.x() - textmiddle.x()
self.default_name_ypos = -25
self.textItem.setPos(self.default_name_xpos, self.default_name_ypos)
return self._node_label
def connectToPort(self, unavailable_ports=[]):
def _labelUnselectedSlot(self):
"""
Called when user unselect the label
"""
self.updateNode()
def _centerLabel(self):
"""
Centers the node label.
"""
text_rect = self._node_label.boundingRect()
text_middle = text_rect.topRight() / 2
node_rect = self.boundingRect()
node_middle = node_rect.topRight() / 2
label_x_pos = node_middle.x() - text_middle.x()
label_y_pos = -25
self._node_label.setPos(label_x_pos, label_y_pos)
return
def _showLabel(self):
"""
Shows the node label on the scene.
"""
if not self._node_label:
self._node_label = LabelItem(self)
self._node_label.item_unselected_signal.connect(self._labelUnselectedSlot)
self._node_label.setEditable(False)
self._updateLabel()
self._node.setSettingValue("label", self._node_label.dump())
def _updateLabel(self):
"""
Update the label using the information stored in the node
"""
if not self._node_label:
return
self._node_label.setPlainText(self._node.name())
label_data = self._node.settings().get("label")
if self._node_label.toPlainText() != label_data["text"]:
self._node_label.setPlainText(label_data["text"])
style = label_data.get("style")
if style:
self._node_label.setStyle(style)
self._node_label.setRotation(label_data.get("rotation", 0))
if self._node.locked():
self._node_label.setFlag(self.ItemIsMovable, False)
if label_data["x"] is None:
self._centerLabel()
self.updateNode()
else:
self._node_label.setPos(label_data["x"], label_data["y"])
def connectToPort(self, pos, unavailable_ports=[]):
"""
Shows a contextual menu for the user to choose port or auto-select one.
@@ -251,32 +402,48 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
"""
self._selected_port = None
menu = QtGui.QMenu()
menu = QtWidgets.QMenu()
ports = self._node.ports()
if not ports:
QtGui.QMessageBox.critical(self.scene().parent(), "Link", "No port available, please configure this device")
QtWidgets.QMessageBox.critical(self.scene().parent(), "Link", "No port available, please configure this device")
return None
# sort by port name
port_names = {}
# sort the ports
ports_dict = {}
for port in ports:
port_names[port.name()] = port
ports = sorted(port_names.keys())
if port.adapterNumber() is not None:
# make the port number unique (special case with WICs).
port_number = port.portNumber()
if port_number >= 16:
port_number *= 8
ports_dict[(port.adapterNumber() * 16) + port_number] = port
elif port.portNumber()is not None:
ports_dict[port.portNumber()] = port
else:
ports_dict[port.name()] = port
try:
ports = sorted(ports_dict.keys(), key=int)
except ValueError:
ports = sorted(ports_dict.keys())
# show a contextual menu for the user to choose a port
for port in ports:
port_object = port_names[port]
port_object = ports_dict[port]
log.debug("Node '{}' Port {} Type {}".format(self.node(), port_object.name(), type(port_object.name())))
if port in unavailable_ports:
# this port cannot be chosen by the user (grayed out)
action = menu.addAction(QtGui.QIcon(':/icons/led_green.svg'), port)
action = menu.addAction(QtGui.QIcon(':/icons/led_green.svg'), port_object.name())
action.setDisabled(True)
elif port_object.isFree():
menu.addAction(QtGui.QIcon(':/icons/led_red.svg'), port)
menu.addAction(QtGui.QIcon(':/icons/led_red.svg'), port_object.name())
else:
menu.addAction(QtGui.QIcon(':/icons/led_green.svg'), port)
menu.addAction(QtGui.QIcon(':/icons/led_green.svg'), port_object.name())
menu.triggered.connect(self.selectedPortSlot)
menu.exec_(QtGui.QCursor.pos())
# add some delay before showing the menu
# https://github.com/GNS3/gns3-gui/issues/3169
QtCore.QThread.msleep(100)
menu.exec_(pos)
return self._selected_port
def selectedPortSlot(self, action):
@@ -303,52 +470,112 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
:param value: value of the change
"""
if change == QtWidgets.QGraphicsItem.ItemPositionChange and self._main_window.uiSnapToGridAction.isChecked() \
and self._allow_snap_to_grid:
grid_size = self._main_window.uiGraphicsView.nodeGridSize()
mid_x = self.boundingRect().width() / 2
value.setX((grid_size * round((value.x() + mid_x) / grid_size)) - mid_x)
mid_y = self.boundingRect().height() / 2
value.setY((grid_size * round((value.y() + mid_y) / grid_size)) - mid_y)
# dynamically change the renderer when this node item is selected/unselected.
if change == QtSvg.QGraphicsSvgItem.ItemSelectedChange:
if change == QtWidgets.QGraphicsItem.ItemSelectedChange:
if value:
self.setSharedRenderer(self._hover_renderer)
self.graphicsEffect().setEnabled(True)
else:
self.setSharedRenderer(self._default_renderer)
self.graphicsEffect().setEnabled(False)
self.updateNode()
# adjust link item positions when this node is moving or has changed.
if change == QtSvg.QGraphicsSvgItem.ItemPositionChange or change == QtSvg.QGraphicsSvgItem.ItemPositionHasChanged:
self.setUnsavedState()
if change == QtWidgets.QGraphicsItem.ItemPositionChange or change == QtWidgets.QGraphicsItem.ItemPositionHasChanged:
for link in self._links:
link.adjust()
return QtGui.QGraphicsItem.itemChange(self, change, value)
return super().itemChange(change, value)
def paint(self, painter, option, widget=None):
"""
Paints the contents of an item in local coordinates.
:param painter: QPainter instance.
:param option: QStyleOptionGraphicsItem instance.
:param widget: QWidget instance.
:param painter: QPainter instance
:param option: QStyleOptionGraphicsItem instance
:param widget: QWidget instance
"""
# don't show the selection rectangle
option.state = QtGui.QStyle.State_None
QtSvg.QGraphicsSvgItem.paint(self, painter, option, widget)
if not self._settings["draw_rectangle_selected_item"]:
option.state = QtWidgets.QStyle.State_None
super().paint(painter, option, widget)
#TODO: show layer position on the node
# # Don't draw if not activated
# if globals.GApp.workspace.flg_showLayerPos == False:
# return
if not self._initialized:
# Show layer level of this node
if not self._initialized or self.show_layer:
brect = self.boundingRect()
# center = self.mapFromItem(self, brect.width() / 2.0, brect.height() / 2.0)
center = self.mapFromItem(self, brect.width() / 2.0, brect.height() / 2.0)
painter.setBrush(QtCore.Qt.red)
painter.setPen(QtCore.Qt.red)
painter.drawRect((brect.width() / 2.0) - 10, (brect.height() / 2.0) - 10, 20, 20)
painter.drawRect(QtCore.QRectF((brect.width() / 2.0) - 10, (brect.height() / 2.0) - 10, 20, 20))
painter.setPen(QtCore.Qt.black)
if self.show_layer:
text = str(int(self.zValue())) # Z value
elif self._last_error:
text = "E" # error
else:
text = "S" # initialization
painter.drawText(QtCore.QPointF(center.x() - 4, center.y() + 4), text)
#painter.setPen(QtCore.Qt.black)
#painter.setFont(QtGui.QFont("TypeWriter", 14, QtGui.QFont.Bold))
#zval = str(int(self.zValue()))
#painter.drawText(QtCore.QPointF(center.x() - 4, center.y() + 4), zval)
def setZValue(self, value):
"""
Sets a new Z value.
:param value: Z value
"""
super().setZValue(value)
for link in self._links:
link.adjust()
def keyPressEvent(self, event):
"""
Handles all key press events
:param event: QKeyEvent
"""
if event.modifiers() & QtCore.Qt.AltModifier:
self._allow_snap_to_grid = False
else:
super().keyPressEvent(event)
def keyReleaseEvent(self, event):
"""
Handles all key release events
:param event: QKeyEvent
"""
self._allow_snap_to_grid = True
def locked(self):
return self._locked
def setLocked(self, locked):
"""
Sets the locked value.
:param value: Z value
"""
if locked is True:
self.setFlag(self.ItemIsMovable, False)
if self._node_label:
self._node_label.setFlag(self.ItemIsMovable, False)
else:
self.setFlag(self.ItemIsMovable, True)
if self._node_label:
self._node_label.setFlag(self.ItemIsMovable, True)
for link in self._links:
link.adjust()
self._locked = locked
def hoverEnterEvent(self, event):
"""
@@ -358,9 +585,8 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
"""
self.setCustomToolTip()
# dynamically change the renderer when this node item is hovered.
if not self.isSelected():
self.setSharedRenderer(self._hover_renderer)
self.graphicsEffect().setEnabled(True)
def hoverLeaveEvent(self, event):
"""
@@ -369,6 +595,13 @@ class NodeItem(QtSvg.QGraphicsSvgItem):
:param event: QGraphicsSceneHoverEvent instance
"""
# dynamically change the renderer back to the default when this node item is not hovered anymore.
if not self.isSelected():
self.setSharedRenderer(self._default_renderer)
self.graphicsEffect().setEnabled(False)
def mouseRelease(self):
"""
Handle all mouse release for this item.
It the item is select but mouse is not on it the event
is send also
"""
self.updateNode()

View File

@@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Graphical representation of a rectangle on the QGraphicsScene.
"""
import xml.etree.ElementTree as ET
from ..qt import QtCore, QtGui, QtWidgets
from .shape_item import ShapeItem
class RectangleItem(QtWidgets.QGraphicsRectItem, ShapeItem):
"""
Class to draw a rectangle on the scene.
"""
def __init__(self, width=200, height=100, **kws):
self._rx = 0
self._ry = 0
super().__init__(width=width, height=height, **kws)
def setHorizontalCornerRadius(self, radius: int):
self._rx = radius
def horizontalCornerRadius(self):
return self._rx
def setVerticalCornerRadius(self, radius: int):
self._ry = radius
def verticalCornerRadius(self):
return self._ry
def paint(self, painter, option, widget=None):
"""
Paints the contents of an item in local coordinates.
:param painter: QPainter instance
:param option: QStyleOptionGraphicsItem instance
:param widget: QWidget instance
"""
painter.setPen(self.pen())
painter.setBrush(self.brush())
painter.drawRoundedRect(self.rect(), self._rx, self._ry)
self.drawLayerInfo(painter)
def toSvg(self):
"""
Return an SVG version of the shape
"""
svg = ET.Element("svg")
svg.set("width", str(int(self.rect().width())))
svg.set("height", str(int(self.rect().height())))
rect = ET.SubElement(svg, "rect")
rect.set("width", str(int(self.rect().width())))
rect.set("height", str(int(self.rect().height())))
if self._rx:
rect.set("rx", str(self._rx))
if self._ry:
rect.set("ry", str(self._ry))
rect = self._styleSvg(rect)
return ET.tostring(svg, encoding="utf-8").decode("utf-8")
def fromSvg(self, svg):
svg_elem = ET.fromstring(svg)
if len(svg_elem):
# handle horizontal corner radius and vertical corner radius (specific to rectangles)
rx = svg_elem[0].get("rx")
ry = svg_elem[0].get("ry")
if rx:
self._rx = int(rx)
elif ry:
self._rx = int(ry) # defaults to ry if it is specified
if ry:
self._ry = int(ry)
elif rx:
self._ry = int(rx) # defaults to rx if it is specified
super().fromSvg(svg)

View File

@@ -20,12 +20,14 @@ Graphical representation of a Serial link on the QGraphicsScene.
"""
import math
from ..qt import QtCore, QtGui
from ..qt import QtCore, QtGui, QtWidgets
from .link_item import LinkItem
from .label_item import LabelItem
from ..ports.port import Port
class SerialLinkItem(LinkItem):
"""
Serial link for the scene.
@@ -35,13 +37,11 @@ class SerialLinkItem(LinkItem):
:param destination_port: destination Port instance
:param link: Link instance (contains back-end stuff for this link)
:param adding_flag: indicates if this link is being added (no destination yet)
:param multilink: used to draw multiple link between the same source and destination
"""
def __init__(self, source_item, source_port, destination_item, destination_port, link=None, adding_flag=False, multilink=0):
def __init__(self, source_item, source_port, destination_item, destination_port, link=None, adding_flag=False):
LinkItem.__init__(self, source_item, source_port, destination_item, destination_port, link, adding_flag, multilink)
self.setPen(QtGui.QPen(QtCore.Qt.red, self._pen_width, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
super().__init__(source_item, source_port, destination_item, destination_port, link, adding_flag)
def adjust(self):
"""
@@ -50,6 +50,17 @@ class SerialLinkItem(LinkItem):
LinkItem.adjust(self)
try:
if self._hovered:
self.setPen(QtGui.QPen(QtCore.Qt.red, self._link._link_style["width"] + 1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
else:
self.setPen(QtGui.QPen(QtGui.QColor(self._link._link_style["color"]), self._link._link_style["width"], self._link._link_style["type"], QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
except:
if self._hovered:
self.setPen(QtGui.QPen(QtCore.Qt.red, self._pen_width + 1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
else:
self.setPen(QtGui.QPen(QtCore.Qt.darkRed, self._pen_width, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
# get source to destination angle
vector_angle = math.atan2(self.dy, self.dx)
@@ -73,8 +84,8 @@ class SerialLinkItem(LinkItem):
scale_vect_diag = math.sqrt(scale_vect.x() ** 2 + scale_vect.y() ** 2)
scale_coef = scale_vect_diag / 40.0
self.source = QtCore.QPointF(self.source.x() + scale_vect.x() / scale_coef, self.source.y() + scale_vect.y() / scale_coef)
self.destination = QtCore.QPointF(self.destination.x() - scale_vect.x() / scale_coef, self.destination.y() - scale_vect.y() / scale_coef)
self.source_point = QtCore.QPointF(self.source.x() + scale_vect.x() / scale_coef, self.source.y() + scale_vect.y() / scale_coef)
self.destination_point = QtCore.QPointF(self.destination.x() - scale_vect.x() / scale_coef, self.destination.y() - scale_vect.y() / scale_coef)
def shape(self):
"""
@@ -83,11 +94,11 @@ class SerialLinkItem(LinkItem):
:returns: QPainterPath instance
"""
path = QtGui.QGraphicsPathItem.shape(self)
path = QtWidgets.QGraphicsPathItem.shape(self)
offset = self._point_size / 2
point = self.source
point = self.source_point
path.addEllipse(point.x() - offset, point.y() - offset, self._point_size, self._point_size)
point = self.destination
point = self.destination_point
path.addEllipse(point.x() - offset, point.y() - offset, self._point_size, self._point_size)
return path
@@ -100,102 +111,75 @@ class SerialLinkItem(LinkItem):
:param widget: QWidget instance.
"""
QtGui.QGraphicsPathItem.paint(self, painter, option, widget)
QtWidgets.QGraphicsPathItem.paint(self, painter, option, widget)
if not self._adding_flag and self._settings["draw_link_status_points"]:
if not self._adding_flag:
# points disappears if nodes are too close to each others.
if self.length < 80:
return
# source point color
if self._source_port.status() == Port.started:
# port is active
color = QtCore.Qt.green
elif self._source_port.status() == Port.suspended:
# port is suspended
if self._link.suspended() or self._source_port.status() == Port.suspended:
# link or port is suspended
shape = QtCore.Qt.RoundCap
color = QtCore.Qt.yellow
elif self._source_port.status() == Port.started:
# port is active
shape = QtCore.Qt.RoundCap
color = QtCore.Qt.green
else:
shape = QtCore.Qt.SquareCap
color = QtCore.Qt.red
painter.setPen(QtGui.QPen(color, self._point_size, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.MiterJoin))
painter.setPen(QtGui.QPen(color, self._point_size, QtCore.Qt.SolidLine, shape, QtCore.Qt.MiterJoin))
#TODO: draw port labels
# if globals.GApp.workspace.flg_showInterfaceNames:
# if self.labelSouceIf == None:
#
# if globals.interfaceLabels.has_key(self.source.hostname + ' ' + self.srcIf):
# self.labelSouceIf = Annotation(self.source)
# annotation = globals.interfaceLabels[self.source.hostname + ' ' + self.srcIf]
# self.labelSouceIf.setZValue(annotation.zValue())
# self.labelSouceIf.setDefaultTextColor(annotation.defaultTextColor())
# self.labelSouceIf.setFont(annotation.font())
# self.labelSouceIf.setPlainText(annotation.toPlainText())
# self.labelSouceIf.setPos(annotation.x(), annotation.y())
# self.labelSouceIf.rotation = annotation.rotation
# self.labelSouceIf.rotate(annotation.rotation)
# del globals.interfaceLabels[self.source.hostname + ' ' + self.srcIf]
# elif not globals.GApp.workspace.flg_showOnlySavedInterfaceNames:
# self.labelSouceIf = Annotation(self.source)
# self.labelSouceIf.setPlainText(self.srcIf)
# self.labelSouceIf.setPos(self.mapToItem(self.source, self.src))
# #self.labelSouceIf.autoGenerated = True
#
# if self.labelSouceIf:
# self.labelSouceIf.deviceName = self.source.hostname
# self.labelSouceIf.deviceIf = self.srcIf
#
# if self.labelSouceIf and not self.labelSouceIf.isVisible():
# self.labelSouceIf.show()
#
# elif self.labelSouceIf and globals.GApp.workspace.flg_showInterfaceNames == False:
# self.labelSouceIf.hide()
source_port_label = self._source_port.label()
if source_port_label is None:
source_port_label = LabelItem(self._source_item)
source_port_label.setPlainText(self._source_port.shortName())
source_port_label.setPos(self.mapToItem(self._source_item, self.source))
self._source_port.setLabel(source_port_label)
painter.drawPoint(self.source)
#painter.drawPoint(self.source)
if self._draw_port_labels:
source_port_label.setFlag(source_port_label.ItemIsMovable, not self._source_item.locked())
source_port_label.show()
else:
source_port_label.hide()
if self._settings["draw_link_status_points"] and self.pen().style() != QtCore.Qt.NoPen:
painter.drawPoint(self.source_point)
# destination point color
if self._destination_port.status() == Port.started:
if self._link.suspended() or self._destination_port.status() == Port.suspended:
# link or port is suspended
color = QtCore.Qt.yellow
shape = QtCore.Qt.RoundCap
elif self._destination_port.status() == Port.started:
# port is active
color = QtCore.Qt.green
elif self._destination_port.status() == Port.suspended:
# port is suspended
color = QtCore.Qt.yellow
shape = QtCore.Qt.RoundCap
else:
color = QtCore.Qt.red
shape = QtCore.Qt.SquareCap
painter.setPen(QtGui.QPen(color, self._point_size, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.MiterJoin))
painter.setPen(QtGui.QPen(color, self._point_size, QtCore.Qt.SolidLine, shape, QtCore.Qt.MiterJoin))
#TODO: draw port labels
# if globals.GApp.workspace.flg_showInterfaceNames:
# if self.labelDestIf == None:
#
# if globals.interfaceLabels.has_key(self.dest.hostname + ' ' + self.destIf):
# self.labelDestIf = Annotation(self.dest)
# annotation = globals.interfaceLabels[self.dest.hostname + ' ' + self.destIf]
# self.labelDestIf.setZValue(annotation.zValue())
# self.labelDestIf.setDefaultTextColor(annotation.defaultTextColor())
# self.labelDestIf.setFont(annotation.font())
# self.labelDestIf.setPlainText(annotation.toPlainText())
# self.labelDestIf.setPos(annotation.x(), annotation.y())
# self.labelDestIf.rotation = annotation.rotation
# self.labelDestIf.rotate(annotation.rotation)
# del globals.interfaceLabels[self.dest.hostname + ' ' + self.destIf]
# elif not globals.GApp.workspace.flg_showOnlySavedInterfaceNames:
# self.labelDestIf = Annotation(self.dest)
# self.labelDestIf.setPlainText(self.destIf)
# self.labelDestIf.setPos(self.mapToItem(self.dest, self.dst))
# #self.labelDestIf.autoGenerated = True
#
# if self.labelDestIf:
# self.labelDestIf.deviceName = self.dest.hostname
# self.labelDestIf.deviceIf = self.destIf
#
# if self.labelDestIf and not self.labelDestIf.isVisible():
# self.labelDestIf.show()
#
#
# elif self.labelDestIf and globals.GApp.workspace.flg_showInterfaceNames == False:
# self.labelDestIf.hide()
destination_port_label = self._destination_port.label()
painter.drawPoint(self.destination)
if destination_port_label is None:
destination_port_label = LabelItem(self._destination_item)
destination_port_label.setPlainText(self._destination_port.shortName())
destination_port_label.setPos(self.mapToItem(self._destination_item, self.destination))
self._destination_port.setLabel(destination_port_label)
if self._draw_port_labels:
destination_port_label.setFlag(destination_port_label.ItemIsMovable, not self._destination_item.locked())
destination_port_label.show()
else:
destination_port_label.hide()
if self._settings["draw_link_status_points"] and self.pen().style() != QtCore.Qt.NoPen:
painter.drawPoint(self.destination_point)
self._drawSymbol()

205
gns3/items/shape_item.py Normal file
View File

@@ -0,0 +1,205 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Base class for shape items (Rectangle, ellipse etc.).
"""
import xml.etree.ElementTree as ET
from ..qt import QtCore, QtGui, QtWidgets
from .drawing_item import DrawingItem
from .utils import colorFromSvg
import logging
log = logging.getLogger(__name__)
class ShapeItem(DrawingItem):
"""
Base class to draw shapes on the scene.
"""
def __init__(self, width=200, height=200, svg=None, **kws):
super().__init__(svg=svg, **kws)
self.setAcceptHoverEvents(True)
self._border = 5
self._edge = None
self._originally_movable = True
if svg is None:
self.setRect(0, 0, width, height)
pen = QtGui.QPen(QtCore.Qt.black, 2, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
self.setPen(pen)
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255, 255)) # default color is white and not transparent
self.setBrush(brush)
else:
self.fromSvg(svg)
if self._id is None:
self.create()
def mousePressEvent(self, event):
"""
Handles all mouse press events.
:param event: QMouseEvent instance
"""
self.update()
self._originally_movable = self.flags() & QtWidgets.QGraphicsItem.ItemIsMovable
if event.pos().x() > (self.rect().right() - self._border):
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
self._edge = "right"
elif event.pos().x() < (self.rect().left() + self._border):
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
self._edge = "left"
elif event.pos().y() < (self.rect().top() + self._border):
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
self._edge = "top"
elif event.pos().y() > (self.rect().bottom() - self._border):
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, False)
self._edge = "bottom"
QtWidgets.QGraphicsItem.mousePressEvent(self, event)
def mouseReleaseEvent(self, event):
"""
Handles all mouse release events.
:param: QMouseEvent instance
"""
self.update()
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, self._originally_movable)
self._edge = None
QtWidgets.QGraphicsItem.mouseReleaseEvent(self, event)
def mouseMoveEvent(self, event):
"""
Handles all mouse move events.
:param event: QMouseEvent instance
"""
self.update()
if self._edge:
r = self.rect()
scenePos = event.scenePos()
if self._edge == "top":
diff = self.y() - scenePos.y()
if r.height() - diff > 0:
self.setPos(self.x(), scenePos.y())
self.setRect(0, 0, self.rect().width(), self.rect().height() + diff)
else:
self._edge = "bottom"
self.setPos(self.x(), self.y() + self.rect().height())
self.setRect(0, 0, self.rect().width(), diff - self.rect().height())
elif self._edge == "left":
diff = self.x() - scenePos.x()
if r.width() - diff > 0:
self.setPos(scenePos.x(), self.y())
self.setRect(0, 0, r.width() + diff, self.rect().height())
else:
self._edge = "right"
self.setPos(self.x() + self.rect().width(), self.y())
self.setRect(0, 0, diff - self.rect().width(), self.rect().height())
elif self._edge == "bottom":
if r.height() > 0:
pos = self.mapFromScene(scenePos)
self.setRect(0, 0, self.rect().width(), pos.y())
else:
self.setRect(0, 0, self.rect().width(), abs(scenePos.y() - self.y()))
self.setPos(self.x(), scenePos.y())
self._edge = "top"
elif self._edge == "right":
if r.width() > 0:
pos = self.mapFromScene(scenePos)
self.setRect(0, 0, pos.x(), self.rect().height())
else:
self.setRect(0, 0, abs(scenePos.x() - self.x()), self.rect().height())
self.setPos(scenePos.x(), self.y())
self._edge = "left"
QtWidgets.QGraphicsItem.mouseMoveEvent(self, event)
def hoverMoveEvent(self, event):
"""
Handles all hover move events.
:param event: QGraphicsSceneHoverEvent instance
"""
# locked objects don't need cursors
if not self.locked():
if event.pos().x() > (self.rect().right() - self._border):
self._graphics_view.setCursor(QtCore.Qt.SizeHorCursor)
elif event.pos().x() < (self.rect().left() + self._border):
self._graphics_view.setCursor(QtCore.Qt.SizeHorCursor)
elif event.pos().y() < (self.rect().top() + self._border):
self._graphics_view.setCursor(QtCore.Qt.SizeVerCursor)
elif event.pos().y() > (self.rect().bottom() - self._border):
self._graphics_view.setCursor(QtCore.Qt.SizeVerCursor)
else:
self._graphics_view.setCursor(QtCore.Qt.SizeAllCursor)
def hoverLeaveEvent(self, event):
"""
Handles all hover leave events.
:param event: QGraphicsSceneHoverEvent instance
"""
# locked objects don't need cursors
if not self.locked():
self._graphics_view.setCursor(QtCore.Qt.ArrowCursor)
def setWidthAndHeight(self, width, height):
self.setRect(0, 0, width, height)
def fromSvg(self, svg):
"""
Import element information from SVG
"""
svg = ET.fromstring(svg)
width = float(svg.get("width", self.rect().width()))
height = float(svg.get("height", self.rect().height()))
self.setRect(0, 0, width, height)
pen = QtGui.QPen()
brush = QtGui.QBrush(QtCore.Qt.SolidPattern)
if len(svg):
pen = self._penFromSVGElement(svg[0])
if svg[0].get("fill"):
new_color = colorFromSvg(svg[0].get("fill"))
color = brush.color()
color.setBlue(new_color.blue())
color.setRed(new_color.red())
color.setGreen(new_color.green())
brush.setColor(color)
if svg[0].get("fill-opacity"):
color = brush.color()
color.setAlphaF(float(svg[0].get("fill-opacity")))
brush.setColor(color)
self.setPen(pen)
self.setBrush(brush)
self.update()

203
gns3/items/text_item.py Normal file
View File

@@ -0,0 +1,203 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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 xml.etree.ElementTree as ET
from ..qt import QtCore, QtWidgets, QtGui
from .drawing_item import DrawingItem
from .utils import colorFromSvg
import logging
log = logging.getLogger(__name__)
class TextItem(QtWidgets.QGraphicsTextItem, DrawingItem):
"""
Text item for the QGraphicsView.
"""
def __init__(self, svg=None, **kws):
super().__init__(**kws)
from ..main_window import MainWindow
main_window = MainWindow.instance()
view_settings = main_window.uiGraphicsView.settings()
qt_font = QtGui.QFont()
qt_font.fromString(view_settings["default_note_font"])
self.setDefaultTextColor(QtGui.QColor(view_settings["default_note_color"]))
self.setFont(qt_font)
if svg:
try:
svg = self.fromSvg(svg)
except ET.ParseError as e:
log.warning(str(e))
# re-evaluate `z` position after creation
if 'z' in kws.keys():
self.setZValue(kws['z'])
if self._id is None:
self.create()
def editText(self):
"""
Edit mode for this note.
"""
self.setTextInteractionFlags(QtCore.Qt.TextEditorInteraction)
self.setSelected(True)
self.setFocus()
cursor = self.textCursor()
cursor.select(QtGui.QTextCursor.Document)
self.setTextCursor(cursor)
def mouseDoubleClickEvent(self, event):
"""
Handles all mouse double click events.
:param event: QMouseEvent instance
"""
self.editText()
def focusOutEvent(self, event):
"""
Handles all focus out events.
:param event: QFocusEvent instance
"""
self.setFlag(QtWidgets.QGraphicsItem.ItemIsFocusable, False)
cursor = self.textCursor()
if cursor.hasSelection():
cursor.clearSelection()
self.setTextCursor(cursor)
self.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
if not self.toPlainText():
# delete the note if empty
self.delete()
return
else:
self.updateDrawing()
return super().focusOutEvent(event)
def paint(self, painter, option, widget=None):
"""
Paints the contents of an item in local coordinates.
:param painter: QPainter instance
:param option: QStyleOptionGraphicsItem instance
:param widget: QWidget instance
"""
super().paint(painter, option, widget)
self.drawLayerInfo(painter)
def toSvg(self):
"""
Return an SVG version of the text
"""
svg = ET.Element("svg")
svg.set("width", str(int(self.boundingRect().width())))
svg.set("height", str(int(self.boundingRect().height())))
text = ET.SubElement(svg, "text")
text.set("font-family", self.font().family())
text.set("font-size", str(self.font().pointSizeF()))
if self.font().italic():
text.set("font-style", "italic")
if self.font().bold():
text.set("font-weight", "bold")
if self.font().strikeOut():
text.set("text-decoration", "line-through")
elif self.font().underline():
text.set("text-decoration", "underline")
text.set("fill", "#" + hex(self.defaultTextColor().rgba())[4:])
text.set("fill-opacity", str(self.defaultTextColor().alphaF()))
text.text = self.toPlainText()
svg = ET.tostring(svg, encoding="utf-8").decode("utf-8")
return svg
def fromSvg(self, svg):
# sometimes we receive \0 at the end of string inside <svg> element
try:
svg = svg.replace("\u0000", "")
except AttributeError:
pass
try:
svg = ET.fromstring(svg)
except ET.ParseError:
self.setPlainText("Unable to parse `text_item`")
return
text = svg[0]
font = QtGui.QFont()
color = text.get("fill")
if color:
new_color = colorFromSvg(color)
color = self.defaultTextColor()
color.setBlue(new_color.blue())
color.setRed(new_color.red())
color.setGreen(new_color.green())
self.setDefaultTextColor(color)
opacity = text.get("fill-opacity")
if opacity:
color = self.defaultTextColor()
color.setAlphaF(float(opacity))
self.setDefaultTextColor(color)
font.setPointSizeF(float(text.get("font-size", self.font().pointSizeF())))
font.setFamily(text.get("font-family", self.font().family()))
if text.get("font-style") == "italic":
font.setItalic(True)
if text.get("font-weight") == "bold":
font.setBold(True)
if text.get("text-decoration") == "underline":
font.setUnderline(True)
if text.get("text-decoration") == "line-through":
font.setStrikeOut(True)
self.setFont(font)
self.setPlainText(text.text)
def editable(self):
"""
Returns either the note is editable or not.
:return: boolean
"""
return True
def keyPressEvent(self, event):
"""
Handles all key press events
:param event: QKeyEvent
"""
if not self.handleKeyPressEvent(event):
super().keyPressEvent(event)

31
gns3/items/utils.py Normal file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/env python
#
# Copyright (C) 2016 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/>.
from ..qt import QtGui
def colorFromSvg(value):
"""
Transform a color coming from a SVG file to a Qcolor
"""
value = value.strip('#')
if value == "":
value = "000000"
if len(value) == 6: # If alpha channel is missing
value = "ff" + value
value = int(value, base=16)
return QtGui.QColor.fromRgba(value)

View File

@@ -1,184 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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/>.
"""
JSON-RPC protocol implementation.
http://www.jsonrpc.org/specification
"""
import json
import uuid
class JSONRPCObject(object):
"""
Base object for JSON-RPC requests, responses,
notifications and errors.
"""
def __init__(self):
return JSONRPCEncoder().default(self)
def __str__(self, *args, **kwargs):
return json.dumps(self, cls=JSONRPCEncoder)
def __call__(self):
return JSONRPCEncoder().default(self)
class JSONRPCEncoder(json.JSONEncoder):
"""
Creates the JSON-RPC message.
"""
def default(self, obj):
"""
Returns a Python dictionary corresponding to a JSON-RPC message.
"""
if isinstance(obj, JSONRPCObject):
message = {"jsonrpc": 2.0}
for field in dir(obj):
if not field.startswith('_'):
value = getattr(obj, field)
message[field] = value
return message
return json.JSONEncoder.default(self, obj)
class JSONRPCInvalidRequest(JSONRPCObject):
"""
Error response for an invalid request.
"""
def __init__(self):
JSONRPCObject.__init__(self)
self.id = None
self.error = {"code": -32600, "message": "Invalid Request"}
class JSONRPCMethodNotFound(JSONRPCObject):
"""
Error response for an method not found.
:param request_id: JSON-RPC identifier
"""
def __init__(self, request_id):
JSONRPCObject.__init__(self)
self.id = request_id
self.error = {"code": -32601, "message": "Method not found"}
class JSONRPCInvalidParams(JSONRPCObject):
"""
Error response for invalid parameters.
:param request_id: JSON-RPC identifier
"""
def __init__(self, request_id):
JSONRPCObject.__init__(self)
self.id = request_id
self.error = {"code": -32602, "message": "Invalid params"}
class JSONRPCInternalError(JSONRPCObject):
"""
Error response for an internal error.
:param request_id: JSON-RPC identifier (optional)
"""
def __init__(self, request_id=None):
JSONRPCObject.__init__(self)
self.id = request_id
self.error = {"code": -32603, "message": "Internal error"}
class JSONRPCParseError(JSONRPCObject):
"""
Error response for parsing error.
"""
def __init__(self):
JSONRPCObject.__init__(self)
self.id = None
self.error = {"code": -32700, "message": "Parse error"}
class JSONRPCCustomError(JSONRPCObject):
"""
Error response for an custom error.
:param code: JSON-RPC error code
:param message: JSON-RPC error message
:param request_id: JSON-RPC identifier (optional)
"""
def __init__(self, code, message, request_id=None):
JSONRPCObject.__init__(self)
self.id = request_id
self.error = {"code": code, "message": message}
class JSONRPCResponse(JSONRPCObject):
"""
JSON-RPC successful response.
:param result: JSON-RPC result
:param request_id: JSON-RPC identifier
"""
def __init__(self, result, request_id):
JSONRPCObject.__init__(self)
self.id = request_id
self.result = result
class JSONRPCRequest(JSONRPCObject):
"""
JSON-RPC request.
:param method: JSON-RPC destination method
:param params: JSON-RPC params for the corresponding method (optional)
:param request_id: JSON-RPC identifier (generated by default)
"""
def __init__(self, method, params=None, request_id=None):
JSONRPCObject.__init__(self)
if request_id == None:
request_id = str(uuid.uuid4())
self.id = request_id
self.method = method
if params:
self.params = params
class JSONRPCNotification(JSONRPCObject):
"""
JSON-RPC notification.
:param method: JSON-RPC destination method
:param params: JSON-RPC params for the corresponding method (optional)
"""
def __init__(self, method, params=None):
JSONRPCObject.__init__(self)
self.method = method
if params:
self.params = params

View File

@@ -19,15 +19,20 @@
Manages and stores everything needed for a connection between 2 devices.
"""
import re
from .qt import sip
import uuid
from .qt import QtCore
from .nios.nio_udp import NIOUDP
from .controller import Controller
import logging
log = logging.getLogger(__name__)
class Link(QtCore.QObject):
"""
Link implementation.
@@ -35,24 +40,28 @@ class Link(QtCore.QObject):
:param source_port: source Port instance
:param destination_node: destination Node instance
:param destination_port: destination Port instance
:param stub: indicates if the link is connected to a stub device like a Cloud
"""
# signals used to let the GUI view know about link
# additions and deletions.
add_link_signal = QtCore.Signal(int)
delete_link_signal = QtCore.Signal(int)
updated_link_signal = QtCore.Signal(int)
error_link_signal = QtCore.Signal(int)
_instance_count = 1
def __init__(self, source_node, source_port, destination_node, destination_port):
def __init__(self, source_node, source_port, destination_node, destination_port, link_id=None, **link_data):
"""
:param link_data: Link information from the API
"""
super(Link, self).__init__()
super().__init__()
log.info("adding link from {} {} to {} {}".format(source_node.name(),
source_port.name(),
destination_node.name(),
destination_port.name()))
log.debug("adding link from {} {} to {} {}".format(source_node.name(),
source_port.name(),
destination_node.name(),
destination_port.name()))
# create an unique ID
self._id = Link._instance_count
@@ -62,59 +71,212 @@ class Link(QtCore.QObject):
self._source_port = source_port
self._destination_node = destination_node
self._destination_port = destination_port
self._source_nio = None
self._destination_nio = None
self._source_nio_active = False
self._destination_nio_active = False
self._source_label = None
self._destination_label = None
self._link_id = link_id
self._capturing = False
self._deleting = False
self._capture_file_path = None
self._capture_file = None
self._response_stream = None
self._capture_compute_id = None
self._initialized = False
self._filters = {}
self._suspend = False
# add a link description
self._description = "Link from {} port {} to {} port {}".format(self._source_node.name(),
self._source_port.name(),
self._destination_node.name(),
self._destination_port.name())
# Boolean if True we are creating the first instance of this node
# if false the node already exist in the topology
# use to avoid erasing information when reloading
self._creator = False
if source_port.isStub() or destination_port.isStub():
self._stub = True
self._nodes = []
self._link_style = {}
body = self._prepareParams()
if self._link_id:
link_data["link_id"] = self._link_id
self._linkCreatedCallback(link_data)
else:
self._stub = False
self._link_id = str(uuid.uuid4())
self._creator = True
Controller.instance().post("/projects/{project_id}/links".format(project_id=source_node.project().id()), self._linkCreatedCallback, body=body)
# we must request UDP information if the NIO is a NIO UDP and before
# it can be created.
if not self._stub:
def _parseResponse(self, result):
# connect signals used when a NIO has been created by a node
# and this NIO need to be attached to a port connected to this link
source_node.nio_signal.connect(self.newNIOSlot)
destination_node.nio_signal.connect(self.newNIOSlot)
# currently, we support only NIO_UDP for normal connections (non-stub).
if not source_port.defaultNio() == NIOUDP:
raise NotImplementedError()
self._source_udp = None
self._destination_udp = None
# connect signals used to receive a UDP port and host allocated by a node
source_node.allocate_udp_nio_signal.connect(self.UDPPortAllocatedSlot)
destination_node.allocate_udp_nio_signal.connect(self.UDPPortAllocatedSlot)
# request the UDP info for each node
source_node.allocateUDPPort(self._source_port.id())
destination_node.allocateUDPPort(self._destination_port.id())
self._capturing = result.get("capturing", False)
if self._capturing:
self._capture_compute_id = result.get("capture_compute_id", None)
self._capture_file_path = result.get("capture_file_path", None)
if Controller.instance().isRemote() or (self._capture_compute_id and self._capture_compute_id != "local"):
# We need to stream the pcap file content if the controller or compute is remote
if Controller.instance().isRemote() or self._capture_file_path is None:
self._capture_file = QtCore.QTemporaryFile()
self._capture_file.open(QtCore.QFile.WriteOnly)
self._capture_file.setAutoRemove(True)
self._capture_file_path = self._capture_file.fileName()
else:
self._capture_file = QtCore.QFile(self._capture_file_path)
self._capture_file.open(QtCore.QFile.WriteOnly)
self._response_stream = Controller.instance().get("/projects/{project_id}/links/{link_id}/pcap".format(project_id=self.project().id(), link_id=self._link_id),
None,
showProgress=False,
downloadProgressCallback=self._downloadPcapProgress,
ignoreErrors=True, # If something is wrong avoid disconnect us from server
timeout=None)
log.debug("Has successfully started capturing packets on link {} to '{}'".format(self._link_id, self._capture_file_path))
else:
# handle stub connections (to a cloud for instance).
if not source_port.isStub() and destination_port.isStub():
source_node.nio_signal.connect(self.newNIOSlot)
self._source_nio = self._destination_port.defaultNio()
self._source_node.nio_cancel_signal.connect(self.cancelNIOSlot)
self._source_node.addNIO(self._source_port, self._source_nio)
elif not destination_port.isStub() and source_port.isStub():
destination_node.nio_signal.connect(self.newNIOSlot)
self._destination_nio = self._source_port.defaultNio()
self._destination_node.nio_cancel_signal.connect(self.cancelNIOSlot)
self._destination_node.addNIO(self._destination_port, self._destination_nio)
self._response_stream = None
if "nodes" in result:
self._nodes = result["nodes"]
self._updateLabels()
if "filters" in result:
self._filters = result["filters"]
if "link_style" in result:
self._link_style = result["link_style"]
if "suspend" in result:
self._suspend = result["suspend"]
self.updated_link_signal.emit(self._id)
def creator(self):
return self._creator
def suspended(self):
return self._suspend
def toggleSuspend(self):
self._suspend = not self._suspend
self.update()
def initialized(self):
return self._initialized
def addPortLabel(self, port, label):
if port.adapterNumber() == self._source_port.adapterNumber() and port.portNumber() == self._source_port.portNumber() and port.destinationNode() == self._destination_node:
self._source_label = label
else:
self._destination_label = label
label.item_unselected_signal.connect(self.update)
if self.creator():
self.update()
else:
self._updateLabels()
def update(self):
if not self._link_id or self.deleting():
return
body = self._prepareParams()
Controller.instance().put("/projects/{project_id}/links/{link_id}".format(project_id=self._source_node.project().id(), link_id=self._link_id), self.updateLinkCallback, body=body)
def listAvailableFilters(self, callback):
"""
Get the list of available filters
"""
Controller.instance().get("/projects/{project_id}/links/{link_id}/available_filters".format(project_id=self._source_node.project().id(), link_id=self._link_id), callback)
def updateLinkCallback(self, result, error=False, *args, **kwargs):
if error:
log.warning("Error while updating link: {}".format(result["message"]))
return
self._parseResponse(result)
def _updateLabels(self):
for node in self._nodes:
if node["node_id"] == self._source_node.node_id() and node["adapter_number"] == self._source_port.adapterNumber() and node["port_number"] == self._source_port.portNumber():
self._updateLabel(self._source_label, node["label"])
elif node["node_id"] == self._destination_node.node_id() and node["adapter_number"] == self._destination_port.adapterNumber() and node["port_number"] == self._destination_port.portNumber():
self._updateLabel(self._destination_label, node["label"])
else:
log.error("both ports are stub!")
raise NotImplementedError
def _updateLabel(self, label, label_data):
if not label or sip.isdeleted(label):
return
if "text" in label_data:
label.setPlainText(label_data["text"])
if "x" in label_data and "y" in label_data:
label.setPos(label_data["x"], label_data["y"])
if "style" in label_data:
label.setStyle(label_data["style"])
if "rotation" in label_data:
label.setRotation(label_data["rotation"])
def _prepareParams(self):
body = {
"nodes": [
{
"node_id": self._source_node.node_id(),
"adapter_number": self._source_port.adapterNumber(),
"port_number": self._source_port.portNumber(),
},
{
"node_id": self._destination_node.node_id(),
"adapter_number": self._destination_port.adapterNumber(),
"port_number": self._destination_port.portNumber()
}
],
"filters": self._filters,
"link_style": self._link_style,
"suspend": self._suspend
}
if self._source_port.label():
body["nodes"][0]["label"] = self._source_port.label().dump()
if self._destination_port.label():
body["nodes"][1]["label"] = self._destination_port.label().dump()
return body
def _linkCreatedCallback(self, result, error=False, **kwargs):
if error:
log.warning("Error while creating link: {}".format(result["message"]))
self.deleteLink(skip_controller=True)
return
self._initialized = True
# let the GUI know about this link has been created
self.add_link_signal.emit(self._id)
self._source_port.setLinkId(self._id)
self._source_port.setLink(self)
self._source_port.setDestinationNode(self._destination_node)
self._source_port.setDestinationPort(self._destination_port)
self._destination_port.setLinkId(self._id)
self._destination_port.setLink(self)
self._destination_port.setDestinationNode(self._source_node)
self._destination_port.setDestinationPort(self._source_port)
self._link_id = result["link_id"]
self._parseResponse(result)
def link_id(self):
return self._link_id
def deleting(self):
"""
Is the link being deleted
"""
return self._deleting
def setDeleting(self):
"""
Mark this link as being deleted
"""
self._deleting = True
def capturing(self):
"""
Is a capture running on the link?
"""
return self._capturing
def capture_file_path(self):
"""
Path of the capture file
"""
return self._capture_file_path
def project(self):
return self._source_node.project()
@classmethod
def reset(cls):
@@ -124,27 +286,125 @@ class Link(QtCore.QObject):
cls._instance_count = 1
def deleteLink(self):
def __str__(self):
description = "Link from {} port {} to {} port {}".format(self._source_node.name(),
self._source_port.name(),
self._destination_node.name(),
self._destination_port.name())
if self.capturing():
description += "\nPacket capture is active"
for filter_type in self._filters.keys():
description += "\nPacket filter '{}' is active".format(filter_type)
return description
def capture_file_name(self):
"""
:returns: File name for a capture on this link
"""
capture_file_name = "{}_{}_to_{}_{}".format(
self._source_node.name(),
self._source_port.name(),
self._destination_node.name(),
self._destination_port.name())
return re.sub(r"[^0-9A-Za-z_-]", "", capture_file_name)
def deleteLink(self, skip_controller=False):
"""
Deletes this link.
"""
log.info("deleting link from {} {} to {} {}".format(self._source_node.name(),
self._source_port.name(),
self._destination_node.name(),
self._destination_port.name()))
log.debug("deleting link from {} {} to {} {}".format(self._source_node.name(),
self._source_port.name(),
self._destination_node.name(),
self._destination_port.name()))
if skip_controller:
self._linkDeletedCallback({})
else:
self.setDeleting()
Controller.instance().delete("/projects/{project_id}/links/{link_id}".format(project_id=self.project().id(),
link_id=self._link_id),
self._linkDeletedCallback)
def _linkDeletedCallback(self, result, error=False, **kwargs):
"""
Called after the link is remove from the topology
"""
if error:
log.error("Error while deleting link: {}".format(result["message"]))
return
# delete the NIOs on both source and destination nodes
self._source_node.deleteNIO(self._source_port)
self._source_port.setFree()
self._source_node.deleteLink(self)
self._source_node.updated_signal.emit()
self._destination_node.deleteNIO(self._destination_port)
self._destination_port.setFree()
self._destination_node.deleteLink(self)
self._destination_node.updated_signal.emit()
# let the GUI know about this link has been deleted
self.delete_link_signal.emit(self._id)
def startCapture(self, data_link_type, capture_file_name):
data = {
"capture_file_name": capture_file_name,
"data_link_type": data_link_type
}
Controller.instance().post("/projects/{project_id}/links/{link_id}/start_capture".format(project_id=self.project().id(), link_id=self._link_id),
self._startCaptureCallback,
body=data)
def _startCaptureCallback(self, result, error=False, **kwargs):
if error:
log.error("Error while starting capture on link {}: {}".format(self._link_id, result["message"]))
return
def _downloadPcapProgress(self, content, server=None, context={}, **kwargs):
"""
Called for each part of the file of the PCAP
"""
if not self._capture_file_path:
return
self._capture_file.write(content)
self._capture_file.flush()
def stopCapture(self):
if Controller.instance().isRemote() or (self._capture_compute_id and self._capture_compute_id != "local"):
if self._capture_file:
self._capture_file.close()
self._capture_file = None
# if self._capture_file_path and os.path.exists(self._capture_file_path):
# try:
# os.remove(self._capture_file_path)
# except OSError as e:
# log.error("Cannot remove file {}: {}".format(self._capture_file_path, e))
self._capture_file_path = None
Controller.instance().post("/projects/{project_id}/links/{link_id}/stop_capture".format(project_id=self.project().id(),
link_id=self._link_id),
self._stopCaptureCallback)
def _stopCaptureCallback(self, result, error=False, **kwargs):
if error:
log.error("Error while stopping capture on link {}: {}".format(self._link_id, result["message"]))
return
log.debug("Has successfully stopped capturing packets on link {}".format(self._link_id))
def get(self, path, callback, **kwargs):
"""
HTTP Get from a link
"""
Controller.instance().get("/projects/{project_id}/links/{link_id}{path}".format(project_id=self.project().id(),
link_id=self._link_id,
path=path),
callback,
**kwargs)
def id(self):
"""
Returns this link identifier.
@@ -154,210 +414,66 @@ class Link(QtCore.QObject):
return self._id
def UDPPortAllocatedSlot(self, node_id, port_id, lport):
def sourceNode(self):
"""
Slot to receive events from Node instances
when a UDP port has been allocated in order to create a NIO UDP.
Returns the source node for this link.
:param node_id: node identifier
:param port_id: port identifier
:param lport: local UDP port
:returns: Node instance
"""
# check that the node is connected to this link as a source
if node_id == self._source_node.id() and port_id == self._source_port.id():
laddr = self._source_node.server().host
self._source_udp = (lport, laddr)
# disconnect the signal has we don't expect new source UDP info for this link.
self._source_node.allocate_udp_nio_signal.disconnect(self.UDPPortAllocatedSlot)
return self._source_node
log.debug("{} has allocated UDP port {} for host {}".format(self._source_node.name(),
lport,
laddr))
# check that the node is connected to this link as a destination
elif node_id == self._destination_node.id() and port_id == self._destination_port.id():
laddr = self._destination_node.server().host
self._destination_udp = (lport, laddr)
# disconnect the signal has we don't expect new source UDP info for this link.
self._destination_node.allocate_udp_nio_signal.disconnect(self.UDPPortAllocatedSlot)
log.debug("{} has allocated UDP port {} for host {}".format(self._destination_node.name(),
lport,
laddr))
if self._source_udp and self._destination_udp:
# we got UDP info from both source and destination nodes
# meaning we can proceed with the creation of UDP NIOs
lport, laddr = self._source_udp
rport, raddr = self._destination_udp
#TODO: check address compatibility? for instance 127.0.0.1 <-> 83.15.12.2 isn't likely gonna work.
self._source_nio = NIOUDP(lport, raddr, rport)
self._destination_nio = NIOUDP(rport, laddr, lport)
self._source_udp = None
self._destination_udp = None
log.debug("creating UDP tunnel from {}:{} to {}:{} ".format(laddr, lport, raddr, rport))
# add the UDP NIOs to the nodes
self._source_node.nio_cancel_signal.connect(self.cancelNIOSlot)
self._source_node.addNIO(self._source_port, self._source_nio)
self._destination_node.nio_cancel_signal.connect(self.cancelNIOSlot)
self._destination_node.addNIO(self._destination_port, self._destination_nio)
def newNIOSlot(self, node_id, port_id):
def destinationNode(self):
"""
Slot to receive events from Node instances
when a NIO has been created on the server
and are active.
Returns the destination node for this link.
:param node_id: node identifier
:param port_id: port identifier
:returns: Node instance
"""
# check that the node is connected to this link as a source
if node_id == self._source_node.id() and port_id == self._source_port.id():
self._source_nio_active = True
# disconnect the signal has we don't expect new source NIO for this link.
self._source_node.nio_signal.disconnect(self.newNIOSlot)
return self._destination_node
# check that the node is connected to this link as a destination
elif node_id == self._destination_node.id() and port_id == self._destination_port.id():
self._destination_nio_active = True
# disconnect the signal has we don't expect new destination NIO for this link.
self._destination_node.nio_signal.disconnect(self.newNIOSlot)
if not self._stub and self._source_nio_active and self._destination_nio_active:
# both NIOs are active now.
self._addToSourcePort(self._source_nio)
self._addToDestinationPort(self._destination_nio)
self._source_node.nio_cancel_signal.disconnect(self.cancelNIOSlot)
self._destination_node.nio_cancel_signal.disconnect(self.cancelNIOSlot)
self._source_nio_active = False
self._destination_nio_active = False
# let the GUI know about this link has been created
self.add_link_signal.emit(self._id)
elif self._stub and self._source_nio_active:
self._addToSourcePort(self._source_nio)
# add the NIO to destination to show the port is not free.
self._addToDestinationPort(self._source_nio)
self._source_nio_active = False
self._source_node.nio_cancel_signal.disconnect(self.cancelNIOSlot)
self.add_link_signal.emit(self._id)
elif self._stub and self._destination_nio_active:
# add the NIO to source to show the port is not free.
self._addToSourcePort(self._destination_nio)
self._addToDestinationPort(self._destination_nio)
self._destination_nio_active = False
self._destination_node.nio_cancel_signal.disconnect(self.cancelNIOSlot)
self.add_link_signal.emit(self._id)
def _addToSourcePort(self, nio):
def sourcePort(self):
"""
Adds a NIO, a link id and a description to the source port.
Returns the source port for this link.
:param nio: NIO instance
:returns: Port instance
"""
self._source_port.setNio(nio)
self._source_port.setLinkId(self._id)
if not self._source_port.description():
self._source_port.setDescription("connected to {name} on port {port}".format(name=self._destination_node.name(),
port=self._destination_port.name()))
log.debug("{} attached to {} on port {}".format(nio,
self._source_node.name(),
self._source_port.name()))
return self._source_port
def _addToDestinationPort(self, nio):
def destinationPort(self):
"""
Adds a NIO, a link id and a description to the destination port.
Returns the destination port for this link.
:param nio: NIO instance
:returns: Port instance
"""
self._destination_port.setNio(nio)
self._destination_port.setLinkId(self._id)
if not self._destination_port.description():
self._destination_port.setDescription("connected to {name} on port {port}".format(name=self._source_node.name(),
port=self._source_port.name()))
return self._destination_port
log.debug("{} attached to {} on port {}".format(nio,
self._destination_node.name(),
self._destination_port.name()))
def cancelNIOSlot(self, node_id):
def getNodePort(self, node):
"""
Slot to receive events from Node instances
when a NIO has been canceled because of an
error returned by the server.
Search the port in the link corresponding to this node
:param node_id: node identifier
:returns: Node instance
"""
if self._destination_node == node:
return self._destination_port
return self._source_port
if not self._stub:
if self._source_node.id() != node_id:
# the destination node has canceled its NIO allocation
self._destination_node.nio_signal.disconnect(self.newNIOSlot)
self._source_node.deleteNIO(self._source_port)
self._source_port.setFree()
self._source_node.updated_signal.emit()
elif self._destination_node.id() != node_id:
# the source node has canceled its NIO allocation
self._source_node.nio_signal.disconnect(self.newNIOSlot)
self._destination_node.deleteNIO(self._destination_port)
self._destination_port.setFree()
self._destination_node.updated_signal.emit()
self._source_node.nio_cancel_signal.disconnect(self.cancelNIOSlot)
self._destination_node.nio_cancel_signal.disconnect(self.cancelNIOSlot)
else:
if self._source_node.id() == node_id:
self._source_node.nio_signal.disconnect(self.newNIOSlot)
self._source_node.nio_cancel_signal.disconnect(self.cancelNIOSlot)
else:
self._destination_node.nio_signal.disconnect(self.newNIOSlot)
self._destination_node.nio_cancel_signal.disconnect(self.cancelNIOSlot)
self._source_nio_active = False
self._destination_nio_active = False
def description(self):
def filters(self):
"""
Returns the text description of this link.
:returns: description
:returns: List the filters active on the node
"""
return self._filters
return self._description
def setDescription(self, description):
def setFilters(self, filters):
"""
Adds a text description to this link.
:param description: description
:params filters: List of filters
"""
self._filters = filters
self._description = description
def dump(self):
def setLinkStyle(self, link_style):
"""
Returns a representation of this link.
:returns: dictionary
:params _link_style: Set link style attributes
"""
return {"id": self.id(),
"description": self._description,
"source_node_id": self._source_node.id(),
"source_port_id": self._source_port.id(),
"destination_node_id": self._destination_node.id(),
"destination_port_id": self._destination_port.id(),
}
self._link_style = link_style

511
gns3/local_config.py Normal file
View File

@@ -0,0 +1,511 @@
# -*- 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 sys
import os
import json
import shutil
import copy
import psutil
from .qt import QtCore, QtWidgets
from .version import __version__, __version_info__
from .utils import parse_version
from .local_server_config import LocalServerConfig
from .settings import LOCAL_SERVER_SETTINGS
import logging
log = logging.getLogger(__name__)
class LocalConfig(QtCore.QObject):
"""
Handles the local GUI settings.
"""
config_changed_signal = QtCore.Signal()
def __init__(self, config_file=None):
"""
:param config_file: Path to the config file (override all other config, useful for tests)
"""
super().__init__()
self._profile = None
self._config_file = config_file
self._migrateOldConfigPath()
self._resetLoadConfig()
def _resetLoadConfig(self):
"""
Reload the config from scratch everything is clean
"""
self._settings = {}
self._last_config_changed = None
if sys.platform.startswith("win"):
filename = "gns3_gui.ini"
else:
filename = "gns3_gui.conf"
appname = "GNS3"
if sys.platform.startswith("win"):
# On windows, the system wide configuration file location is %COMMON_APPDATA%/GNS3/gns3_gui.conf
common_appdata = os.path.expandvars("%COMMON_APPDATA%")
system_wide_config_file = os.path.join(common_appdata, appname, filename)
else:
# On UNIX-like platforms, the system wide configuration file location is /etc/xdg/GNS3/gns3_gui.conf
system_wide_config_file = os.path.join("/etc/xdg", appname, filename)
if not self._config_file:
self._config_file = os.path.join(self.configDirectory(), filename)
# First load system wide settings
if os.path.exists(system_wide_config_file):
self._readConfig(system_wide_config_file)
config_file_in_cwd = os.path.join(os.getcwd(), filename)
if os.path.exists(config_file_in_cwd):
# use any config file present in the current working directory
self._config_file = config_file_in_cwd
elif not os.path.exists(self._config_file):
try:
# create the config file if it doesn't exist
os.makedirs(os.path.dirname(self._config_file), exist_ok=True)
if sys.platform.startswith("win"):
old_config_path = os.path.join(os.path.expandvars("%APPDATA%"), "GNS3", filename)
else:
old_config_path = os.path.join(os.path.expanduser("~"), ".config", "GNS3", filename)
# TODO: migrate versioned config file from a previous version of GNS3 (for instance 2.2 -> 2.3) + support profiles
if os.path.exists(old_config_path):
# migrate post version 2.2.0 configuration file
shutil.copyfile(old_config_path, self._config_file)
# reset the local server path and ubridge path
settings = LocalServerConfig.instance().loadSettings("Server", LOCAL_SERVER_SETTINGS)
settings["path"] = ""
settings["ubridge_path"] = ""
LocalServerConfig.instance().saveSettings("Server", settings)
else:
# create a new config
with open(self._config_file, "w", encoding="utf-8") as f:
json.dump({"version": __version__, "type": "settings"}, f)
except OSError as e:
log.error("Could not create the config file {}: {}".format(self._config_file, e))
user_settings = self._readConfig(self._config_file)
# overwrite system wide settings with user specific ones
self._settings.update(user_settings)
self._migrateOldConfig()
self.writeConfig()
def profile(self):
"""
:returns: Current settings profile
"""
return self._profile
def setProfile(self, profile):
previous_profile = self._profile
if profile == "default":
self._profile = None
else:
self._profile = profile
if previous_profile != self._profile:
self._config_file = None
self._resetLoadConfig()
def configDirectory(self):
"""
Get the configuration directory
"""
version = "{}.{}".format(__version_info__[0], __version_info__[1])
if sys.platform.startswith("win"):
appdata = os.path.expandvars("%APPDATA%")
path = os.path.join(appdata, "GNS3", version)
else:
home = os.path.expanduser("~")
path = os.path.join(home, ".config", "GNS3", version)
if self._profile is not None:
path = os.path.join(path, "profiles", self._profile)
return os.path.normpath(path)
def runAsRootPath(self):
"""
Gets run as root filename
:return: string
"""
return os.path.join(self.configDirectory(), "run_as_root")
def _migrateOldConfigPath(self):
"""
Migrate pre 1.4 config path
"""
# In < 1.4 on Mac the config was in a gns3.net directory
# We have move to same location as Linux
if sys.platform.startswith("darwin"):
version = "{}.{}".format(__version_info__[0], __version_info__[1])
old_path = os.path.join(os.path.expanduser("~"), ".config", "gns3.net")
new_path = os.path.join(os.path.expanduser("~"), ".config", "GNS3", version)
if os.path.exists(old_path) and not os.path.exists(new_path):
try:
shutil.copytree(old_path, new_path)
except OSError as e:
log.error("Can't copy the old config: %s", str(e))
def _migrateOldConfig(self):
"""
Migrate config from a previous version.
"""
# Display an error if settings come from a more recent version of GNS3
# patch level version are compatible (ex 1.5.3 and 1.5.2). But if you open
# settings from 1.6.1 with 1.5.1 you will have an error
if "version" in self._settings:
if parse_version(self._settings["version"])[:2] > parse_version(__version__)[:2]:
app = QtWidgets.QApplication(sys.argv) # We need to create an application because settings are loaded before Qt init
error_message = "Settings are for version {} of GNS3. It is not possible to use a previous version of GNS3 without risking losing data. Delete the settings in '{}' to start GNS3".format(self._settings["version"], self.configDirectory())
QtWidgets.QMessageBox.critical(False, "Version error", error_message)
# Exit immediately not clean but we want to avoid any side effect that could corrupt the file
QtCore.QTimer.singleShot(0, app.quit)
app.exec_()
sys.exit(1)
if "version" not in self._settings or parse_version(self._settings["version"]) < parse_version("1.4.0alpha1"):
servers = self._settings.get("Servers", {})
if "LocalServer" in self._settings:
servers["local_server"] = copy.copy(self._settings["LocalServer"])
# We migrate the server binary for OSX due to the change from py2app to CX freeze
if servers["local_server"]["path"] == "/Applications/GNS3.app/Contents/Resources/server/Contents/MacOS/gns3server":
servers["local_server"]["path"] = "gns3server"
if "RemoteServers" in self._settings:
servers["remote_servers"] = copy.copy(self._settings["RemoteServers"])
self._settings["Servers"] = servers
if "GUI" in self._settings:
main_window = self._settings.get("MainWindow", {})
main_window["hide_getting_started_dialog"] = self._settings["GUI"].get("hide_getting_started_dialog", False)
self._settings["MainWindow"] = main_window
if "version" not in self._settings or parse_version(self._settings["version"]) < parse_version("1.4.1dev2"):
if sys.platform.startswith("darwin"):
from .settings import PRECONFIGURED_TELNET_CONSOLE_COMMANDS, DEFAULT_TELNET_CONSOLE_COMMAND
if "MainWindow" in self._settings:
if self._settings["MainWindow"].get("telnet_console_command") not in PRECONFIGURED_TELNET_CONSOLE_COMMANDS.values():
self._settings["MainWindow"]["telnet_console_command"] = DEFAULT_TELNET_CONSOLE_COMMAND
# Migrate 1.X to 2.0
if "version" not in self._settings or parse_version(self._settings["version"]) < parse_version("2.0.0"):
if "Qemu" in self._settings:
# The internet VM is replaced by the nat Node
# we remove it from the list of available VM
vms = []
for vm in self._settings["Qemu"].get("vms", []):
if vm.get("hda_disk_image") != "core-linux-6.4-internet-0.1.img":
vms.append(vm)
self._settings["Qemu"]["vms"] = vms
# Starting with 2.0.0dev5 IOU licence is stored in the settings
if "version" not in self._settings or parse_version(self._settings["version"]) < parse_version("2.0.0"):
if "IOU" in self._settings and "iourc_path" in self._settings["IOU"] and "iourc_content" not in self._settings["IOU"]:
try:
with open(self._settings["IOU"]["iourc_path"], "r", encoding="utf-8") as f:
self._settings["IOU"]["iourc_content"] = f.read().replace("\r\n", "\n")
del self._settings["IOU"]["iourc_path"]
except OSError as e:
log.warning("Can't import IOU licence {}: {}".format(self._settings["IOU"]["iourc_path"], str(e)))
except UnicodeDecodeError as e:
log.warning("Non ascii characters in iourc file {}, please remove them: {}".format(self._settings["IOU"]["iourc_path"], str(e)))
def _readConfig(self, config_path):
"""
Read the configuration file.
"""
log.debug("Load config from %s", config_path)
try:
with open(config_path, "r", encoding="utf-8") as f:
self._last_config_changed = os.stat(config_path).st_mtime
config = json.load(f)
self._settings.update(config)
except (ValueError, OSError) as e:
log.error("Could not read the config file {}: {}".format(self._config_file, e))
# Update already loaded section
for section in self._settings.keys():
if isinstance(self._settings[section], dict):
self.loadSectionSettings(section, self._settings[section])
return dict()
def writeConfig(self):
"""
Write the configuration file.
"""
self._settings["version"] = __version__
try:
temporary = os.path.join(os.path.dirname(self._config_file), "gns3_gui.tmp")
with open(temporary, "w", encoding="utf-8") as f:
json.dump(self._settings, f, sort_keys=True, indent=4)
shutil.move(temporary, self._config_file)
log.debug("Configuration save to %s", self._config_file)
self._last_config_changed = os.stat(self._config_file).st_mtime
except (ValueError, OSError) as e:
log.error("Could not write the config file {}: {}".format(self._config_file, e))
def checkConfigChanged(self):
try:
if self._last_config_changed and self._last_config_changed < os.stat(self._config_file).st_mtime:
log.debug("Client config has changed, reloading it...")
self._readConfig(self._config_file)
self.config_changed_signal.emit()
except OSError as e:
log.error("Error when checking for changes {}: {}".format(self._config_file, str(e)))
def configFilePath(self):
"""
Returns the config file path.
:returns: path to the config file.
"""
return self._config_file
def setConfigFilePath(self, config_file):
"""
Set a new config file
:returns: path to the config file.
"""
self._config_file = config_file
self._resetLoadConfig()
def settings(self):
"""
Get the settings.
:returns: settings (dict)
"""
return copy.deepcopy(self._settings)
def setSettings(self, settings):
"""
Save the settings.
:param settings: settings to save (dict)
"""
if self._settings != settings:
self._settings.update(settings)
self.writeConfig()
self.config_changed_signal.emit()
def loadSectionSettings(self, section, default_settings):
"""
Get all the settings from a given section.
:param default_settings: setting names and default values (dict)
:returns: settings (dict)
"""
settings = self.settings().get(section, dict())
changed = False
def _copySettings(local, default):
"""
Copy only existing settings, ignore the other.
Add default values if require.
"""
nonlocal changed
# use default values for missing settings
for name, value in default.items():
if name not in local:
local[name] = value
changed = True
elif isinstance(value, dict):
local[name] = _copySettings(local[name], default[name])
return local
settings = _copySettings(settings, default_settings)
self._settings[section] = settings
if changed:
log.debug("Section %s has missing default values. Adding keys %s Saving configuration", section, ','.join(set(default_settings.keys()) - set(settings.keys())))
self.writeConfig()
return copy.deepcopy(settings)
def saveSectionSettings(self, section, settings):
"""
Save all the settings in a given section.
:param section: section name
:param settings: settings to save (dict)
"""
if section not in self._settings:
self._settings[section] = {}
if self._settings[section] != settings:
self._settings[section].update(copy.deepcopy(settings))
log.debug("Section %s has changed. Saving configuration", section)
self.writeConfig()
else:
log.debug("Section %s has not changed. Skip saving configuration", section)
def experimental(self):
"""
:returns: Boolean. True if experimental features allowed
"""
from gns3.settings import GENERAL_SETTINGS
return self.loadSectionSettings("MainWindow", GENERAL_SETTINGS)["experimental_features"]
def hdpi(self):
"""
:returns: Boolean. True if hdpi is allowed
"""
from gns3.settings import GENERAL_SETTINGS
return self.loadSectionSettings("MainWindow", GENERAL_SETTINGS)["hdpi"]
def multiProfiles(self):
"""
:returns: Boolean. True if multi_profiles is enabled
"""
from gns3.settings import GENERAL_SETTINGS
return self.loadSectionSettings("MainWindow", GENERAL_SETTINGS)["multi_profiles"]
def setMultiProfiles(self, value):
from gns3.settings import GENERAL_SETTINGS
settings = self.loadSectionSettings("MainWindow", GENERAL_SETTINGS)
settings["multi_profiles"] = value
self.saveSectionSettings("MainWindow", settings)
def directFileUpload(self):
"""
:returns: Boolean. True if direct_file_upload is enabled
"""
from gns3.settings import GENERAL_SETTINGS
return self.loadSectionSettings("MainWindow", GENERAL_SETTINGS)["direct_file_upload"]
def setDirectFileUpload(self, value):
from gns3.settings import GENERAL_SETTINGS
settings = self.loadSectionSettings("MainWindow", GENERAL_SETTINGS)
settings["direct_file_upload"] = value
self.saveSectionSettings("MainWindow", settings)
def showInterfaceLabelsOnNewProject(self):
"""
:returns: Boolean. True if show_interface_labels_on_new_project is enabled
"""
from gns3.settings import GRAPHICS_VIEW_SETTINGS
return self.loadSectionSettings("GraphicsView", GRAPHICS_VIEW_SETTINGS).get("show_interface_labels_on_new_project", False)
def setShowInterfaceLabelsOnNewProject(self, value):
from gns3.settings import GRAPHICS_VIEW_SETTINGS
settings = self.loadSectionSettings("GraphicsView", GRAPHICS_VIEW_SETTINGS)
settings["show_interface_labels_on_new_project"] = value
self.saveSectionSettings("GraphicsView", settings)
def showGridOnNewProject(self):
"""
:returns: Boolean. True if show_grid_on_new_project is enabled
"""
from gns3.settings import GRAPHICS_VIEW_SETTINGS
return self.loadSectionSettings("GraphicsView", GRAPHICS_VIEW_SETTINGS).get("show_grid_on_new_project", False)
def snapToGridOnNewProject(self):
"""
:returns: Boolean. True if snap_to_grid_on_new_project is enabled
"""
from gns3.settings import GRAPHICS_VIEW_SETTINGS
return self.loadSectionSettings("GraphicsView", GRAPHICS_VIEW_SETTINGS).get("snap_to_grid_on_new_project", False)
@staticmethod
def instance():
"""
Singleton to return only on instance of LocalConfig.
:returns: instance of LocalConfig
"""
if not hasattr(LocalConfig, "_instance") or LocalConfig._instance is None:
LocalConfig._instance = LocalConfig()
return LocalConfig._instance
@staticmethod
def isMainGui():
"""
:returns: Return true if we are the main gui (first gui to start)
"""
my_pid = os.getpid()
pid_path = os.path.join(LocalConfig.instance().configDirectory(), "gns3_gui.pid")
if os.path.exists(pid_path):
try:
with open(pid_path) as f:
pid = int(f.read())
if pid != my_pid:
try:
process = psutil.Process(pid=pid)
ps_name = process.name().lower()
except (OSError, psutil.NoSuchProcess, psutil.AccessDenied):
pass
else:
if "gns3" in ps_name or "python" in ps_name:
# Process run under the same user id
if sys.platform.startswith("win") or process.uids()[0] == os.getuid():
return False
else:
return True
except (OSError, ValueError) as e:
log.critical("Can't read pid file %s: %s", pid_path, str(e))
return False
try:
with open(pid_path, 'w+') as f:
f.write(str(my_pid))
except OSError as e:
log.critical("Can't write pid file %s: %s", pid_path, str(e))
return False
return True

616
gns3/local_server.py Normal file
View File

@@ -0,0 +1,616 @@
#!/usr/bin/env python
#
# Copyright (C) 2016 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 os
import sys
import copy
import stat
import shlex
import socket
import shutil
import random
import string
import struct
import psutil
import signal
import subprocess
from gns3.qt import QtWidgets, QtCore, qslot
from gns3.settings import LOCAL_SERVER_SETTINGS, DEFAULT_LOCAL_SERVER_HOST
from gns3.local_config import LocalConfig
from gns3.local_server_config import LocalServerConfig
from gns3.utils.wait_for_connection_worker import WaitForConnectionWorker
from gns3.utils.progress_dialog import ProgressDialog
from gns3.utils.sudo import sudo
from gns3.http_client import HTTPClient
from gns3.controller import Controller
import logging
log = logging.getLogger(__name__)
class StopLocalServerWorker(QtCore.QObject):
"""
Worker for displaying a progress dialog when closing
the server
"""
# signals to update the progress dialog.
error = QtCore.pyqtSignal(str, bool)
finished = QtCore.pyqtSignal()
updated = QtCore.pyqtSignal(int)
def __init__(self, local_server_process):
super().__init__()
self._local_server_process = local_server_process
self._precision = 100 # In MS
self._remaining_trial = int(10 * (1000 / self._precision))
@qslot
def _callbackSlot(self, *params):
self._local_server_process.poll()
if self._local_server_process.returncode is None and self._remaining_trial > 0:
self._remaining_trial -= 1
QtCore.QTimer.singleShot(self._precision, self._callbackSlot)
else:
self.finished.emit()
def run(self):
QtCore.QTimer.singleShot(1000, self._callbackSlot)
def cancel(self):
return
class LocalServer(QtCore.QObject):
"""
Manage the local server process
"""
def __init__(self, parent=None):
# Remember if the server was started by us or not
self._server_started_by_me = False
self._local_server_path = ""
self._local_server_process = None
super().__init__()
self._parent = parent
self._config_directory = LocalConfig.instance().configDirectory()
self._settings = {}
self.localServerSettings()
self._port = self._settings.get("port", 3080)
if not self._settings.get("auto_start", True):
if self._settings.get("host") is None:
self._http_client = HTTPClient(self._settings)
Controller.instance().setHttpClient(self._http_client)
else:
self._http_client = None
self._stopping = False
self._timer = QtCore.QTimer()
self._timer.setInterval(5000)
self._timer.timeout.connect(self._checkLocalServerRunningSlot)
self._timer.start()
def _pid_path(self):
"""
:returns: Path of the PID file
"""
return os.path.join(self._config_directory, "gns3_server.pid")
def parent(self):
"""
Parent window
"""
if self._parent is None:
from gns3.main_window import MainWindow
return MainWindow.instance()
return self._parent
def _checkWindowsService(self, service_name):
try:
import pywintypes
import win32service
import win32serviceutil
except ImportError as e:
log.error("Could not check if the {} service is running: {}".format(service_name, e))
return
try:
if win32serviceutil.QueryServiceStatus(service_name, None)[1] != win32service.SERVICE_RUNNING:
return False
except pywintypes.error as e:
if e.winerror == 1060: # service is not installed
return False
else:
log.error("Could not check if the {} service is running: {}".format(service_name, e.strerror))
return True
def _checkUbridgePermissions(self):
"""
Checks that uBridge can interact with network interfaces.
"""
path = os.path.abspath(self._settings["ubridge_path"])
if not path or len(path) == 0 or not os.path.exists(path) or not os.path.isfile(path):
return False
if sys.platform.startswith("win"):
# do not check anything on Windows
return True
if os.geteuid() == 0:
# we are root, so we should have privileged access.
return True
request_setuid = False
if sys.platform.startswith("linux"):
# test if the executable has the CAP_NET_RAW capability (Linux only)
try:
# test the 2nd byte and check if the 13th bit (CAP_NET_RAW) is set
if "security.capability" not in os.listxattr(path) or not struct.unpack("<IIIII", os.getxattr(path, "security.capability"))[1] & 1 << 13:
proceed = QtWidgets.QMessageBox.question(
self.parent(),
"uBridge",
"uBridge requires CAP_NET_RAW capability to interact with network interfaces. Set the capability to uBridge? All users on the system will be able to read packet from the network interfaces.",
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if proceed == QtWidgets.QMessageBox.Yes:
sudo(["setcap", "cap_net_admin,cap_net_raw=ep", path])
except AttributeError:
# Due to a Python bug, os.listxattr could be missing: https://github.com/GNS3/gns3-gui/issues/2010
log.warning("Could not determine if CAP_NET_RAW capability is set for uBridge (Python bug)")
return True
except OSError as e:
QtWidgets.QMessageBox.critical(self.parent(), "uBridge", "Can't set CAP_NET_RAW capability to uBridge {}: {}".format(path, str(e)))
request_setuid = True
if sys.platform.startswith("darwin") or request_setuid:
try:
if os.stat(path).st_uid != 0 or not os.stat(path).st_mode & stat.S_ISUID:
proceed = QtWidgets.QMessageBox.question(
self.parent(),
"uBridge",
"uBridge requires root permissions to interact with network interfaces. Set root permissions to uBridge? All admin users on the system will be able to read packet from the network interfaces.",
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if proceed == QtWidgets.QMessageBox.Yes:
from gns3.utils.macos_ubridge_setuid import macos_ubridge_setuid
if sys.platform.startswith("darwin") and hasattr(sys, "frozen"):
macos_ubridge_setuid()
else:
sudo(["chown", "root:admin", path], ["chmod", "4750", path])
except OSError as e:
QtWidgets.QMessageBox.critical(self.parent(), "uBridge", "Can't set root permissions to uBridge {}: {}".format(path, str(e)))
return False
return True
def _passwordGenerate(self):
"""
Generate a random password
"""
return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(64))
def localServerSettings(self):
"""
Returns the local server settings.
:returns: local server settings (dict)
"""
settings = LocalServerConfig.instance().loadSettings("Server", LOCAL_SERVER_SETTINGS)
self._settings = copy.copy(settings)
# user & password
if settings["auth"] is True and not settings["user"].strip():
settings["user"] = "admin"
settings["password"] = self._passwordGenerate()
# local GNS3 server path
local_server_path = shutil.which(settings["path"].strip())
if local_server_path is None:
default_server_path = shutil.which("gns3server")
if default_server_path is not None:
settings["path"] = os.path.abspath(default_server_path)
else:
settings["path"] = os.path.abspath(local_server_path)
# uBridge path
ubridge_path = shutil.which(settings["ubridge_path"].strip())
if ubridge_path is None:
default_ubridge_path = shutil.which("ubridge")
if default_ubridge_path is not None:
settings["ubridge_path"] = os.path.abspath(default_ubridge_path)
else:
settings["ubridge_path"] = os.path.abspath(ubridge_path)
if self._settings != settings:
self.updateLocalServerSettings(settings)
return settings
def updateLocalServerSettings(self, new_settings):
"""
Update the local server settings. Keep the key not in new_settings
"""
if "host" in new_settings and new_settings["host"] is None:
new_settings["host"] = DEFAULT_LOCAL_SERVER_HOST
old_settings = copy.copy(self._settings)
if not self._settings:
self._settings = new_settings
else:
self._settings.update(new_settings)
self._port = self._settings["port"]
LocalServerConfig.instance().saveSettings("Server", self._settings)
# Settings have changed we need to restart the server
if old_settings != self._settings:
if self._settings["auto_start"]:
# We restart the local server only if we really need. Auth can be hot change
settings_require_restart = ('host', 'port', 'path')
need_restart = False
for s in settings_require_restart:
if old_settings.get(s) != self._settings.get(s):
need_restart = True
if need_restart:
self.stopLocalServer(wait=True)
self.localServerAutoStartIfRequired()
# If the controller is remote:
else:
self.stopLocalServer(wait=True)
if self._settings.get("host") is None:
self._http_client = None
else:
self._http_client = HTTPClient(self._settings)
Controller.instance().setHttpClient(self._http_client)
def shouldLocalServerAutoStart(self):
"""
Returns either the local server
is automatically started on startup.
:returns: boolean
"""
return self._settings["auto_start"] and self._settings["host"] is not None
def localServerPath(self):
"""
Returns the local server path.
:returns: path to local server program.
"""
return self._settings["path"]
def _killAlreadyRunningServer(self):
"""
Kill a running zombie server (started by a gui that no longer exists)
This will not kill server started by hand.
"""
try:
if os.path.exists(self._pid_path()):
with open(self._pid_path()) as f:
pid = int(f.read())
process = psutil.Process(pid=pid)
log.info("Kill already running server with PID %d", pid)
process.kill()
except (OSError, ValueError, psutil.NoSuchProcess, psutil.AccessDenied):
# Permission issue, or process no longer exists, or file is empty
return
def localServerAutoStartIfRequired(self):
"""
Try to start the embedded gns3 server.
"""
if not self.shouldLocalServerAutoStart():
self._http_client = HTTPClient(self._settings)
Controller.instance().setHttpClient(self._http_client)
return
if self.isLocalServerRunning() and self._server_started_by_me:
return True
# We check if two gui are not launched at the same time
# to avoid killing the server of the other GUI
if not LocalConfig.isMainGui():
log.info("Not the main GUI, will not auto start the server")
self._http_client = HTTPClient(self._settings)
Controller.instance().setHttpClient(self._http_client)
return True
if self.isLocalServerRunning():
log.debug("A local server already running on this host")
# Try to kill the server. The server can be still running after
# if the server was started by hand
self._killAlreadyRunningServer()
if not self.isLocalServerRunning():
if not self.initLocalServer():
QtWidgets.QMessageBox.critical(self.parent(), "Local server", "Could not start the local server process: {}".format(self._settings["path"]))
return False
if not self.startLocalServer():
QtWidgets.QMessageBox.critical(self.parent(), "Local server", "Could not start the local server process: {}".format(self._settings["path"]))
return False
if self.parent():
worker = WaitForConnectionWorker(self._settings["host"], self._port)
progress_dialog = ProgressDialog(worker,
"Local server",
"Connecting to server {} on port {}...".format(self._settings["host"], self._port),
"Cancel", busy=True, parent=self.parent())
progress_dialog.show()
if not progress_dialog.exec_():
return False
self._server_started_by_me = True
self._http_client = HTTPClient(self._settings)
Controller.instance().setHttpClient(self._http_client)
return True
def initLocalServer(self):
"""
Initialize the local server.
"""
self._checkUbridgePermissions()
if sys.platform.startswith("win"):
import pywintypes
try:
if not self._checkWindowsService("npf") and not self._checkWindowsService("npcap"):
log.warning("The NPF or NPCAP service is not installed, please install Winpcap or Npcap and reboot.")
except pywintypes.error as e:
log.warning("Could not check if the NPF or Npcap service is running: {}".format(e.strerror))
self._port = self._settings["port"]
# check the local server path
local_server_path = self.localServerPath()
if not local_server_path:
log.warning("No local server is configured")
return False
if not os.path.isfile(local_server_path):
QtWidgets.QMessageBox.critical(self.parent(), "Local server", "Could not find local server {}".format(local_server_path))
return False
elif not os.access(local_server_path, os.X_OK):
QtWidgets.QMessageBox.critical(self.parent(), "Local server", "{} is not an executable".format(local_server_path))
return False
try:
# check if the local address still exists
for res in socket.getaddrinfo(self._settings["host"], 0, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
af, socktype, proto, _, sa = res
with socket.socket(af, socktype, proto) as sock:
sock.bind(sa)
break
except OSError as e:
QtWidgets.QMessageBox.critical(self.parent(), "Local server", "Could not bind with {}: {} (please check your host binding setting in the preferences)".format(self._settings["host"], e))
return False
try:
# check if the port is already taken
find_unused_port = False
for res in socket.getaddrinfo(self._settings["host"], self._port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
af, socktype, proto, _, sa = res
with socket.socket(af, socktype, proto) as sock:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(sa)
break
except OSError as e:
log.warning("Could not use socket {}:{} {}".format(self._settings["host"], self._port, e))
find_unused_port = True
if find_unused_port:
# find an alternate port for the local server
old_port = self._port
try:
self._port = self._findUnusedLocalPort(self._settings["host"])
except OSError as e:
QtWidgets.QMessageBox.critical(self.parent(), "Local server", "Could not find an unused port for the local server: {}".format(e))
return False
log.warning("The server port {} is already in use, fallback to port {}".format(old_port, self._port))
return True
def _findUnusedLocalPort(self, host):
"""
Find an unused port.
:param host: server hosts
:returns: port number
"""
with socket.socket() as s:
s.bind((host, 0))
return s.getsockname()[1]
def startLocalServer(self):
"""
Starts the local server process.
"""
self._stopping = False
path = self.localServerPath()
command = '"{executable}" --local'.format(executable=path)
if LocalConfig.instance().profile():
command += " --profile {}".format(LocalConfig.instance().profile())
if self._settings["allow_console_from_anywhere"]:
# allow connections to console from remote addresses
command += " --allow"
if logging.getLogger().isEnabledFor(logging.DEBUG):
command += " --debug"
settings_dir = self._config_directory
if os.path.isdir(settings_dir):
# save server logging info to a file in the settings directory
logpath = os.path.join(settings_dir, "gns3_server.log")
if os.path.isfile(logpath):
# delete the previous log file
try:
os.remove(logpath)
except FileNotFoundError:
pass
except OSError as e:
log.warning("could not delete server log file {}: {}".format(logpath, e))
command += ' --log="{}" --pid="{}"'.format(logpath, self._pid_path())
log.debug("Starting local server process with {}".format(command))
try:
if sys.platform.startswith("win"):
# use the string on Windows
self._local_server_process = subprocess.Popen(
command,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP,
stderr=subprocess.PIPE,
env=os.environ)
else:
# use arguments on other platforms
args = shlex.split(command)
self._local_server_process = subprocess.Popen(args, stderr=subprocess.PIPE, env=os.environ)
except (OSError, subprocess.SubprocessError) as e:
log.warning('Could not start local server "{}": {}'.format(command, e))
return False
log.debug("Local server process has started (PID={})".format(self._local_server_process.pid))
return True
def _checkLocalServerRunningSlot(self):
if self._local_server_process and not self._stopping:
if not self.localServerProcessIsRunning():
log.error("Local server process has stopped")
try:
log.error(self._local_server_process.stderr.read().decode())
except (OSError, UnicodeDecodeError):
pass
self._local_server_process = None
def localServerProcessIsRunning(self):
"""
Returns either the local server is running.
:returns: boolean
"""
try:
if self._local_server_process and self._local_server_process.poll() is None:
return True
except OSError:
pass
return False
def isLocalServerRunning(self):
"""
Synchronous check if a server is already running on this host.
:returns: boolean
"""
status, json_data = HTTPClient(self._settings).getSynchronous("GET", "/version")
if status == 401: # Auth issue that need to be solved later
return True
elif json_data is None:
return False
elif status != 200:
return False
else:
version = json_data.get("version", None)
if version is None:
log.debug("Server is not a GNS3 server")
return False
return True
def stopLocalServer(self, wait=False):
"""
Stops the local server.
:param wait: wait for the server to stop
"""
if self.localServerProcessIsRunning():
self._stopping = True
log.debug("Stopping local server (PID={})".format(self._local_server_process.pid))
# local server is running, let's stop it
if self._http_client:
self._http_client.shutdown()
if wait:
worker = StopLocalServerWorker(self._local_server_process)
progress_dialog = ProgressDialog(worker, "Local server", "Waiting for the local server to stop...", None, busy=True, parent=self.parent())
progress_dialog.show()
progress_dialog.exec_()
if self._local_server_process.returncode is None:
self._killLocalServer()
self._server_started_by_me = False
def _killLocalServer(self):
# the local server couldn't be stopped with the normal procedure
try:
if sys.platform.startswith("win"):
self._local_server_process.send_signal(signal.CTRL_BREAK_EVENT)
else:
self._local_server_process.send_signal(signal.SIGINT)
# If the process is already dead we received a permission error
# it's a race condition between the timeout and send signal
except (PermissionError, SystemError):
pass
try:
# wait for the server to stop for maximum x seconds
self._local_server_process.wait(timeout=60)
except subprocess.TimeoutExpired:
proceed = QtWidgets.QMessageBox.question(self.parent(),
"Local server",
"The Local server cannot be stopped, would you like to kill it?",
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if proceed == QtWidgets.QMessageBox.Yes:
self._local_server_process.kill()
@staticmethod
def instance():
"""
Singleton to return only on instance of LocalServer.
:returns: instance of LocalServer
"""
if not hasattr(LocalServer, '_instance') or LocalServer._instance is None:
LocalServer._instance = LocalServer()
return LocalServer._instance
def main():
import pprint
pp = pprint.PrettyPrinter(indent=4)
print("Local server config")
local_server = LocalServer(False)
pp.pprint(local_server.localServerSettings())
local_server.localServerAutoStart()
local_server.stopLocalServer()
if __name__ == '__main__':
main()

163
gns3/local_server_config.py Normal file
View File

@@ -0,0 +1,163 @@
# -*- 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 os
import sys
import configparser
import logging
log = logging.getLogger(__name__)
class LocalServerConfig:
"""
Local server configuration.
"""
def __init__(self, config_file=None):
appname = "GNS3"
self._config = configparser.RawConfigParser()
if config_file:
self._config_file = config_file
else:
if sys.platform.startswith("win"):
filename = "gns3_server.ini"
else:
filename = "gns3_server.conf"
from .local_config import LocalConfig
if sys.platform.startswith("win"):
self._config_file = os.path.join(LocalConfig.instance().configDirectory(), filename)
else:
self._config_file = os.path.join(LocalConfig.instance().configDirectory(), filename)
try:
# create the config file if it doesn't exist
open(self._config_file, "a").close()
except OSError as e:
log.error("Could not create the local server configuration {}: {}".format(self._config_file, e))
self.readConfig()
def setConfigFile(self, path):
"""
Change the location of the server config (use for test)
"""
self._config = configparser.RawConfigParser()
self._config_file = path
self.readConfig()
def readConfig(self):
"""
Read the configuration file.
"""
try:
self._config.read(self._config_file, encoding="utf-8")
except (OSError, configparser.Error, UnicodeEncodeError, UnicodeDecodeError) as e:
log.error("Could not read the local server configuration {}: {}".format(self._config_file, e))
def writeConfig(self):
"""
Write the configuration file.
"""
try:
log.debug("Write configuration file %s", self._config_file)
with open(self._config_file, "w", encoding="utf-8") as fp:
self._config.write(fp)
except (OSError, configparser.Error) as e:
log.error("Could not write the local server configuration {}: {}".format(self._config_file, e))
def loadSettings(self, section, default_settings):
"""
Get all the settings from a given section.
:param section: section name
:param default_settings: setting names and default values (dict)
:returns: settings (dict)
"""
if section not in self._config:
self._config[section] = {}
settings = {}
for name, default in default_settings.items():
if isinstance(default, bool):
settings[name] = self._config[section].getboolean(name, default)
elif isinstance(default, int):
settings[name] = self._config[section].getint(name, default)
elif isinstance(default, float):
settings[name] = self._config[section].getfloat(name, default)
else:
settings[name] = self._config[section].get(name, default)
if settings[name] == "None":
settings[name] = None
# sync with the config file
self.saveSettings(section, settings)
return settings
def saveSettings(self, section, settings):
"""
Save all the settings in a given section.
:param section: section name
:param settings: settings to save (dict)
"""
changed = False
if section not in self._config:
self._config[section] = {}
changed = True
for name, value in settings.items():
if name not in self._config[section] or self._config[section][name] != str(value):
self._config[section][name] = str(value)
changed = True
if changed:
self.writeConfig()
def deleteSetting(self, section, name):
"""
Delete a specific setting in a given section.
:param section: section name
:param name: setting name to delete
"""
if section in self._config and name in self._config[section]:
del self._config[section][name]
self.writeConfig()
@staticmethod
def instance():
"""
Singleton to return only on instance of LocalServerConfig.
:returns: instance of Config
"""
if not hasattr(LocalServerConfig, "_instance"):
LocalServerConfig._instance = LocalServerConfig()
return LocalServerConfig._instance

128
gns3/logger.py Normal file
View File

@@ -0,0 +1,128 @@
#!/usr/bin/env python
# -*- 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/>.
"""Provide a pretty logging on console"""
import logging
import sys
import os
class ColouredFormatter(logging.Formatter):
RESET = '\x1B[0m'
RED = '\x1B[31m'
YELLOW = '\x1B[33m'
GREEN = '\x1B[32m'
PINK = '\x1b[35m'
def format(self, record, colour=False):
message = super().format(record)
if not colour or sys.platform.startswith("win"):
return message.replace("#RESET#", "")
level_no = record.levelno
if level_no >= logging.CRITICAL:
colour = self.RED
elif level_no >= logging.ERROR:
colour = self.RED
elif level_no >= logging.WARNING:
colour = self.YELLOW
elif level_no >= logging.INFO:
colour = self.GREEN
elif level_no >= logging.DEBUG:
colour = self.PINK
else:
colour = self.RESET
message = message.replace("#RESET#", self.RESET)
message = '{colour}{message}{reset}'.format(colour=colour, message=message, reset=self.RESET)
return message
class ColouredStreamHandler(logging.StreamHandler):
def format(self, record, colour=False):
if not isinstance(self.formatter, ColouredFormatter):
self.formatter = ColouredFormatter()
return self.formatter.format(record, colour)
def emit(self, record):
stream = self.stream
try:
msg = self.format(record, stream.isatty())
stream.write(msg)
stream.write(self.terminator)
self.flush()
# On OSX when frozen flush raise a BrokenPipeError
except BrokenPipeError:
pass
except Exception:
self.handleError(record)
def init_logger(level, logfile, quiet=False):
if sys.platform.startswith("win"):
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.formatter = ColouredFormatter("{asctime} {levelname} {name}:{lineno} {message}", "%Y-%m-%d %H:%M:%S", "{")
else:
stream_handler = ColouredStreamHandler(sys.stdout)
stream_handler.formatter = ColouredFormatter("{asctime} {levelname} {name}:{lineno}#RESET# {message}", "%Y-%m-%d %H:%M:%S", "{")
logging.basicConfig(level=level, handlers=[stream_handler])
log = logging.getLogger()
log.addHandler(stream_handler)
log_factory = logging.getLogRecordFactory()
def factory(name, level, fn, lno, msg, args, exc_info, func=None, sinfo=None, **kwargs):
"""
Reformat the log message to get something more clean
"""
# When qt message box is display the correct line number is a part of
# the name
if ":" in name:
name, lno = name.split(":")
lno = int(lno)
name = name.replace("gns3.", "")
try:
return log_factory(name, level, fn, lno, msg, args, exc_info, func=func, sinfo=sinfo, **kwargs)
except Exception as e: # To avoid recursion we just print the message if something is wrong when logging
print(msg)
return
logging.setLogRecordFactory(factory)
try:
try:
os.makedirs(os.path.dirname(logfile))
except FileExistsError:
pass
handler = logging.FileHandler(logfile, "w")
handler.formatter = logging.Formatter("{asctime} {levelname} {filename}:{lineno} {message}", "%Y-%m-%d %H:%M:%S", "{")
log.addHandler(handler)
except OSError as e:
log.warning("could not log to {}: {}".format(logfile, e))
log.info('Log level: {}'.format(logging.getLevelName(level)))
return logging.getLogger()

View File

@@ -16,25 +16,46 @@
# 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 datetime
import sys
import os
import faulthandler
# Try to install updates & restart application if an update is installed
try:
import gns3.update_manager
if gns3.update_manager.UpdateManager().installDownloadedUpdates():
print("Update installed restart the application")
python = sys.executable
os.execl(python, *sys.argv)
except Exception as e:
print("Fail update installation: {}".format(str(e)))
import datetime
import traceback
import time
import locale
import argparse
import signal
import psutil
try:
from gns3.qt import QtCore, QtWidgets
except ImportError:
raise SystemExit("Can't import Qt modules: Qt and/or PyQt is probably not installed correctly...")
from gns3.main_window import MainWindow
from gns3.logger import init_logger
from gns3.crash_report import CrashReport
from gns3.local_config import LocalConfig
from gns3.application import Application
from gns3.utils import parse_version
from gns3.dialogs.profile_select import ProfileSelectDialog
from gns3.version import __version__
import logging
log = logging.getLogger(__name__)
try:
from gns3.qt import QtCore, QtGui, DEFAULT_BINDING
except ImportError:
raise RuntimeError("Can't import Qt modules: Qt and/or PyQt is probably not installed correctly...")
from gns3.main_window import MainWindow
from gns3.version import __version__
def locale_check():
"""
@@ -48,8 +69,8 @@ def locale_check():
or there: http://robjwells.com/post/61198832297/get-your-us-ascii-out-of-my-face
"""
# no need to check on Windows
if sys.platform.startswith("win"):
# no need to check on Windows or when frozen
if sys.platform.startswith("win") or hasattr(sys, "frozen"):
return
language = encoding = None
@@ -59,17 +80,18 @@ def locale_check():
log.error("could not determine the current locale: {}".format(e))
if not language and not encoding:
try:
log.warn("could not find a default locale, switching to C.UTF-8...")
log.warning("could not find a default locale, switching to C.UTF-8...")
locale.setlocale(locale.LC_ALL, ("C", "UTF-8"))
except locale.Error as e:
log.error("could not switch to the C.UTF-8 locale: {}".format(e))
raise SystemExit
elif encoding != "UTF-8":
log.warn("your locale {}.{} encoding is not UTF-8, switching to the UTF-8 version...".format(language, encoding))
log.warning("your locale {}.{} encoding is not UTF-8, switching to the UTF-8 version...".format(language, encoding))
try:
locale.setlocale(locale.LC_ALL, (language, "UTF-8"))
except locale.Error as e:
log.error("could not set an UTF-8 encoding for the {} locale: {}".format(language, e))
raise SystemExit
else:
log.info("current locale is {}.{}".format(language, encoding))
@@ -79,10 +101,57 @@ def main():
Entry point for GNS3 GUI.
"""
# Get Python tracebacks explicitly, on a fault like segfault
faulthandler.enable()
# Sometimes (for example at first launch) the OSX app service launcher add
# an extra argument starting with -psn_. We filter it
if sys.platform.startswith("darwin"):
sys.argv = [a for a in sys.argv if not a.startswith("-psn_")]
if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.15.2"):
# Fixes issue on macOS Big Sur: https://github.com/GNS3/gns3-gui/issues/3037
os.environ["QT_MAC_WANTS_LAYER"] = "1"
parser = argparse.ArgumentParser()
parser.add_argument('--version', help="show the version", action='version', version=__version__)
parser.parse_args()
exception_file_path = "exception.log"
parser.add_argument("project", help="load a GNS3 project (.gns3)", metavar="path", nargs="?")
parser.add_argument("--version", help="show the version", action="version", version=__version__)
parser.add_argument("--debug", help="print out debug messages", action="store_true", default=False)
parser.add_argument("-q", "--quiet", action="store_true", help="do not show logs on stdout")
parser.add_argument("--config", help="Configuration file")
parser.add_argument("--profile", help="Settings profile (blank will use default settings files)")
options = parser.parse_args()
exception_file_path = "exceptions.log"
if options.project:
options.project = os.path.abspath(options.project)
try:
import truststore
truststore.inject_into_ssl()
log.info("Using system certificate store for SSL connections")
except ImportError:
pass
if hasattr(sys, "frozen"):
# We add to the path where the OS search executable our binary location starting by GNS3
# packaged binary
frozen_dir = os.path.dirname(os.path.abspath(sys.executable))
if sys.platform.startswith("darwin"):
frozen_dirs = [frozen_dir]
elif sys.platform.startswith("win"):
frozen_dirs = [
frozen_dir,
os.path.normpath(os.path.join(frozen_dir, 'dynamips')),
os.path.normpath(os.path.join(frozen_dir, 'ubridge')),
os.path.normpath(os.path.join(frozen_dir, 'vpcs')),
os.path.normpath(os.path.join(frozen_dir, 'traceng'))
]
os.environ["PATH"] = os.pathsep.join(frozen_dirs) + os.pathsep + os.environ.get("PATH", "")
if options.project:
os.chdir(frozen_dir)
def exceptionHook(exception, value, tb):
@@ -91,93 +160,159 @@ def main():
lines = traceback.format_exception(exception, value, tb)
print("****** Exception detected, traceback information saved in {} ******".format(exception_file_path))
print("\n----> PLEASE REPORT ON http://forum.gns3.net/development-f14.html OR http://github.com/GNS3/gns3-gui/issues\n")
print("\n" . join(lines))
print("\nPLEASE REPORT ON https://www.gns3.com\n")
print("".join(lines))
try:
curdate = time.strftime("%d %b %Y %H:%M:%S")
logfile = open(exception_file_path, "a")
logfile = open(exception_file_path, "a", encoding="utf-8")
logfile.write("=== GNS3 {} traceback on {} ===\n".format(__version__, curdate))
logfile.write("\n" . join(lines))
logfile.write("".join(lines))
logfile.close()
except OSError as e:
print("Could not save traceback to {}: {}".format(exception_file_path, e))
print("Could not save traceback to {}: {}".format(os.path.normpath(exception_file_path), e))
if not sys.stdout.isatty():
# if stdout is not a tty (redirected to the console view),
# then print the exception on stderr too.
print("".join(lines), file=sys.stderr)
if exception is MemoryError:
print("YOUR SYSTEM IS OUT OF MEMORY!")
else:
CrashReport.instance().captureException(exception, value, tb)
# catch exceptions to write them in a file
sys.excepthook = exceptionHook
current_year = datetime.date.today().year
print("GNS3 GUI version {}".format(__version__))
print("Copyright (c) 2007-{} GNS3 Technologies Inc.".format(current_year))
# we only support Python 3 version >= 3.8
if sys.version_info < (3, 8):
raise SystemExit("Python 3.8 or higher is required")
# we only support Python 2 version >= 2.7 and Python 3 version >= 3.3
if sys.version_info < (2, 7):
raise RuntimeError("Python 2.7 or higher is required")
elif sys.version_info[0] == 3 and sys.version_info < (3, 3):
raise RuntimeError("Python 3.3 or higher is required")
if parse_version(QtCore.QT_VERSION_STR) < parse_version("5.5.0"):
raise SystemExit("Requirement is PyQt5 version 5.5.0 or higher, got version {}".format(QtCore.QT_VERSION_STR))
version = lambda version_string: [int(i) for i in version_string.split('.')]
if version(QtCore.QT_VERSION_STR) < version("4.6"):
raise RuntimeError("Requirement is Qt version 4.6 or higher, got version {}".format(QtCore.QT_VERSION_STR))
# 4.8.3 because of QSettings (http://pyqt.sourceforge.net/Docs/PyQt4/pyqt_qsettings.html)
if DEFAULT_BINDING == "PyQt" and version(QtCore.BINDING_VERSION_STR) < version("4.8.3"):
raise RuntimeError("Requirement is PyQt version 4.8.3 or higher, got version {}".format(QtCore.BINDING_VERSION_STR))
if DEFAULT_BINDING == "PySide" and version(QtCore.BINDING_VERSION_STR) < version("1.0"):
raise RuntimeError("Requirement is PySide version 1.0 or higher, got version {}".format(QtCore.BINDING_VERSION_STR))
try:
# if tornado is present then enable pretty logging.
import tornado.log
tornado.log.enable_pretty_logging()
except ImportError:
pass
if parse_version(psutil.__version__) < parse_version("2.2.1"):
raise SystemExit("Requirement is psutil version 2.2.1 or higher, got version {}".format(psutil.__version__))
# check for the correct locale
# (UNIX/Linux only)
locale_check()
# don't use the registry to store settings on Windows
# because we don't like it!
if sys.platform.startswith('win'):
try:
os.getcwd()
except FileNotFoundError:
log.critical("the current working directory doesn't exist")
return
# always use the INI format on Windows and OSX (because we don't like the registry and plist files)
if sys.platform.startswith('win') or sys.platform.startswith('darwin'):
QtCore.QSettings.setDefaultFormat(QtCore.QSettings.IniFormat)
if sys.platform.startswith('win') and hasattr(sys, "frozen"):
try:
import win32console
import win32con
import win32gui
except ImportError:
raise RuntimeError("Python for Windows extensions must be installed.")
raise SystemExit("Python for Windows extensions must be installed.")
try:
win32console.AllocConsole()
#FIXME: do not hide the console for alpha releases to help with debugging
#console_window = win32console.GetConsoleWindow()
#win32gui.ShowWindow(console_window, win32con.SW_HIDE)
except win32console.error as e:
print("warning: could not allocate console: {}".format(e))
if not options.debug:
try:
# hide the console
# win32console.AllocConsole()
console_window = win32console.GetConsoleWindow()
parent_window = win32gui.GetParent(console_window)
if not parent_window and console_window:
win32gui.ShowWindow(console_window, win32con.SW_HIDE)
elif parent_window:
win32gui.ShowWindow(parent_window, win32con.SW_HIDE)
else:
log.warning("Could not get the console window")
except win32console.error as e:
log.warning("Could not allocate console: {}".format(e))
exit_code = MainWindow.exit_code_reboot
while exit_code == MainWindow.exit_code_reboot:
local_config = LocalConfig.instance()
exit_code = 0
app = QtGui.QApplication(sys.argv)
global app
app = Application(sys.argv, hdpi=local_config.hdpi())
# this info is necessary for QSettings
app.setOrganizationName("GNS3")
app.setOrganizationDomain("gns3.net")
app.setApplicationName("GNS3")
app.setApplicationVersion(__version__)
if local_config.multiProfiles() and not options.profile:
profile_select = ProfileSelectDialog()
profile_select.show()
if profile_select.exec_():
options.profile = profile_select.profile()
else:
sys.exit(0)
# update the exception file path to have it in the same directory as the settings file.
exception_file_path = os.path.join(os.path.dirname(QtCore.QSettings().fileName()), exception_file_path)
# Init the config
if options.config:
local_config.setConfigFilePath(options.config)
elif options.profile:
local_config.setProfile(options.profile)
mainwindow = MainWindow.instance()
mainwindow.show()
exit_code = app.exec_()
delattr(MainWindow, "_instance")
app.deleteLater()
# save client logging info to a file
logfile = os.path.join(LocalConfig.instance().configDirectory(), "gns3_gui.log")
# on debug enable logging to stdout
if options.debug:
init_logger(logging.DEBUG, logfile)
elif options.quiet:
init_logger(logging.ERROR, logfile)
else:
init_logger(logging.INFO, logfile)
current_year = datetime.date.today().year
log.info("GNS3 GUI version {}".format(__version__))
log.info("Copyright (c) 2007-{} GNS3 Technologies Inc.".format(current_year))
log.info("Application started with {}".format(" ".join(sys.argv)))
log.debug("PATH={}".format(os.environ["PATH"]))
# update the exception file path to have it in the same directory as the settings file.
exception_file_path = os.path.join(LocalConfig.instance().configDirectory(), exception_file_path)
# We disallow to run GNS3 from outside the /Applications folder to avoid
# issue when people run GNS3 from the .dmg
if sys.platform.startswith("darwin") and hasattr(sys, "frozen"):
if not os.path.realpath(sys.executable).startswith("/Applications"):
error_message = "GNS3.app must be moved to the '/Applications' folder before it can be used"
QtWidgets.QMessageBox.critical(False, "Loading error", error_message)
QtCore.QTimer.singleShot(0, app.quit)
app.exec_()
sys.exit(1)
global mainwindow
startup_file = app.open_file_at_startup
if not startup_file:
startup_file = options.project
mainwindow = MainWindow(open_file=startup_file)
# On OSX we can receive the file to open from a system event
# loadPath is smart and will load only if a path is present
app.file_open_signal.connect(lambda path: mainwindow.loadPath(path))
# Manage Ctrl + C or kill command
def sigint_handler(*args):
log.info("Signal received exiting the application")
app.closeAllWindows()
orig_sigint = signal.signal(signal.SIGINT, sigint_handler)
orig_sigterm = signal.signal(signal.SIGTERM, sigint_handler)
mainwindow.show()
exit_code = app.exec_()
signal.signal(signal.SIGINT, orig_sigint)
signal.signal(signal.SIGTERM, orig_sigterm)
delattr(MainWindow, "_instance")
# We force deleting the app object otherwise it's segfault on Fedora
del app
# We force a full garbage collect before exit
# for unknown reason otherwise Qt Segfault on OSX in some
# conditions
import gc
gc.collect()
sys.exit(exit_code)

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,16 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from gns3.modules.builtin import Builtin
from gns3.modules.dynamips import Dynamips
from gns3.modules.iou import IOU
from gns3.modules.vpcs import VPCS
from gns3.modules.traceng import TraceNG
from gns3.modules.virtualbox import VirtualBox
from gns3.modules.qemu import Qemu
from gns3.modules.vmware import VMware
from gns3.modules.docker import Docker
MODULES = [Dynamips, IOU]
#MODULES = [Builtin, VPCS, Dynamips, IOU, Qemu, VirtualBox, VMware, Docker, TraceNG]
#FIXME: deactivate TraceNG module
MODULES = [Builtin, VPCS, Dynamips, IOU, Qemu, VirtualBox, VMware, Docker]

View File

@@ -0,0 +1,157 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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/>.
"""
Built-in module implementation.
"""
from gns3.qt import QtWidgets
from gns3.local_config import LocalConfig
from gns3.local_server_config import LocalServerConfig
from ..module import Module
from .cloud import Cloud
from .nat import Nat
from .ethernet_hub import EthernetHub
from .ethernet_switch import EthernetSwitch
from .frame_relay_switch import FrameRelaySwitch
from .atm_switch import ATMSwitch
from .settings import BUILTIN_SETTINGS
import logging
log = logging.getLogger(__name__)
class Builtin(Module):
"""
Built-in module.
"""
def __init__(self):
super().__init__()
self._loadSettings()
def _saveSettings(self):
"""
Saves the settings to the persistent settings file.
"""
LocalConfig.instance().saveSectionSettings(self.__class__.__name__, self._settings)
server_settings = {}
config = LocalServerConfig.instance()
if self._settings["default_nat_interface"]:
# save some settings to the local server config file
server_settings["default_nat_interface"] = self._settings["default_nat_interface"]
config.saveSettings(self.__class__.__name__, server_settings)
else:
config.deleteSetting(self.__class__.__name__, "default_nat_interface")
def _loadSettings(self):
"""
Loads the settings from the persistent settings file.
"""
local_config = LocalConfig.instance()
self._settings = local_config.loadSectionSettings(self.__class__.__name__, BUILTIN_SETTINGS)
@staticmethod
def configurationPage(node_type):
"""
Returns the configuration page for this module.
:returns: QWidget object
"""
from .pages.ethernet_hub_configuration_page import EthernetHubConfigurationPage
from .pages.ethernet_switch_configuration_page import EthernetSwitchConfigurationPage
from .pages.cloud_configuration_page import CloudConfigurationPage
if node_type == "ethernet_hub":
return EthernetHubConfigurationPage
elif node_type == "ethernet_switch":
return EthernetSwitchConfigurationPage
elif node_type == "cloud":
return CloudConfigurationPage
return None
@staticmethod
def getNodeClass(node_type, platform=None):
"""
Returns the class corresponding to node type.
:param node_type: node type (string)
:param platform: not used
:returns: class or None
"""
if node_type == "cloud":
return Cloud
elif node_type == "nat":
return Nat
elif node_type == "ethernet_hub":
return EthernetHub
elif node_type == "ethernet_switch":
return EthernetSwitch
elif node_type == "frame_relay_switch":
return FrameRelaySwitch
elif node_type == "atm_switch":
return ATMSwitch
return None
@staticmethod
def classes():
"""
Returns all the node classes supported by this module.
:returns: list of classes
"""
return [Nat, Cloud, EthernetHub, EthernetSwitch, FrameRelaySwitch, ATMSwitch]
@staticmethod
def preferencePages():
"""
:returns: QWidget object list
"""
from .pages.builtin_preferences_page import BuiltinPreferencesPage
from .pages.cloud_preferences_page import CloudPreferencesPage
from .pages.ethernet_hub_preferences_page import EthernetHubPreferencesPage
from .pages.ethernet_switch_preferences_page import EthernetSwitchPreferencesPage
return [BuiltinPreferencesPage, EthernetHubPreferencesPage, EthernetSwitchPreferencesPage, CloudPreferencesPage]
@staticmethod
def instance():
"""
Singleton to return only on instance of built-in module.
:returns: instance of Builtin
"""
if not hasattr(Builtin, "_instance"):
Builtin._instance = Builtin()
return Builtin._instance
def __str__(self):
"""
Returns the module name.
"""
return "builtin"

View File

@@ -0,0 +1,145 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 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 re
from gns3.node import Node
import logging
log = logging.getLogger(__name__)
class ATMSwitch(Node):
"""
ATM switch.
:param module: parent module for this node
:param server: GNS3 server instance
:param project: Project instance
"""
URL_PREFIX = "atm_switch"
def __init__(self, module, server, project):
super().__init__(module, server, project)
# this is an always-on node
self.setStatus(Node.started)
self._always_on = True
self.settings().update({"mappings": {}})
def info(self):
"""
Returns information about this ATM switch.
:returns: formatted string
"""
info = """ATM switch {name} is always-on
Running on server {host} with port {port}
Local ID is {id} and server ID is {node_id}
Hardware is Dynamips emulated simple ATM switch
""".format(name=self.name(),
id=self.id(),
node_id=self._node_id,
host=self._compute.name(),
port=self._compute.port())
port_info = ""
mapping = re.compile(r"""^([0-9]*):([0-9]*):([0-9]*)$""")
for port in self._ports:
if port.isFree():
port_info += " Port {} is empty\n".format(port.name())
else:
port_info += " Port {name} {description}\n".format(name=port.name(),
description=port.description())
for source, destination in self._settings["mappings"].items():
match_source_mapping = mapping.search(source)
match_destination_mapping = mapping.search(destination)
if match_source_mapping and match_destination_mapping:
source_port, source_vpi, source_vci = match_source_mapping.group(1, 2, 3)
destination_port, destination_vpi, destination_vci = match_destination_mapping.group(1, 2, 3)
else:
source_port, source_vpi = source.split(":")
destination_port, destination_vpi = destination.split(":")
source_vci = destination_vci = 0
if port.name() == source_port or port.name() == destination_port:
if port.name() == source_port:
vpi1 = source_vpi
vci1 = source_vci
port = destination_port
vci2 = destination_vci
vpi2 = destination_vpi
else:
vpi1 = destination_vpi
vci1 = destination_vci
port = source_port
vci2 = source_vci
vpi2 = source_vpi
if vci1 and vci2:
port_info += " incoming VPI {vpi1} and VCI {vci1} is switched to port {port} outgoing VPI {vpi2} and VCI {vci2}\n".format(vpi1=vpi1,
vci1=vci1,
port=port,
vpi2=vpi2,
vci2=vci2)
else:
port_info += " incoming VPI {vpi1} is switched to port {port} outgoing VPI {vpi2}\n".format(vpi1=vpi1,
port=port,
vpi2=vpi2)
break
return info + port_info
def configPage(self):
"""
Returns the configuration page widget to be used by the node properties dialog.
:returns: QWidget object
"""
from .pages.atm_switch_configuration_page import ATMSwitchConfigurationPage
return ATMSwitchConfigurationPage
@staticmethod
def defaultSymbol():
"""
Returns the default symbol path for this node.
:returns: symbol path (or resource).
"""
return ":/symbols/atm_switch.svg"
@staticmethod
def categories():
"""
Returns the node categories the node is part of (used by the device panel).
:returns: list of node categories
"""
return [Node.switches]
def __str__(self):
return "ATM switch"

View File

@@ -0,0 +1,176 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016 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/>.
from gns3.node import Node
from .settings import CLOUD_SETTINGS
import logging
log = logging.getLogger(__name__)
class Cloud(Node):
"""
Cloud node
:param module: parent module for this node
:param server: GNS3 server instance
:param project: Project instance
"""
URL_PREFIX = "cloud"
def __init__(self, module, server, project):
super().__init__(module, server, project)
# this is an always-on node
self.setStatus(Node.started)
self._always_on = True
self._interfaces = {}
self._cloud_settings = {"ports_mapping": [],
"remote_console_host": CLOUD_SETTINGS["remote_console_host"],
"remote_console_port": CLOUD_SETTINGS["remote_console_port"],
"remote_console_type": CLOUD_SETTINGS["remote_console_type"],
"remote_console_http_path": CLOUD_SETTINGS["remote_console_http_path"]
}
self.settings().update(self._cloud_settings)
def interfaces(self):
return self._interfaces
def _createCallback(self, result):
"""
Callback for create.
:param result: server response
"""
if "interfaces" in result:
self._interfaces = result["interfaces"].copy()
def _updateCallback(self, result):
"""
Callback for update.
:param result: server response
"""
if "interfaces" in result:
self._interfaces = result["interfaces"].copy()
def consoleType(self):
"""
Get the console type.
"""
return self.settings()["remote_console_type"]
def consoleHost(self):
"""
Returns the host to connect to the console.
:returns: host (string)
"""
return self.settings()["remote_console_host"]
def console(self):
"""
Returns the console port number of this node
:returns: port number
"""
return self.settings()["remote_console_port"]
def consoleHttpPath(self):
"""
Returns the path of the web ui
:returns: string
"""
return self._settings["remote_console_http_path"]
def info(self):
"""
Returns information about this cloud.
:returns: formatted string
"""
info = """Cloud {name} is always-on
Running on server {host} with port {port}
""".format(name=self.name(),
host=self.compute().name(),
port=self.compute().port())
if self.consoleType() != "none":
info += """ Remote console is {console_host} on port {console} and type is {console_type}
""".format(console_host=self.consoleHost(),
console=self.console(),
console_type=self.consoleType())
if self.consoleType() in ("http", "https"):
info += """ Remote console HTTP path is '{console_http_path}'
""".format(console_http_path=self.consoleHttpPath())
else:
info += """ No remote console configured
"""
port_info = ""
for port in self._ports:
if port.isFree():
port_info += " Port {} is empty\n".format(port.name())
else:
port_info += " Port {name} {description}\n".format(name=port.name(),
description=port.description())
return info + port_info
def configPage(self):
"""
Returns the configuration page widget to be used by the node properties dialog.
:returns: QWidget object
"""
from .pages.cloud_configuration_page import CloudConfigurationPage
return CloudConfigurationPage
@staticmethod
def defaultSymbol():
"""
Returns the default symbol path for this cloud.
:returns: symbol path (or resource).
"""
return ":/symbols/cloud.svg"
@staticmethod
def categories():
"""
Returns the node categories the node is part of (used by the device panel).
:returns: list of node categories
"""
return [Node.end_devices]
def __str__(self):
return "Cloud"

Some files were not shown because too many files have changed in this diff Show More