diff options
author | Maxim Devaev <[email protected]> | 2022-07-23 06:57:38 +0300 |
---|---|---|
committer | Maxim Devaev <[email protected]> | 2022-07-24 05:38:26 +0300 |
commit | 477e6f05e44d3c83ff19a97f1454ac1ba9191e70 (patch) | |
tree | a976dcd5550ad549699f54b5c10a0e68cececb6e | |
parent | aa5a538c64f8ef8fe268bf1f78b44a0d70f14389 (diff) |
writable msd
-rw-r--r-- | kvmd/plugins/msd/otg/__init__.py | 34 | ||||
-rw-r--r-- | web/kvm/index.html | 11 | ||||
-rw-r--r-- | web/kvm/navbar-msd.pug | 3 | ||||
-rw-r--r-- | web/share/js/kvm/msd.js | 12 |
4 files changed, 44 insertions, 16 deletions
diff --git a/kvmd/plugins/msd/otg/__init__.py b/kvmd/plugins/msd/otg/__init__.py index 3a2250e8..f04d5084 100644 --- a/kvmd/plugins/msd/otg/__init__.py +++ b/kvmd/plugins/msd/otg/__init__.py @@ -56,7 +56,6 @@ from .. import MsdDisconnectedError from .. import MsdImageNotSelected from .. import MsdUnknownImageError from .. import MsdImageExistsError -from .. import MsdRwNotSupported from .. import BaseMsd from .. import MsdImageWriter @@ -95,6 +94,7 @@ class _VirtualDriveState: image: Optional[_DriveImage] connected: bool cdrom: bool + rw: bool @classmethod def from_drive_state(cls, state: _DriveState) -> "_VirtualDriveState": @@ -102,6 +102,7 @@ class _VirtualDriveState: image=state.image, connected=bool(state.image), cdrom=state.cdrom, + rw=state.rw, ) @@ -223,7 +224,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes "features": { "multi": True, "cdrom": True, - "rw": False, + "rw": True, }, } @@ -244,10 +245,11 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes async with self.__state.busy(check_online=False): try: self.__drive.set_image_path("") - self.__drive.set_rw_flag(False) self.__drive.set_cdrom_flag(False) + self.__drive.set_rw_flag(False) + await self.__remount_rw(False) except Exception: - get_logger(0).exception("Can't reset MSD") + get_logger(0).exception("Can't reset MSD properly") @aiotools.atomic async def cleanup(self) -> None: @@ -264,9 +266,6 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes ) -> None: async with self.__state.busy(): - if rw is not None: - raise MsdRwNotSupported() - assert self.__state.storage assert self.__state.vd @@ -286,6 +285,9 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes if cdrom is not None: self.__state.vd.cdrom = cdrom + if rw is not None: + self.__state.vd.rw = rw + @aiotools.atomic async def set_connected(self, connected: bool) -> None: async with self.__state.busy(): @@ -301,13 +303,17 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes if not os.path.exists(self.__state.vd.image.path): raise MsdUnknownImageError() + self.__drive.set_rw_flag(self.__state.vd.rw) self.__drive.set_cdrom_flag(self.__state.vd.cdrom) + if self.__state.vd.rw: + await self.__remount_rw(True) self.__drive.set_image_path(self.__state.vd.image.path) else: if not (self.__state.vd.connected or self.__drive.get_image_path()): raise MsdDisconnectedError() self.__drive.set_image_path("") + await self.__remount_rw(False, fatal=False) self.__state.vd.connected = connected @@ -339,10 +345,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes finally: await self.__close_new_writer() - try: - await self.__remount_rw(False) - except Exception: - pass + await self.__remount_rw(False, fatal=False) finally: # Между закрытием файла и эвентом айнотифи состояние может быть не обновлено, # так что форсим обновление вручную, чтобы получить актуальное состояние. @@ -442,9 +445,6 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes async with self.__state._lock: # pylint: disable=protected-access try: drive_state = self.__get_drive_state() - if drive_state.rw: - # Внештатное использование MSD, ломаемся - raise MsdError("MSD has been switched to RW-mode manually") if self.__state.vd is None and drive_state.image is None: # Если только что включились и образ не подключен - попробовать @@ -485,6 +485,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes if os.path.exists(path): logger.info("Setting up initial image %r ...", self.__initial_image) try: + self.__drive.set_rw_flag(False) self.__drive.set_cdrom_flag(self.__initial_cdrom) self.__drive.set_image_path(path) except Exception: @@ -550,6 +551,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes # ===== - async def __remount_rw(self, rw: bool) -> None: + async def __remount_rw(self, rw: bool, fatal: bool=True) -> None: if not (await aiohelpers.remount("MSD", self.__remount_cmd, rw)): - raise MsdError("Can't execute remount helper") + if fatal: + raise MsdError("Can't execute remount helper") diff --git a/web/kvm/index.html b/web/kvm/index.html index 3b908aee..093133ee 100644 --- a/web/kvm/index.html +++ b/web/kvm/index.html @@ -437,6 +437,17 @@ </td> </tr> </table> + <table class="kv msd-rw feature-disabled"> + <tr> + <td>Read-write mode:</td> + <td align="right"> + <div class="switch-box"> + <input disabled type="checkbox" id="msd-rw-switch"> + <label for="msd-rw-switch"><span class="switch-inner"></span><span class="switch"></span></label> + </div> + </td> + </tr> + </table> <div class="msd-multi-storage feature-disabled"> <hr> <div class="text"> diff --git a/web/kvm/navbar-msd.pug b/web/kvm/navbar-msd.pug index b2cd5b99..68d764c3 100644 --- a/web/kvm/navbar-msd.pug +++ b/web/kvm/navbar-msd.pug @@ -47,6 +47,9 @@ li(id="msd-dropdown" class="right feature-disabled") label(for="msd-mode-radio-cdrom") CD-ROM input(type="radio" id="msd-mode-radio-flash" name="msd-mode-radio" value="0") label(for="msd-mode-radio-flash") Flash + table(class="kv msd-rw feature-disabled") + tr + +menu_switch_notable("msd-rw-switch", "Read-write mode", false, false) div(class="msd-multi-storage feature-disabled") hr div(class="text") diff --git a/web/share/js/kvm/msd.js b/web/share/js/kvm/msd.js index 3575f0c4..aff901d5 100644 --- a/web/share/js/kvm/msd.js +++ b/web/share/js/kvm/msd.js @@ -43,6 +43,8 @@ export function Msd() { tools.radio.setOnClick("msd-mode-radio", __clickModeRadio); + tools.el.setOnClick($("msd-rw-switch"), __clickRwSwitch); + tools.el.setOnClick($("msd-select-new-button"), __toggleSelectSub); $("msd-new-file").onchange = __selectNewFile; $("msd-new-url").oninput = __selectNewUrl; @@ -88,6 +90,10 @@ export function Msd() { __sendParam("cdrom", tools.radio.getValue("msd-mode-radio")); }; + var __clickRwSwitch = function() { + __sendParam("rw", $("msd-rw-switch").checked); + }; + var __sendParam = function(name, value) { let http = tools.makeRequest("POST", `/api/msd/set_params?${name}=${encodeURIComponent(value)}`, function() { if (http.readyState === 4) { @@ -243,6 +249,9 @@ export function Msd() { tools.radio.setEnabled("msd-mode-radio", (online && s.features.cdrom && !s.drive.connected && !s.busy)); tools.radio.setValue("msd-mode-radio", `${Number(online && s.features.cdrom && s.drive.cdrom)}`); + tools.el.setEnabled($("msd-rw-switch"), (online && s.features.rw && !s.drive.connected && !s.busy)); + $("msd-rw-switch").checked = (online && s.features.rw && s.drive.rw); + tools.el.setEnabled($("msd-connect-button"), (online && (!s.features.multi || s.drive.image) && !s.drive.connected && !s.busy)); tools.el.setEnabled($("msd-disconnect-button"), (online && s.drive.connected && !s.busy)); @@ -289,6 +298,9 @@ export function Msd() { for (let el of $$$(".msd-cdrom-emulation")) { tools.feature.setEnabled(el, s.features.cdrom); } + for (let el of $$$(".msd-rw")) { + tools.feature.setEnabled(el, s.features.rw); + } } tools.hidden.setVisible($("msd-message-offline"), (s && !s.online)); |