Strip the old / import export project code controller will do everything

pull/638/head
Julien Duponchelle 8 years ago
parent 3300e9ec48
commit 88ffd43c97
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8

@ -399,181 +399,3 @@ class Project:
break
m.update(buf)
return m.hexdigest()
def export(self, include_images=False):
"""
Export the project as zip. It's a ZipStream object.
The file will be read chunk by chunk when you iterate on
the zip.
It will ignore some files like snapshots and tmp
:returns: ZipStream object
"""
z = zipstream.ZipFile()
# topdown allows to modify the list of directory in order to ignore the directory
for root, dirs, files in os.walk(self._path, topdown=True):
# Remove snapshots and capture
if os.path.split(root)[-1:][0] == "project-files":
dirs[:] = [d for d in dirs if d not in ("snapshots", "tmp")]
# Ignore log files and OS noise
files = [f for f in files if not f.endswith('_log.txt') and not f.endswith('.log') and f != '.DS_Store']
for file in files:
path = os.path.join(root, file)
# Try open the file
try:
open(path).close()
except OSError as e:
msg = "Could not export file {}: {}".format(path, e)
log.warn(msg)
self.emit("log.warning", {"message": msg})
continue
# We rename the .gns3 project.gns3 to avoid the task to the client to guess the file name
if file.endswith(".gns3"):
self._export_project_file(path, z, include_images)
else:
# We merge the data from all server in the same project-files directory
node_directory = os.path.join(self._path, "servers", "vm")
if os.path.commonprefix([root, node_directory]) == node_directory:
z.write(path, os.path.relpath(path, node_directory), compress_type=zipfile.ZIP_DEFLATED)
else:
z.write(path, os.path.relpath(path, self._path), compress_type=zipfile.ZIP_DEFLATED)
return z
def _export_images(self, image, z):
"""
Take a project file (.gns3) and export images to the zip
:param image: Image path
:param z: Zipfile instance for the export
"""
from . import MODULES
for module in MODULES:
try:
img_directory = module.instance().get_images_directory()
except NotImplementedError:
# Some modules don't have images
continue
directory = os.path.split(img_directory)[-1:][0]
if os.path.exists(image):
path = image
else:
path = os.path.join(img_directory, image)
if os.path.exists(path):
arcname = os.path.join("images", directory, os.path.basename(image))
z.write(path, arcname)
break
def _export_project_file(self, path, z, include_images):
"""
Take a project file (.gns3) and patch it for the export
:param path: Path of the .gns3
"""
with open(path) as f:
topology = json.load(f)
if "topology" in topology and "nodes" in topology["topology"]:
for node in topology["topology"]["nodes"]:
if "properties" in node and node["type"] != "DockerVM":
for prop, value in node["properties"].items():
if prop.endswith("image"):
node["properties"][prop] = os.path.basename(value)
if include_images is True:
self._export_images(value, z)
z.writestr("project.gns3", json.dumps(topology).encode())
def import_zip(self, stream, gns3vm=True):
"""
Import a project contain in a zip file
:param stream: A io.BytesIO of the zipfile
:param gns3vm: True move Docker, IOU and Qemu to the GNS3 VM
"""
with zipfile.ZipFile(stream) as myzip:
myzip.extractall(self.path)
project_file = os.path.join(self.path, "project.gns3")
if os.path.exists(project_file):
with open(project_file) as f:
topology = json.load(f)
topology["project_id"] = self.id
topology["name"] = self.name
topology.setdefault("topology", {})
topology["topology"].setdefault("nodes", [])
topology["topology"]["servers"] = [
{
"id": 1,
"local": True,
"vm": False
}
]
# By default all node run on local server
for node in topology["topology"]["nodes"]:
node["server_id"] = 1
if gns3vm:
# Move to servers/vm directory the data that should be import on remote server
modules_to_vm = {
"qemu": "QemuVM",
"iou": "IOUDevice",
"docker": "DockerVM"
}
node_directory = os.path.join(self.path, "servers", "vm", "project-files")
vm_server_use = False
for module, vm_type in modules_to_vm.items():
module_directory = os.path.join(self.path, "project-files", module)
if os.path.exists(module_directory):
os.makedirs(node_directory, exist_ok=True)
shutil.move(module_directory, os.path.join(node_directory, module))
# Patch node to use the GNS3 VM
for node in topology["topology"]["nodes"]:
if node["type"] == vm_type:
node["server_id"] = 2
vm_server_use = True
# We use the GNS3 VM. We need to add the server to the list
if vm_server_use:
topology["topology"]["servers"].append({
"id": 2,
"vm": True,
"local": False
})
# Write the modified topology
with open(project_file, "w") as f:
json.dump(topology, f, indent=4)
# Rename to a human distinctive name
shutil.move(project_file, os.path.join(self.path, self.name + ".gns3"))
if os.path.exists(os.path.join(self.path, "images")):
self._import_images()
def _import_images(self):
"""
Copy images to the images directory or delete them if they
already exists.
"""
image_dir = self._config().get("images_path")
root = os.path.join(self.path, "images")
for (dirpath, dirnames, filenames) in os.walk(root):
for filename in filenames:
path = os.path.join(dirpath, filename)
dst = os.path.join(image_dir, os.path.relpath(path, root))
os.makedirs(os.path.dirname(dst), exist_ok=True)
shutil.move(path, dst)
# Cleanup the project
shutil.rmtree(root, ignore_errors=True)

