mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-26 00:38:10 +00:00
Save image size + start to automatic template creation based on image checksum.
This commit is contained in:
parent
f13b4e89b7
commit
078c42f185
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
Loading…
Reference in New Issue
Block a user