Merge branch 'master' into 1.5

This commit is contained in:
Julien Duponchelle 2016-01-20 17:10:10 +01:00
commit c280fd5fb8
12 changed files with 48 additions and 16 deletions

3
.gitignore vendored
View File

@ -1,5 +1,8 @@
*.py[cod] *.py[cod]
#py.test
.cache
# C extensions # C extensions
*.so *.so

View File

@ -9,8 +9,5 @@ install:
- pip install coveralls - pip install coveralls
script: script:
- py.test -v -s tests --cov gns3server --cov-report term-missing - py.test -v -s tests --cov gns3server --cov-report term-missing
notifications:
slack:
secure: gsbGgtNbJ0ElyPawA9DNunVgVD4SHmB/vDeQBMnmnw3g8Z01iNiiFLaaiUo/Vr65Yd0KMujw7ocC5aiSsgPWF3dEC57ntogWcMF2tf9YlbHdY+90HlIs7k7/xf3vRdrE+rNy24svvU7zaxYCL9gO70PQqIT6nI2Dgy4qQFiwr2s=
after_success: after_success:
- coveralls - coveralls

View File

@ -1,5 +1,8 @@
# Change Log # Change Log
## 1.4.0 12/01/2016
* Release 1.4.0
## 1.4.0rc3 05/01/2016 ## 1.4.0rc3 05/01/2016
* API documentation update * API documentation update

View File

@ -3,6 +3,6 @@
sphinx==1.2.3 sphinx==1.2.3
pytest==2.8.2 pytest==2.8.2
pep8==1.5.7 pep8==1.5.7
pytest-timeout pytest-capturelog==0.7
pytest-capturelog pytest-cov==2.2.0
pytest-cov pytest-timeout==0.5

View File

@ -602,6 +602,10 @@ class Dynamips(BaseManager):
elif startup_config_content: elif startup_config_content:
startup_config_path = self._create_config(vm, default_startup_config_path, startup_config_content) startup_config_path = self._create_config(vm, default_startup_config_path, startup_config_content)
yield from vm.set_configs(startup_config_path) yield from vm.set_configs(startup_config_path)
# An empty startup config crash dynamips
else:
startup_config_path = self._create_config(vm, default_startup_config_path, "!\n")
yield from vm.set_configs(startup_config_path)
private_config_path = settings.get("private_config") private_config_path = settings.get("private_config")
private_config_content = settings.get("private_config_content") private_config_content = settings.get("private_config_content")

View File

@ -281,6 +281,7 @@ class Router(BaseVM):
yield from self._hypervisor.send('vm stop "{name}"'.format(name=self._name)) yield from self._hypervisor.send('vm stop "{name}"'.format(name=self._name))
self.status = "stopped" self.status = "stopped"
log.info('Router "{name}" [{id}] has been stopped'.format(name=self._name, id=self._id)) log.info('Router "{name}" [{id}] has been stopped'.format(name=self._name, id=self._id))
yield from self.save_configs()
@asyncio.coroutine @asyncio.coroutine
def reload(self): def reload(self):
@ -352,7 +353,6 @@ class Router(BaseVM):
if self._hypervisor and not self._hypervisor.devices: if self._hypervisor and not self._hypervisor.devices:
try: try:
yield from self.stop() yield from self.stop()
yield from self.save_configs()
yield from self._hypervisor.send('vm delete "{}"'.format(self._name)) yield from self._hypervisor.send('vm delete "{}"'.format(self._name))
except DynamipsError: except DynamipsError:
pass pass

View File

@ -400,7 +400,7 @@ class IOUVM(BaseVM):
raise IOUError("License section not found in iourc file {}".format(self.iourc_path)) raise IOUError("License section not found in iourc file {}".format(self.iourc_path))
hostname = socket.gethostname() hostname = socket.gethostname()
if hostname not in config["license"]: if hostname not in config["license"]:
raise IOUError("Hostname key not found in iourc file {}".format(self.iourc_path)) raise IOUError("Hostname \"{}\" not found in iourc file {}".format(hostname, self.iourc_path))
user_ioukey = config["license"][hostname] user_ioukey = config["license"][hostname]
if user_ioukey[-1:] != ';': if user_ioukey[-1:] != ';':
raise IOUError("IOU key not ending with ; in iourc file".format(self.iourc_path)) raise IOUError("IOU key not ending with ; in iourc file".format(self.iourc_path))

