writable msd

This commit is contained in:
Maxim Devaev
2022-07-23 06:57:38 +03:00
parent aa5a538c64
commit 477e6f05e4
4 changed files with 44 additions and 16 deletions

View File

@@ -56,7 +56,6 @@ from .. import MsdDisconnectedError
from .. import MsdImageNotSelected from .. import MsdImageNotSelected
from .. import MsdUnknownImageError from .. import MsdUnknownImageError
from .. import MsdImageExistsError from .. import MsdImageExistsError
from .. import MsdRwNotSupported
from .. import BaseMsd from .. import BaseMsd
from .. import MsdImageWriter from .. import MsdImageWriter
@@ -95,6 +94,7 @@ class _VirtualDriveState:
image: Optional[_DriveImage] image: Optional[_DriveImage]
connected: bool connected: bool
cdrom: bool cdrom: bool
rw: bool
@classmethod @classmethod
def from_drive_state(cls, state: _DriveState) -> "_VirtualDriveState": def from_drive_state(cls, state: _DriveState) -> "_VirtualDriveState":
@@ -102,6 +102,7 @@ class _VirtualDriveState:
image=state.image, image=state.image,
connected=bool(state.image), connected=bool(state.image),
cdrom=state.cdrom, cdrom=state.cdrom,
rw=state.rw,
) )
@@ -223,7 +224,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
"features": { "features": {
"multi": True, "multi": True,
"cdrom": 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): async with self.__state.busy(check_online=False):
try: try:
self.__drive.set_image_path("") self.__drive.set_image_path("")
self.__drive.set_rw_flag(False)
self.__drive.set_cdrom_flag(False) self.__drive.set_cdrom_flag(False)
self.__drive.set_rw_flag(False)
await self.__remount_rw(False)
except Exception: except Exception:
get_logger(0).exception("Can't reset MSD") get_logger(0).exception("Can't reset MSD properly")
@aiotools.atomic @aiotools.atomic
async def cleanup(self) -> None: async def cleanup(self) -> None:
@@ -264,9 +266,6 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
) -> None: ) -> None:
async with self.__state.busy(): async with self.__state.busy():
if rw is not None:
raise MsdRwNotSupported()
assert self.__state.storage assert self.__state.storage
assert self.__state.vd assert self.__state.vd
@@ -286,6 +285,9 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
if cdrom is not None: if cdrom is not None:
self.__state.vd.cdrom = cdrom self.__state.vd.cdrom = cdrom
if rw is not None:
self.__state.vd.rw = rw
@aiotools.atomic @aiotools.atomic
async def set_connected(self, connected: bool) -> None: async def set_connected(self, connected: bool) -> None:
async with self.__state.busy(): 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): if not os.path.exists(self.__state.vd.image.path):
raise MsdUnknownImageError() raise MsdUnknownImageError()
self.__drive.set_rw_flag(self.__state.vd.rw)
self.__drive.set_cdrom_flag(self.__state.vd.cdrom) 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) self.__drive.set_image_path(self.__state.vd.image.path)
else: else:
if not (self.__state.vd.connected or self.__drive.get_image_path()): if not (self.__state.vd.connected or self.__drive.get_image_path()):
raise MsdDisconnectedError() raise MsdDisconnectedError()
self.__drive.set_image_path("") self.__drive.set_image_path("")
await self.__remount_rw(False, fatal=False)
self.__state.vd.connected = connected self.__state.vd.connected = connected
@@ -339,10 +345,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
finally: finally:
await self.__close_new_writer() await self.__close_new_writer()
try: await self.__remount_rw(False, fatal=False)
await self.__remount_rw(False)
except Exception:
pass
finally: finally:
# Между закрытием файла и эвентом айнотифи состояние может быть не обновлено, # Между закрытием файла и эвентом айнотифи состояние может быть не обновлено,
# так что форсим обновление вручную, чтобы получить актуальное состояние. # так что форсим обновление вручную, чтобы получить актуальное состояние.
@@ -442,9 +445,6 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
async with self.__state._lock: # pylint: disable=protected-access async with self.__state._lock: # pylint: disable=protected-access
try: try:
drive_state = self.__get_drive_state() 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: 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): if os.path.exists(path):
logger.info("Setting up initial image %r ...", self.__initial_image) logger.info("Setting up initial image %r ...", self.__initial_image)
try: try:
self.__drive.set_rw_flag(False)
self.__drive.set_cdrom_flag(self.__initial_cdrom) self.__drive.set_cdrom_flag(self.__initial_cdrom)
self.__drive.set_image_path(path) self.__drive.set_image_path(path)
except Exception: 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)): 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")

View File

@@ -437,6 +437,17 @@
</td> </td>
</tr> </tr>
</table> </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"> <div class="msd-multi-storage feature-disabled">
<hr> <hr>
<div class="text"> <div class="text">

View File

@@ -47,6 +47,9 @@ li(id="msd-dropdown" class="right feature-disabled")
label(for="msd-mode-radio-cdrom") CD-ROM label(for="msd-mode-radio-cdrom") CD-ROM
input(type="radio" id="msd-mode-radio-flash" name="msd-mode-radio" value="0") input(type="radio" id="msd-mode-radio-flash" name="msd-mode-radio" value="0")
label(for="msd-mode-radio-flash") Flash 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") div(class="msd-multi-storage feature-disabled")
hr hr
div(class="text") div(class="text")

View File

@@ -43,6 +43,8 @@ export function Msd() {
tools.radio.setOnClick("msd-mode-radio", __clickModeRadio); tools.radio.setOnClick("msd-mode-radio", __clickModeRadio);
tools.el.setOnClick($("msd-rw-switch"), __clickRwSwitch);
tools.el.setOnClick($("msd-select-new-button"), __toggleSelectSub); tools.el.setOnClick($("msd-select-new-button"), __toggleSelectSub);
$("msd-new-file").onchange = __selectNewFile; $("msd-new-file").onchange = __selectNewFile;
$("msd-new-url").oninput = __selectNewUrl; $("msd-new-url").oninput = __selectNewUrl;
@@ -88,6 +90,10 @@ export function Msd() {
__sendParam("cdrom", tools.radio.getValue("msd-mode-radio")); __sendParam("cdrom", tools.radio.getValue("msd-mode-radio"));
}; };
var __clickRwSwitch = function() {
__sendParam("rw", $("msd-rw-switch").checked);
};
var __sendParam = function(name, value) { var __sendParam = function(name, value) {
let http = tools.makeRequest("POST", `/api/msd/set_params?${name}=${encodeURIComponent(value)}`, function() { let http = tools.makeRequest("POST", `/api/msd/set_params?${name}=${encodeURIComponent(value)}`, function() {
if (http.readyState === 4) { 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.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.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-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)); 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")) { for (let el of $$$(".msd-cdrom-emulation")) {
tools.feature.setEnabled(el, s.features.cdrom); 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)); tools.hidden.setVisible($("msd-message-offline"), (s && !s.online));