@ -22,7 +22,6 @@ import zipfile
import zipstream
def export_project(project, include_images=False):
"""
Export the project as zip. It's a ZipStream object.
@ -128,5 +127,3 @@ def _export_images(project, image, z):
arcname = os.path.join("images", directory, os.path.basename(image))
z.write(path, arcname)
break

@ -175,155 +175,3 @@ def test_emit(async_run):
(action, event, context) = async_run(queue.get(0.5))
assert action == "test"
assert context["project_id"] == project.id
def test_export(tmpdir):
project = Project(project_id=str(uuid.uuid4()))
path = project.path
os.makedirs(os.path.join(path, "vm-1", "dynamips"))
with open(os.path.join(path, "vm-1", "dynamips", "test"), 'w+') as f:
f.write("HELLO")
with open(os.path.join(path, "vm-1", "dynamips", "test_log.txt"), 'w+') as f:
f.write("LOG")
os.makedirs(os.path.join(path, "project-files", "snapshots"))
with open(os.path.join(path, "project-files", "snapshots", "test"), 'w+') as f:
f.write("WORLD")
z = project.export()
with open(str(tmpdir / 'zipfile.zip'), 'wb') as f:
for data in z:
f.write(data)
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
with myzip.open("vm-1/dynamips/test") as myfile:
content = myfile.read()
assert content == b"HELLO"
assert 'project-files/snapshots/test' not in myzip.namelist()
assert 'vm-1/dynamips/test_log.txt' not in myzip.namelist()
def test_export_with_vm(tmpdir):
project_id = str(uuid.uuid4())
project = Project(project_id=project_id)
path = project.path
os.makedirs(os.path.join(path, "vm-1", "dynamips"))
# The .gns3 should be renamed project.gns3 in order to simplify import
with open(os.path.join(path, "test.gns3"), 'w+') as f:
f.write("{}")
with open(os.path.join(path, "vm-1", "dynamips", "test"), 'w+') as f:
f.write("HELLO")
with open(os.path.join(path, "vm-1", "dynamips", "test_log.txt"), 'w+') as f:
f.write("LOG")
os.makedirs(os.path.join(path, "project-files", "snapshots"))
with open(os.path.join(path, "project-files", "snapshots", "test"), 'w+') as f:
f.write("WORLD")
os.makedirs(os.path.join(path, "servers", "vm", "project-files", "docker"))
with open(os.path.join(path, "servers", "vm", "project-files", "docker", "busybox"), 'w+') as f:
f.write("DOCKER")
z = project.export()
with open(str(tmpdir / 'zipfile.zip'), 'wb') as f:
for data in z:
f.write(data)
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
with myzip.open("vm-1/dynamips/test") as myfile:
content = myfile.read()
assert content == b"HELLO"
assert 'test.gns3' not in myzip.namelist()
assert 'project.gns3' in myzip.namelist()
assert 'project-files/snapshots/test' not in myzip.namelist()
assert 'vm-1/dynamips/test_log.txt' not in myzip.namelist()
assert 'servers/vm/project-files/docker/busybox' not in myzip.namelist()
assert 'project-files/docker/busybox' in myzip.namelist()
def test_import(tmpdir):
project_id = str(uuid.uuid4())
project = Project(name="test", project_id=project_id)
topology = {
"project_id": str(uuid.uuid4()),
"name": "testtest",
"topology": {
"nodes": [
{
"server_id": 3,
"type": "VPCSDevice"
},
{
"server_id": 3,
"type": "QemuVM"
}
]
}
}
with open(str(tmpdir / "project.gns3"), 'w+') as f:
json.dump(topology, f)
with open(str(tmpdir / "b.png"), 'w+') as f:
f.write("B")
zip_path = str(tmpdir / "project.zip")
with zipfile.ZipFile(zip_path, 'w') as myzip:
myzip.write(str(tmpdir / "project.gns3"), "project.gns3")
myzip.write(str(tmpdir / "b.png"), "b.png")
myzip.write(str(tmpdir / "b.png"), "project-files/dynamips/test")
myzip.write(str(tmpdir / "b.png"), "project-files/qemu/test")
with open(zip_path, "rb") as f:
project.import_zip(f)
assert os.path.exists(os.path.join(project.path, "b.png"))
assert os.path.exists(os.path.join(project.path, "test.gns3"))
assert os.path.exists(os.path.join(project.path, "project-files/dynamips/test"))
assert os.path.exists(os.path.join(project.path, "servers/vm/project-files/qemu/test"))
with open(os.path.join(project.path, "test.gns3")) as f:
content = json.load(f)
assert content["name"] == "test"
assert content["project_id"] == project_id
assert content["topology"]["servers"] == [
{
"id": 1,
"local": True,
"vm": False
},
{
"id": 2,
"local": False,
"vm": True
},
]
assert content["topology"]["nodes"][0]["server_id"] == 1
assert content["topology"]["nodes"][1]["server_id"] == 2
def test_import_with_images(tmpdir):
project_id = str(uuid.uuid4())
project = Project(name="test", project_id=project_id)
with open(str(tmpdir / "test.image"), 'w+') as f:
f.write("B")
zip_path = str(tmpdir / "project.zip")
with zipfile.ZipFile(zip_path, 'w') as myzip:
myzip.write(str(tmpdir / "test.image"), "images/IOS/test.image")
with open(zip_path, "rb") as f:
project.import_zip(f)
# TEST import images
path = os.path.join(project._config().get("images_path"), "IOS", "test.image")
assert os.path.exists(path), path

@ -199,5 +199,3 @@ def test_export_with_images(tmpdir, project):
with zipfile.ZipFile(str(tmpdir / 'zipfile.zip')) as myzip:
myzip.getinfo("images/IOS/test.image")

@ -199,40 +199,3 @@ def test_stream_file(http_compute, tmpdir):
response = http_compute.get("/projects/{project_id}/files/../hello".format(project_id=project.id), raw=True)
assert response.status == 403
def test_export(http_compute, tmpdir, loop, project):
os.makedirs(project.path, exist_ok=True)
with open(os.path.join(project.path, 'a'), 'w+') as f:
f.write('hello')
response = http_compute.get("/projects/{project_id}/export".format(project_id=project.id), raw=True)
assert response.status == 200
assert response.headers['CONTENT-TYPE'] == 'application/gns3project'
assert response.headers['CONTENT-DISPOSITION'] == 'attachment; filename="{}.gns3project"'.format(project.name)
with open(str(tmpdir / 'project.zip'), 'wb+') as f:
f.write(response.body)
with zipfile.ZipFile(str(tmpdir / 'project.zip')) as myzip:
with myzip.open("a") as myfile:
content = myfile.read()
assert content == b"hello"
def test_import(http_compute, tmpdir, loop):
with zipfile.ZipFile(str(tmpdir / "test.zip"), 'w') as myzip:
myzip.writestr("demo", b"hello")
project_id = str(uuid.uuid4())
with open(str(tmpdir / "test.zip"), "rb") as f:
response = http_compute.post("/projects/{project_id}/import".format(project_id=project_id), body=f.read(), raw=True)
assert response.status == 201
project = ProjectManager.instance().get_project(project_id=project_id)
with open(os.path.join(project.path, "demo")) as f:
content = f.read()
assert content == "hello"

Loading…
Cancel
Save