mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-28 11:18:11 +00:00
Merge pull request #104 from GNS3/dynamips_hypervisor_lock
Asyncio lock for Dynamips hypervisor.
This commit is contained in:
commit
5b08677537
@ -59,6 +59,8 @@ class DynamipsHypervisor:
|
|||||||
self._reader = None
|
self._reader = None
|
||||||
self._writer = None
|
self._writer = None
|
||||||
|
|
||||||
|
self._io_lock = asyncio.Lock()
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def connect(self, timeout=10):
|
def connect(self, timeout=10):
|
||||||
"""
|
"""
|
||||||
@ -80,7 +82,8 @@ class DynamipsHypervisor:
|
|||||||
while time.time() - begin < timeout:
|
while time.time() - begin < timeout:
|
||||||
yield from asyncio.sleep(0.01)
|
yield from asyncio.sleep(0.01)
|
||||||
try:
|
try:
|
||||||
self._reader, self._writer = yield from asyncio.open_connection(host, self._port)
|
with (yield from self._io_lock):
|
||||||
|
self._reader, self._writer = yield from asyncio.open_connection(host, self._port)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
last_exception = e
|
last_exception = e
|
||||||
continue
|
continue
|
||||||
@ -120,8 +123,9 @@ class DynamipsHypervisor:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
yield from self.send("hypervisor close")
|
yield from self.send("hypervisor close")
|
||||||
self._writer.close()
|
with (yield from self._io_lock):
|
||||||
self._reader, self._writer = None
|
self._writer.close()
|
||||||
|
self._reader, self._writer = None
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def stop(self):
|
def stop(self):
|
||||||
@ -129,17 +133,18 @@ class DynamipsHypervisor:
|
|||||||
Stops this hypervisor (will no longer run).
|
Stops this hypervisor (will no longer run).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
with (yield from self._io_lock):
|
||||||
# try to properly stop the hypervisor
|
try:
|
||||||
yield from self.send("hypervisor stop")
|
# try to properly stop the hypervisor
|
||||||
except DynamipsError:
|
yield from self.send("hypervisor stop")
|
||||||
pass
|
except DynamipsError:
|
||||||
try:
|
pass
|
||||||
yield from self._writer.drain()
|
try:
|
||||||
self._writer.close()
|
yield from self._writer.drain()
|
||||||
except OSError as e:
|
self._writer.close()
|
||||||
log.debug("Stopping hypervisor {}:{} {}".format(self._host, self._port, e))
|
except OSError as e:
|
||||||
self._reader = self._writer = None
|
log.debug("Stopping hypervisor {}:{} {}".format(self._host, self._port, e))
|
||||||
|
self._reader = self._writer = None
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def reset(self):
|
def reset(self):
|
||||||
@ -255,59 +260,60 @@ class DynamipsHypervisor:
|
|||||||
# but still have more data. The only thing we know for sure is the last line
|
# but still have more data. The only thing we know for sure is the last line
|
||||||
# will begin with '100-' or a '2xx-' and end with '\r\n'
|
# will begin with '100-' or a '2xx-' and end with '\r\n'
|
||||||
|
|
||||||
if self._writer is None or self._reader is None:
|
with (yield from self._io_lock):
|
||||||
raise DynamipsError("Not connected")
|
if self._writer is None or self._reader is None:
|
||||||
|
raise DynamipsError("Not connected")
|
||||||
|
|
||||||
try:
|
|
||||||
command = command.strip() + '\n'
|
|
||||||
log.debug("sending {}".format(command))
|
|
||||||
self._writer.write(command.encode())
|
|
||||||
except OSError as e:
|
|
||||||
raise DynamipsError("Lost communication with {host}:{port} :{error}, Dynamips process running: {run}"
|
|
||||||
.format(host=self._host, port=self._port, error=e, run=self.is_running()))
|
|
||||||
|
|
||||||
# Now retrieve the result
|
|
||||||
data = []
|
|
||||||
buf = ''
|
|
||||||
while True:
|
|
||||||
try:
|
try:
|
||||||
chunk = yield from self._reader.read(1024) # match to Dynamips' buffer size
|
command = command.strip() + '\n'
|
||||||
if not chunk:
|
log.debug("sending {}".format(command))
|
||||||
raise DynamipsError("No data returned from {host}:{port}, Dynamips process running: {run}"
|
self._writer.write(command.encode())
|
||||||
.format(host=self._host, port=self._port, run=self.is_running()))
|
|
||||||
buf += chunk.decode()
|
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise DynamipsError("Communication timed out with {host}:{port} :{error}, Dynamips process running: {run}"
|
raise DynamipsError("Lost communication with {host}:{port} :{error}, Dynamips process running: {run}"
|
||||||
.format(host=self._host, port=self._port, error=e, run=self.is_running()))
|
.format(host=self._host, port=self._port, error=e, run=self.is_running()))
|
||||||
|
|
||||||
# If the buffer doesn't end in '\n' then we can't be done
|
# Now retrieve the result
|
||||||
try:
|
data = []
|
||||||
if buf[-1] != '\n':
|
|
||||||
continue
|
|
||||||
except IndexError:
|
|
||||||
raise DynamipsError("Could not communicate with {host}:{port}, Dynamips process running: {run}"
|
|
||||||
.format(host=self._host, port=self._port, run=self.is_running()))
|
|
||||||
|
|
||||||
data += buf.split('\r\n')
|
|
||||||
if data[-1] == '':
|
|
||||||
data.pop()
|
|
||||||
buf = ''
|
buf = ''
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
chunk = yield from self._reader.read(1024) # match to Dynamips' buffer size
|
||||||
|
if not chunk:
|
||||||
|
raise DynamipsError("No data returned from {host}:{port}, Dynamips process running: {run}"
|
||||||
|
.format(host=self._host, port=self._port, run=self.is_running()))
|
||||||
|
buf += chunk.decode()
|
||||||
|
except OSError as e:
|
||||||
|
raise DynamipsError("Communication timed out with {host}:{port} :{error}, Dynamips process running: {run}"
|
||||||
|
.format(host=self._host, port=self._port, error=e, run=self.is_running()))
|
||||||
|
|
||||||
# Does it contain an error code?
|
# If the buffer doesn't end in '\n' then we can't be done
|
||||||
if self.error_re.search(data[-1]):
|
try:
|
||||||
raise DynamipsError(data[-1][4:])
|
if buf[-1] != '\n':
|
||||||
|
continue
|
||||||
|
except IndexError:
|
||||||
|
raise DynamipsError("Could not communicate with {host}:{port}, Dynamips process running: {run}"
|
||||||
|
.format(host=self._host, port=self._port, run=self.is_running()))
|
||||||
|
|
||||||
# Or does the last line begin with '100-'? Then we are done!
|
data += buf.split('\r\n')
|
||||||
if data[-1][:4] == '100-':
|
if data[-1] == '':
|
||||||
data[-1] = data[-1][4:]
|
|
||||||
if data[-1] == 'OK':
|
|
||||||
data.pop()
|
data.pop()
|
||||||
break
|
buf = ''
|
||||||
|
|
||||||
# Remove success responses codes
|
# Does it contain an error code?
|
||||||
for index in range(len(data)):
|
if self.error_re.search(data[-1]):
|
||||||
if self.success_re.search(data[index]):
|
raise DynamipsError(data[-1][4:])
|
||||||
data[index] = data[index][4:]
|
|
||||||
|
|
||||||
log.debug("returned result {}".format(data))
|
# Or does the last line begin with '100-'? Then we are done!
|
||||||
return data
|
if data[-1][:4] == '100-':
|
||||||
|
data[-1] = data[-1][4:]
|
||||||
|
if data[-1] == 'OK':
|
||||||
|
data.pop()
|
||||||
|
break
|
||||||
|
|
||||||
|
# Remove success responses codes
|
||||||
|
for index in range(len(data)):
|
||||||
|
if self.success_re.search(data[index]):
|
||||||
|
data[index] = data[index][4:]
|
||||||
|
|
||||||
|
log.debug("returned result {}".format(data))
|
||||||
|
return data
|
||||||
|
Loading…
Reference in New Issue
Block a user