Auto upload missing images

This commit is contained in:
Julien Duponchelle committed 2016-06-07 19:38:01 +02:00
1 parent 972cbd0594
commit 08e482004f
15 files changed
+194 -65

No files matched your search

+25 -6
View File
@@ -19,6 +19,7 @@ import aiohttp
import asyncio
import json
import uuid
import io
from ..utils import parse_version
from ..controller.controller_error import ControllerError
@@ -34,6 +35,17 @@ class ComputeError(ControllerError):
pass
class ComputeConflict(aiohttp.web.HTTPConflict):
"""
Raise when the compute send a 409 that we can handle
:param response: The response of the compute
"""
def __init__(self, response):
super().__init__(text=response["message"])
self.response = response
class Timeout(aiohttp.Timeout):
"""
Could be removed with aiohttp 0.22 that support None timeout
@@ -293,7 +305,7 @@ class Compute:
if hasattr(data, '__json__'):
data = json.dumps(data.__json__())
# Stream the request
elif isinstance(data, aiohttp.streams.StreamReader):
elif isinstance(data, aiohttp.streams.StreamReader) or isinstance(data, io.BufferedIOBase):
chunked = True
headers['content-type'] = 'application/octet-stream'
else:
@@ -306,10 +318,13 @@ class Compute:
if response.status >= 300:
# Try to decode the GNS3 error
try:
msg = json.loads(body)["message"]
except (KeyError, json.decoder.JSONDecodeError):
msg = body
if body:
try:
msg = json.loads(body)["message"]
except (KeyError, json.decoder.JSONDecodeError):
msg = body
else:
msg = ""
if response.status == 400:
raise aiohttp.web.HTTPBadRequest(text="Bad request {} {}".format(url, body))
@@ -320,7 +335,11 @@ class Compute:
elif response.status == 404:
raise aiohttp.web.HTTPNotFound(text=msg)
elif response.status == 409:
raise aiohttp.web.HTTPConflict(text=msg)
try:
raise ComputeConflict(json.loads(body))
# If the 409 doesn't come from a GNS3 server
except json.decoder.JSONDecodeError:
raise aiohttp.web.HTTPConflict(text=msg)
elif response.status == 500:
raise aiohttp.web.HTTPInternalServerError(text="Internal server error {}".format(url))
elif response.status == 503:
+34 -3
View File
@@ -15,12 +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/>.
import aiohttp
import asyncio
import copy
import uuid
import os
from .compute import ComputeConflict
from ..utils.images import images_directories
class Node:
def __init__(self, project, compute, node_id=None, node_type=None, name=None, console=None, console_type=None, properties={}):
@@ -101,8 +105,19 @@ class Node:
"""
data = self._node_data()
data["node_id"] = self._id
response = yield from self._compute.post("/projects/{}/{}/nodes".format(self._project.id, self._node_type), data=data)
self.parse_node_response(response.json)
trial = 0
while trial != 6:
try:
response = yield from self._compute.post("/projects/{}/{}/nodes".format(self._project.id, self._node_type), data=data)
except ComputeConflict as e:
if e.response.get("exception") == "ImageMissingError":
res = yield from self._upload_missing_image(self._node_type, e.response["image"])
if not res:
raise e
else:
self.parse_node_response(response.json)
return True
trial += 1
@asyncio.coroutine
def update(self, name=None, console=None, console_type=None, properties={}):
@@ -236,6 +251,22 @@ class Node:
else:
return (yield from self._compute.delete("/projects/{}/{}/nodes/{}{}".format(self._project.id, self._node_type, self._id, path)))
@asyncio.coroutine
def _upload_missing_image(self, type, img):
"""
Search an image on local computer and upload it to remote compute
if the image exists
"""
for directory in images_directories(type):
image = os.path.join(directory, img)
if os.path.exists(image):
self.project.controller.notification.emit("log.info", {"message": "Uploading missing image {}".format(img)})
with open(image, 'rb') as f:
yield from self._compute.post("/{}/images/{}".format(self._node_type, os.path.basename(img)), data=f, timeout=None)
self.project.controller.notification.emit("log.info", {"message": "Upload finished for {}".format(img)})
return True
return False
@asyncio.coroutine
def dynamips_auto_idlepc(self):
"""