1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-12-26 16:58:28 +00:00

Save image size + start to automatic template creation based on image checksum.

This commit is contained in:
grossmj 2021-08-11 16:58:23 +09:30
parent f13b4e89b7
commit 078c42f185
7 changed files with 39 additions and 9 deletions

View File

@ -56,8 +56,8 @@ async def get_images(
@router.post("/upload/{image_name}", response_model=schemas.Image, status_code=status.HTTP_201_CREATED) @router.post("/upload/{image_name}", response_model=schemas.Image, status_code=status.HTTP_201_CREATED)
async def upload_image( async def upload_image(
image_name: str, image_name: str,
image_type: schemas.ImageType,
request: Request, request: Request,
image_type: schemas.ImageType = schemas.ImageType.qemu,
images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)), images_repo: ImagesRepository = Depends(get_repository(ImagesRepository)),
) -> schemas.Image: ) -> schemas.Image:
""" """
@ -78,6 +78,11 @@ async def upload_image(
except (OSError, InvalidImageError) as e: except (OSError, InvalidImageError) as e:
raise ControllerError(f"Could not save {image_type} image '{image_name}': {e}") raise ControllerError(f"Could not save {image_type} image '{image_name}': {e}")
# TODO: automatically create template based on image checksum
#from gns3server.controller import Controller
#controller = Controller.instance()
#controller.appliance_manager.find_appliance_with_image(image.checksum)
return image return image

View File

@ -56,6 +56,14 @@ class Appliance:
def name(self): def name(self):
return self._data.get("name") return self._data.get("name")
@property
def images(self):
return self._data.get("images")
@property
def versions(self):
return self._data.get("versions")
@symbol.setter @symbol.setter
def symbol(self, new_symbol): def symbol(self, new_symbol):
self._data["symbol"] = new_symbol self._data["symbol"] = new_symbol

View File

@ -77,6 +77,20 @@ class ApplianceManager:
os.makedirs(appliances_path, exist_ok=True) os.makedirs(appliances_path, exist_ok=True)
return appliances_path return appliances_path
#TODO: finish
def find_appliance_with_image(self, image_checksum):
for appliance in self._appliances.values():
if appliance.images:
for image in appliance.images:
if image["md5sum"] == image_checksum:
print(f"APPLIANCE FOUND {appliance.name}")
version = image["version"]
print(f"IMAGE VERSION {version}")
if image.versions:
for version in image.versions:
pass
def load_appliances(self, symbol_theme="Classic"): def load_appliances(self, symbol_theme="Classic"):
""" """
Loads appliance files from disk. Loads appliance files from disk.

View File

@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from sqlalchemy import Column, String, Integer from sqlalchemy import Column, String, Integer, BigInteger
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from .base import BaseTable from .base import BaseTable
@ -28,6 +28,7 @@ class Image(BaseTable):
id = Column(Integer, primary_key=True, autoincrement=True) id = Column(Integer, primary_key=True, autoincrement=True)
filename = Column(String, unique=True, index=True) filename = Column(String, unique=True, index=True)
image_type = Column(String) image_type = Column(String)
image_size = Column(BigInteger)
path = Column(String) path = Column(String)
checksum = Column(String) checksum = Column(String)
checksum_algorithm = Column(String) checksum_algorithm = Column(String)

View File

@ -57,12 +57,13 @@ class ImagesRepository(BaseRepository):
result = await self._db_session.execute(query) result = await self._db_session.execute(query)
return result.scalars().first() return result.scalars().first()
async def add_image(self, image_name, image_type, path, checksum, checksum_algorithm) -> models.Image: async def add_image(self, image_name, image_type, image_size, path, checksum, checksum_algorithm) -> models.Image:
db_image = models.Image( db_image = models.Image(
id=None, id=None,
filename=image_name, filename=image_name,
image_type=image_type, image_type=image_type,
image_size=image_size,
path=path, path=path,
checksum=checksum, checksum=checksum,
checksum_algorithm=checksum_algorithm checksum_algorithm=checksum_algorithm

View File

@ -34,6 +34,7 @@ class ImageBase(BaseModel):
filename: str = Field(..., description="Image name") filename: str = Field(..., description="Image name")
image_type: ImageType = Field(..., description="Image type") image_type: ImageType = Field(..., description="Image type")
image_size: int = Field(..., description="Image size in bytes")
checksum: str = Field(..., description="Checksum value") checksum: str = Field(..., description="Checksum value")
checksum_algorithm: str = Field(..., description="Checksum algorithm") checksum_algorithm: str = Field(..., description="Checksum algorithm")

View File

@ -236,9 +236,9 @@ def check_valid_image_header(data: bytes, image_type: str, header_magic_len: int
# (normal IOS images are big endian!) # (normal IOS images are big endian!)
if data[:header_magic_len] != b'\x7fELF\x01\x01\x01' and data[:7] != b'\x7fELF\x02\x01\x01': if data[:header_magic_len] != b'\x7fELF\x01\x01\x01' and data[:7] != b'\x7fELF\x02\x01\x01':
raise InvalidImageError("Invalid IOU file detected") raise InvalidImageError("Invalid IOU file detected")
# elif image_type == "qemu": elif image_type == "qemu":
# if data[:expected_header_magic_len] != b'QFI\xfb': if data[:header_magic_len] != b'QFI\xfb':
# raise InvalidImageError("Invalid Qemu file detected (must be raw or qcow2)") raise InvalidImageError("Invalid Qemu file detected (must be qcow2 format)")
async def write_image( async def write_image(
@ -267,8 +267,8 @@ async def write_image(
await f.write(chunk) await f.write(chunk)
checksum.update(chunk) checksum.update(chunk)
file_size = os.path.getsize(tmp_path) image_size = os.path.getsize(tmp_path)
if not file_size or file_size < header_magic_len: if not image_size or image_size < header_magic_len:
raise InvalidImageError("The image content is empty or too small to be valid") raise InvalidImageError("The image content is empty or too small to be valid")
checksum = checksum.hexdigest() checksum = checksum.hexdigest()
@ -280,4 +280,4 @@ async def write_image(
raise raise
os.chmod(tmp_path, stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC) os.chmod(tmp_path, stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC)
shutil.move(tmp_path, path) shutil.move(tmp_path, path)
return await images_repo.add_image(image_name, image_type, path, checksum, checksum_algorithm="md5") return await images_repo.add_image(image_name, image_type, image_size, path, checksum, checksum_algorithm="md5")