View File

@ -157,6 +157,10 @@ class QemuVM(BaseVM):
else: else:
qemu_bin = os.path.basename(qemu_path) qemu_bin = os.path.basename(qemu_path)
qemu_bin = re.sub(r'(w)?\.(exe|EXE)$', '', qemu_bin) qemu_bin = re.sub(r'(w)?\.(exe|EXE)$', '', qemu_bin)
# Old version of GNS3 provide a binary named qemu.exe
if qemu_bin == "qemu":
self._platform = "i386"
else:
self._platform = re.sub(r'^qemu-system-(.*)$', r'\1', qemu_bin, re.IGNORECASE) self._platform = re.sub(r'^qemu-system-(.*)$', r'\1', qemu_bin, re.IGNORECASE)
if self._platform.split(".")[0] not in QEMU_PLATFORMS: if self._platform.split(".")[0] not in QEMU_PLATFORMS:
raise QemuError("Platform {} is unknown".format(self._platform)) raise QemuError("Platform {} is unknown".format(self._platform))

View File

@ -540,7 +540,13 @@ class VMware(BaseManager):
""" """
if sys.platform.startswith("win"): if sys.platform.startswith("win"):
return os.path.expandvars(r"%USERPROFILE%\Documents\Virtual Machines") from win32com.shell import shell, shellcon
documents_folder = shell.SHGetSpecialFolderPath(None, shellcon.CSIDL_PERSONAL)
windows_type = sys.getwindowsversion().product_type
if windows_type == 2 or windows_type == 3:
return '{}\My Virtual Machines'.format(documents_folder)
else:
return '{}\Virtual Machines'.format(documents_folder)
elif sys.platform.startswith("darwin"): elif sys.platform.startswith("darwin"):
return os.path.expanduser("~/Documents/Virtual Machines.localized") return os.path.expanduser("~/Documents/Virtual Machines.localized")
else: else:

View File

@ -296,7 +296,7 @@ QEMU_UPDATE_SCHEMA = {
}, },
"boot_priority": { "boot_priority": {
"description": "QEMU boot priority", "description": "QEMU boot priority",
"enum": ["c", "d"] "enum": ["c", "d", "n", "cn", "cd"]
}, },
"ram": { "ram": {
"description": "amount of RAM in MB", "description": "amount of RAM in MB",
@ -468,7 +468,7 @@ QEMU_OBJECT_SCHEMA = {
}, },
"boot_priority": { "boot_priority": {
"description": "QEMU boot priority", "description": "QEMU boot priority",
"enum": ["c", "d"] "enum": ["c", "d", "n", "cn", "cd"]
}, },
"vm_directory": { "vm_directory": {
"decription": "Path to the VM working directory", "decription": "Path to the VM working directory",

View File

@ -226,6 +226,9 @@ class Server:
# Asyncio will raise error if coroutine is not called # Asyncio will raise error if coroutine is not called
self._loop.set_debug(True) self._loop.set_debug(True)
for key, val in os.environ.items():
log.debug("ENV %s=%s", key, val)
app = aiohttp.web.Application() app = aiohttp.web.Application()
for method, route, handler in Route.get_routes(): for method, route, handler in Route.get_routes():
log.debug("Adding route: {} {}".format(method, route)) log.debug("Adding route: {} {}".format(method, route))

View File

@ -258,6 +258,18 @@ def test_set_qemu_path_windows(vm, tmpdir):
assert vm.platform == "x86_64" assert vm.platform == "x86_64"
def test_set_qemu_path_old_windows(vm, tmpdir):
bin_path = os.path.join(os.environ["PATH"], "qemu.exe")
open(bin_path, "w+").close()
os.chmod(bin_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
vm.qemu_path = bin_path
assert vm.qemu_path == bin_path
assert vm.platform == "i386"
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows") @pytest.mark.skipif(sys.platform.startswith("win"), reason="Not supported on Windows")
def test_set_qemu_path_kvm_binary(vm, tmpdir, fake_qemu_binary): def test_set_qemu_path_kvm_binary(vm, tmpdir, fake_qemu_binary):