mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-02-01 18:41:54 +08:00
refactoring
This commit is contained in:
@@ -5,7 +5,8 @@ from typing import Type
|
|||||||
|
|
||||||
# =====
|
# =====
|
||||||
class RegionIsBusyError(Exception):
|
class RegionIsBusyError(Exception):
|
||||||
pass
|
def __init__(self) -> None:
|
||||||
|
super().__init__("Performing another operation, please try again later")
|
||||||
|
|
||||||
|
|
||||||
class AioExclusiveRegion:
|
class AioExclusiveRegion:
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ from . import gpio
|
|||||||
|
|
||||||
# =====
|
# =====
|
||||||
class AtxIsBusy(aioregion.RegionIsBusyError):
|
class AtxIsBusy(aioregion.RegionIsBusyError):
|
||||||
def __init__(self) -> None:
|
pass
|
||||||
super().__init__("Performing another operation, please try again later")
|
|
||||||
|
|
||||||
|
|
||||||
class Atx:
|
class Atx:
|
||||||
|
|||||||
@@ -21,37 +21,36 @@ from .logging import get_logger
|
|||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
class MassStorageError(Exception):
|
class MsdError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MassStorageOperationError(MassStorageError):
|
class MsdOperationError(MsdError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IsNotOperationalError(MassStorageOperationError):
|
class MsdIsNotOperationalError(MsdOperationError):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__("Missing path for mass-storage device")
|
super().__init__("Missing path for mass-storage device")
|
||||||
|
|
||||||
|
|
||||||
class AlreadyConnectedToPcError(MassStorageOperationError):
|
class MsdAlreadyConnectedToPcError(MsdOperationError):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__("Mass-storage is already connected to Server")
|
super().__init__("Mass-storage is already connected to Server")
|
||||||
|
|
||||||
|
|
||||||
class AlreadyConnectedToKvmError(MassStorageOperationError):
|
class MsdAlreadyConnectedToKvmError(MsdOperationError):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__("Mass-storage is already connected to KVM")
|
super().__init__("Mass-storage is already connected to KVM")
|
||||||
|
|
||||||
|
|
||||||
class IsNotConnectedToKvmError(MassStorageOperationError):
|
class MsdIsNotConnectedToKvmError(MsdOperationError):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__("Mass-storage is not connected to KVM")
|
super().__init__("Mass-storage is not connected to KVM")
|
||||||
|
|
||||||
|
|
||||||
class IsBusyError(MassStorageOperationError, aioregion.RegionIsBusyError):
|
class MsdIsBusyError(MsdOperationError, aioregion.RegionIsBusyError):
|
||||||
def __init__(self) -> None:
|
pass
|
||||||
super().__init__("Mass-storage is busy (write in progress)")
|
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
@@ -156,7 +155,7 @@ def _explore_device(device_path: str) -> Optional[_MassStorageDeviceInfo]:
|
|||||||
def _msd_operated(method: Callable) -> Callable:
|
def _msd_operated(method: Callable) -> Callable:
|
||||||
async def wrap(self: "MassStorageDevice", *args: Any, **kwargs: Any) -> Any:
|
async def wrap(self: "MassStorageDevice", *args: Any, **kwargs: Any) -> Any:
|
||||||
if not self._device_path: # pylint: disable=protected-access
|
if not self._device_path: # pylint: disable=protected-access
|
||||||
IsNotOperationalError()
|
MsdIsNotOperationalError()
|
||||||
return (await method(self, *args, **kwargs))
|
return (await method(self, *args, **kwargs))
|
||||||
return wrap
|
return wrap
|
||||||
|
|
||||||
@@ -177,8 +176,8 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
|
|||||||
self.__loop = loop
|
self.__loop = loop
|
||||||
|
|
||||||
self.__device_info: Optional[_MassStorageDeviceInfo] = None
|
self.__device_info: Optional[_MassStorageDeviceInfo] = None
|
||||||
self.__region = aioregion.AioExclusiveRegion(IsBusyError)
|
self.__region = aioregion.AioExclusiveRegion(MsdIsBusyError)
|
||||||
self._device_file: Optional[aiofiles.base.AiofilesContextManager] = None
|
self.__device_file: Optional[aiofiles.base.AiofilesContextManager] = None
|
||||||
self.__written = 0
|
self.__written = 0
|
||||||
|
|
||||||
logger = get_logger(0)
|
logger = get_logger(0)
|
||||||
@@ -188,7 +187,7 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
|
|||||||
logger.info("Enabled image metadata writing")
|
logger.info("Enabled image metadata writing")
|
||||||
loop.run_until_complete(self.connect_to_kvm(no_delay=True))
|
loop.run_until_complete(self.connect_to_kvm(no_delay=True))
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
if isinstance(err, MassStorageError):
|
if isinstance(err, MsdError):
|
||||||
log = logger.error
|
log = logger.error
|
||||||
else:
|
else:
|
||||||
log = logger.exception
|
log = logger.exception
|
||||||
@@ -201,7 +200,7 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
|
|||||||
async def connect_to_kvm(self, no_delay: bool=False) -> None:
|
async def connect_to_kvm(self, no_delay: bool=False) -> None:
|
||||||
with self.__region:
|
with self.__region:
|
||||||
if self.__device_info:
|
if self.__device_info:
|
||||||
raise AlreadyConnectedToKvmError()
|
raise MsdAlreadyConnectedToKvmError()
|
||||||
# TODO: disable gpio
|
# TODO: disable gpio
|
||||||
if not no_delay:
|
if not no_delay:
|
||||||
await asyncio.sleep(self.__init_delay)
|
await asyncio.sleep(self.__init_delay)
|
||||||
@@ -212,7 +211,7 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
|
|||||||
async def connect_to_pc(self) -> None:
|
async def connect_to_pc(self) -> None:
|
||||||
with self.__region:
|
with self.__region:
|
||||||
if not self.__device_info:
|
if not self.__device_info:
|
||||||
raise AlreadyConnectedToPcError()
|
raise MsdAlreadyConnectedToPcError()
|
||||||
# TODO: enable gpio
|
# TODO: enable gpio
|
||||||
self.__device_info = None
|
self.__device_info = None
|
||||||
get_logger().info("Mass-storage device switched to Server")
|
get_logger().info("Mass-storage device switched to Server")
|
||||||
@@ -225,7 +224,7 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
|
|||||||
return {
|
return {
|
||||||
"in_operate": bool(self._device_path),
|
"in_operate": bool(self._device_path),
|
||||||
"connected_to": ("kvm" if self.__device_info else "server"),
|
"connected_to": ("kvm" if self.__device_info else "server"),
|
||||||
"busy": bool(self._device_file),
|
"busy": bool(self.__device_file),
|
||||||
"written": self.__written,
|
"written": self.__written,
|
||||||
"info": info,
|
"info": info,
|
||||||
}
|
}
|
||||||
@@ -238,19 +237,19 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
|
|||||||
async def __aenter__(self) -> "MassStorageDevice":
|
async def __aenter__(self) -> "MassStorageDevice":
|
||||||
self.__region.enter()
|
self.__region.enter()
|
||||||
if not self.__device_info:
|
if not self.__device_info:
|
||||||
raise IsNotConnectedToKvmError()
|
raise MsdIsNotConnectedToKvmError()
|
||||||
self._device_file = await aiofiles.open(self.__device_info.path, mode="w+b", buffering=0)
|
self.__device_file = await aiofiles.open(self.__device_info.path, mode="w+b", buffering=0)
|
||||||
self.__written = 0
|
self.__written = 0
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def write_image_info(self, name: str, complete: bool) -> None:
|
async def write_image_info(self, name: str, complete: bool) -> None:
|
||||||
assert self._device_file
|
assert self.__device_file
|
||||||
assert self.__device_info
|
assert self.__device_info
|
||||||
if self.__write_meta:
|
if self.__write_meta:
|
||||||
if self.__device_info.size - self.__written > _IMAGE_INFO_SIZE:
|
if self.__device_info.size - self.__written > _IMAGE_INFO_SIZE:
|
||||||
await self._device_file.seek(self.__device_info.size - _IMAGE_INFO_SIZE)
|
await self.__device_file.seek(self.__device_info.size - _IMAGE_INFO_SIZE)
|
||||||
await self.__write_to_device_file(_make_image_info_bytes(name, self.__written, complete))
|
await self.__write_to_device_file(_make_image_info_bytes(name, self.__written, complete))
|
||||||
await self._device_file.seek(0)
|
await self.__device_file.seek(0)
|
||||||
await self.__load_device_info()
|
await self.__load_device_info()
|
||||||
else:
|
else:
|
||||||
get_logger().error("Can't write image info because device is full")
|
get_logger().error("Can't write image info because device is full")
|
||||||
@@ -272,24 +271,24 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
|
|||||||
self.__region.exit()
|
self.__region.exit()
|
||||||
|
|
||||||
async def __write_to_device_file(self, data: bytes) -> None:
|
async def __write_to_device_file(self, data: bytes) -> None:
|
||||||
assert self._device_file
|
assert self.__device_file
|
||||||
await self._device_file.write(data)
|
await self.__device_file.write(data)
|
||||||
await self._device_file.flush()
|
await self.__device_file.flush()
|
||||||
await self.__loop.run_in_executor(None, os.fsync, self._device_file.fileno())
|
await self.__loop.run_in_executor(None, os.fsync, self.__device_file.fileno())
|
||||||
|
|
||||||
async def __load_device_info(self) -> None:
|
async def __load_device_info(self) -> None:
|
||||||
device_info = await self.__loop.run_in_executor(None, _explore_device, self._device_path)
|
device_info = await self.__loop.run_in_executor(None, _explore_device, self._device_path)
|
||||||
if not device_info:
|
if not device_info:
|
||||||
raise MassStorageError("Can't explore device %r" % (self._device_path))
|
raise MsdError("Can't explore device %r" % (self._device_path))
|
||||||
self.__device_info = device_info
|
self.__device_info = device_info
|
||||||
|
|
||||||
async def __close_device_file(self) -> None:
|
async def __close_device_file(self) -> None:
|
||||||
try:
|
try:
|
||||||
if self._device_file:
|
if self.__device_file:
|
||||||
get_logger().info("Closing mass-storage device file ...")
|
get_logger().info("Closing mass-storage device file ...")
|
||||||
await self._device_file.close()
|
await self.__device_file.close()
|
||||||
except Exception:
|
except Exception:
|
||||||
get_logger().exception("Can't close mass-storage device file")
|
get_logger().exception("Can't close mass-storage device file")
|
||||||
# TODO: reset device file
|
# TODO: reset device file
|
||||||
self._device_file = None
|
self.__device_file = None
|
||||||
self.__written = 0
|
self.__written = 0
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from .hid import Hid
|
|||||||
|
|
||||||
from .atx import Atx
|
from .atx import Atx
|
||||||
|
|
||||||
from .msd import MassStorageOperationError
|
from .msd import MsdOperationError
|
||||||
from .msd import MassStorageDevice
|
from .msd import MassStorageDevice
|
||||||
|
|
||||||
from .streamer import Streamer
|
from .streamer import Streamer
|
||||||
@@ -47,10 +47,11 @@ def _json(result: Optional[Dict]=None, status: int=200) -> aiohttp.web.Response:
|
|||||||
|
|
||||||
|
|
||||||
def _json_exception(msg: str, err: Exception, status: int) -> aiohttp.web.Response:
|
def _json_exception(msg: str, err: Exception, status: int) -> aiohttp.web.Response:
|
||||||
get_logger().error("%s: %s", msg, err)
|
msg = "%s: %s" % (msg, err)
|
||||||
|
get_logger().error(msg)
|
||||||
return _json({
|
return _json({
|
||||||
"error": type(err).__name__,
|
"error": type(err).__name__,
|
||||||
"error_msg": str(err),
|
"error_msg": msg,
|
||||||
}, status=status)
|
}, status=status)
|
||||||
|
|
||||||
|
|
||||||
@@ -65,7 +66,7 @@ def _wrap_exceptions_for_web(msg: str) -> Callable:
|
|||||||
return (await method(self, request))
|
return (await method(self, request))
|
||||||
except RegionIsBusyError as err:
|
except RegionIsBusyError as err:
|
||||||
return _json_exception(msg, err, 409)
|
return _json_exception(msg, err, 409)
|
||||||
except (BadRequest, MassStorageOperationError) as err:
|
except (BadRequest, MsdOperationError) as err:
|
||||||
return _json_exception(msg, err, 400)
|
return _json_exception(msg, err, 400)
|
||||||
return wrap
|
return wrap
|
||||||
return make_wrapper
|
return make_wrapper
|
||||||
@@ -227,7 +228,7 @@ class Server: # pylint: disable=too-many-instance-attributes
|
|||||||
await self.__broadcast_event("msd_state", state="free") # type: ignore
|
await self.__broadcast_event("msd_state", state="free") # type: ignore
|
||||||
finally:
|
finally:
|
||||||
if written != 0:
|
if written != 0:
|
||||||
logger.info("written %d bytes to mass-storage device", written)
|
logger.info("Written %d bytes to mass-storage device", written)
|
||||||
return _json({"written": written})
|
return _json({"written": written})
|
||||||
|
|
||||||
async def __streamer_state_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response:
|
async def __streamer_state_handler(self, _: aiohttp.web.Request) -> aiohttp.web.Response:
|
||||||
|
|||||||
Reference in New Issue
Block a user