From 411ac37f2fab23fd13c0766cad15d09b0675b387 Mon Sep 17 00:00:00 2001 From: themylogin Date: Mon, 16 Dec 2024 14:01:12 +0100 Subject: [PATCH 1/2] Move enclosure label to its own file --- .../25.04/2024-12-16_12-49_enclosure_label.py | 28 ++++++++++++++ .../middlewared/api/v25_04_0/__init__.py | 1 + .../api/v25_04_0/enclosure_label.py | 16 ++++++++ .../middlewared/plugins/enclosure.py | 37 ------------------ .../plugins/enclosure_/enclosure2.py | 5 +-- .../plugins/enclosure_/enclosure_label.py | 38 +++++++++++++++++++ .../enclosure/test_enclosure2_query.py | 2 +- 7 files changed, 85 insertions(+), 42 deletions(-) create mode 100644 src/middlewared/middlewared/alembic/versions/25.04/2024-12-16_12-49_enclosure_label.py create mode 100644 src/middlewared/middlewared/api/v25_04_0/enclosure_label.py delete mode 100644 src/middlewared/middlewared/plugins/enclosure.py create mode 100644 src/middlewared/middlewared/plugins/enclosure_/enclosure_label.py diff --git a/src/middlewared/middlewared/alembic/versions/25.04/2024-12-16_12-49_enclosure_label.py b/src/middlewared/middlewared/alembic/versions/25.04/2024-12-16_12-49_enclosure_label.py new file mode 100644 index 0000000000000..d6c9de2de0af8 --- /dev/null +++ b/src/middlewared/middlewared/alembic/versions/25.04/2024-12-16_12-49_enclosure_label.py @@ -0,0 +1,28 @@ +"""Rename `enclosure_label` table + +Revision ID: 19cdc9f2d2df +Revises: b44c092bfa30 +Create Date: 2024-12-16 12:49:19.950812+00:00 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '19cdc9f2d2df' +down_revision = 'b44c092bfa30' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.execute("ALTER TABLE truenas_enclosurelabel RENAME TO enclosure_label") + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### diff --git a/src/middlewared/middlewared/api/v25_04_0/__init__.py b/src/middlewared/middlewared/api/v25_04_0/__init__.py index 08eed715dea52..8006d8917164d 100644 --- a/src/middlewared/middlewared/api/v25_04_0/__init__.py +++ b/src/middlewared/middlewared/api/v25_04_0/__init__.py @@ -16,6 +16,7 @@ from .disk import * # noqa from .docker import * # noqa from .docker_network import * # noqa +from .enclosure_label import * # noqa from .failover_reboot import * # noqa from .fc_host import * # noqa from .fcport import * # noqa diff --git a/src/middlewared/middlewared/api/v25_04_0/enclosure_label.py b/src/middlewared/middlewared/api/v25_04_0/enclosure_label.py new file mode 100644 index 0000000000000..c32cf7873fc8d --- /dev/null +++ b/src/middlewared/middlewared/api/v25_04_0/enclosure_label.py @@ -0,0 +1,16 @@ +from middlewared.api.base import BaseModel, ForUpdateMetaclass + +__all__ = ["EnclosureLabelUpdateData", "EnclosureLabelUpdateArgs", "EnclosureLabelUpdateResult"] + + +class EnclosureLabelUpdateData(BaseModel, metaclass=ForUpdateMetaclass): + label: str + + +class EnclosureLabelUpdateArgs(BaseModel): + id: str + enclosure_update: EnclosureLabelUpdateData + + +class EnclosureLabelUpdateResult(BaseModel): + result: None diff --git a/src/middlewared/middlewared/plugins/enclosure.py b/src/middlewared/middlewared/plugins/enclosure.py deleted file mode 100644 index 6a12f5a126b1d..0000000000000 --- a/src/middlewared/middlewared/plugins/enclosure.py +++ /dev/null @@ -1,37 +0,0 @@ -import middlewared.sqlalchemy as sa - -from middlewared.schema import accepts, Dict, Str -from middlewared.service import CRUDService - - -class EnclosureLabelModel(sa.Model): - __tablename__ = "truenas_enclosurelabel" - - id = sa.Column(sa.Integer(), primary_key=True) - encid = sa.Column(sa.String(200), unique=True) - label = sa.Column(sa.String(200)) - - -class EnclosureService(CRUDService): - class Config: - cli_namespace = "storage.enclosure" - - @accepts( - Str("id"), - Dict( - "enclosure_update", - Str("label"), - update=True, - ), - ) - async def do_update(self, id_, data): - if "label" in data: - await self.middleware.call( - "datastore.delete", "truenas.enclosurelabel", [["encid", "=", id_]] - ) - await self.middleware.call( - "datastore.insert", - "truenas.enclosurelabel", - {"encid": id_, "label": data["label"]}, - ) - return await self.get_instance(id_) diff --git a/src/middlewared/middlewared/plugins/enclosure_/enclosure2.py b/src/middlewared/middlewared/plugins/enclosure_/enclosure2.py index 7e32f94dd7689..f6b85e6ef891c 100644 --- a/src/middlewared/middlewared/plugins/enclosure_/enclosure2.py +++ b/src/middlewared/middlewared/plugins/enclosure_/enclosure2.py @@ -139,10 +139,7 @@ def query(self, filters, options): # this feature is only available on hardware that ix sells return enclosures - labels = { - label['encid']: label['label'] - for label in self.middleware.call_sync('datastore.query', 'truenas.enclosurelabel') - } + labels = self.middleware.call_sync('enclosure.get_labels') for i in self.get_ses_enclosures() + self.map_nvme() + self.middleware.call_sync('enclosure2.map_jbof'): if i.pop('should_ignore'): continue diff --git a/src/middlewared/middlewared/plugins/enclosure_/enclosure_label.py b/src/middlewared/middlewared/plugins/enclosure_/enclosure_label.py new file mode 100644 index 0000000000000..104ec6520bc71 --- /dev/null +++ b/src/middlewared/middlewared/plugins/enclosure_/enclosure_label.py @@ -0,0 +1,38 @@ +import middlewared.sqlalchemy as sa + +from middlewared.api import api_method +from middlewared.api.current import EnclosureLabelUpdateArgs, EnclosureLabelUpdateResult +from middlewared.service import private, Service + + +class EnclosureLabelModel(sa.Model): + __tablename__ = "enclosure_label" + + id = sa.Column(sa.Integer(), primary_key=True) + encid = sa.Column(sa.String(200), unique=True) + label = sa.Column(sa.String(200)) + + +class EnclosureService(Service): + class Config: + namespace = "enclosure" + cli_namespace = "storage.enclosure" + + @api_method(EnclosureLabelUpdateArgs, EnclosureLabelUpdateResult) + async def update(self, id_, data): + if "label" in data: + await self.middleware.call( + "datastore.delete", "enclosure.label", [["encid", "=", id_]] + ) + await self.middleware.call( + "datastore.insert", + "enclosure.label", + {"encid": id_, "label": data["label"]}, + ) + + @private + async def get_labels(self): + return { + label["encid"]: label["label"] + for label in await self.middleware.call("datastore.query", "enclosure.label") + } diff --git a/src/middlewared/middlewared/pytest/unit/plugins/enclosure/test_enclosure2_query.py b/src/middlewared/middlewared/pytest/unit/plugins/enclosure/test_enclosure2_query.py index 5fed380fcf247..127dc3e0efe83 100644 --- a/src/middlewared/middlewared/pytest/unit/plugins/enclosure/test_enclosure2_query.py +++ b/src/middlewared/middlewared/pytest/unit/plugins/enclosure/test_enclosure2_query.py @@ -73,7 +73,7 @@ def test_enclosure2_query(enc2_data): e.middleware._resolve_methods([Enclosure2Service], []) e.middleware['truenas.get_chassis_hardware'] = Mock(return_value=enc2_mocked.chassis) e.middleware['truenas.is_ix_hardware'] = Mock(return_value=True) - e.middleware['datastore.query'] = Mock(return_value=enc2_mocked.labels) + e.middleware['enclosure.get_labels'] = Mock(return_value=enc2_mocked.labels) e.middleware['system.dmidecode_info'] = Mock(return_value=enc2_mocked.dmi) e.middleware['jbof.query'] = Mock(return_value=[]) e.middleware['enclosure2.map_jbof'] = Mock(return_value=[]) From 394daf305f754df60f3dd864f50b248ef4f53ca0 Mon Sep 17 00:00:00 2001 From: themylogin Date: Tue, 17 Dec 2024 21:30:51 +0100 Subject: [PATCH 2/2] Address review --- .../api/v25_04_0/enclosure_label.py | 12 +++---- .../plugins/enclosure_/enclosure2.py | 2 +- .../plugins/enclosure_/enclosure_label.py | 31 +++++++++---------- .../enclosure/test_enclosure2_query.py | 2 +- 4 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/middlewared/middlewared/api/v25_04_0/enclosure_label.py b/src/middlewared/middlewared/api/v25_04_0/enclosure_label.py index c32cf7873fc8d..cd4f7e5ee3546 100644 --- a/src/middlewared/middlewared/api/v25_04_0/enclosure_label.py +++ b/src/middlewared/middlewared/api/v25_04_0/enclosure_label.py @@ -1,15 +1,11 @@ -from middlewared.api.base import BaseModel, ForUpdateMetaclass +from middlewared.api.base import BaseModel -__all__ = ["EnclosureLabelUpdateData", "EnclosureLabelUpdateArgs", "EnclosureLabelUpdateResult"] +__all__ = ["EnclosureLabelSetArgs", "EnclosureLabelUpdateResult"] -class EnclosureLabelUpdateData(BaseModel, metaclass=ForUpdateMetaclass): - label: str - - -class EnclosureLabelUpdateArgs(BaseModel): +class EnclosureLabelSetArgs(BaseModel): id: str - enclosure_update: EnclosureLabelUpdateData + label: str class EnclosureLabelUpdateResult(BaseModel): diff --git a/src/middlewared/middlewared/plugins/enclosure_/enclosure2.py b/src/middlewared/middlewared/plugins/enclosure_/enclosure2.py index f6b85e6ef891c..e9479982c1437 100644 --- a/src/middlewared/middlewared/plugins/enclosure_/enclosure2.py +++ b/src/middlewared/middlewared/plugins/enclosure_/enclosure2.py @@ -139,7 +139,7 @@ def query(self, filters, options): # this feature is only available on hardware that ix sells return enclosures - labels = self.middleware.call_sync('enclosure.get_labels') + labels = self.middleware.call_sync('enclosure.label.get_all') for i in self.get_ses_enclosures() + self.map_nvme() + self.middleware.call_sync('enclosure2.map_jbof'): if i.pop('should_ignore'): continue diff --git a/src/middlewared/middlewared/plugins/enclosure_/enclosure_label.py b/src/middlewared/middlewared/plugins/enclosure_/enclosure_label.py index 104ec6520bc71..f3402751b0174 100644 --- a/src/middlewared/middlewared/plugins/enclosure_/enclosure_label.py +++ b/src/middlewared/middlewared/plugins/enclosure_/enclosure_label.py @@ -1,7 +1,7 @@ import middlewared.sqlalchemy as sa from middlewared.api import api_method -from middlewared.api.current import EnclosureLabelUpdateArgs, EnclosureLabelUpdateResult +from middlewared.api.current import EnclosureLabelSetArgs, EnclosureLabelUpdateResult from middlewared.service import private, Service @@ -15,24 +15,23 @@ class EnclosureLabelModel(sa.Model): class EnclosureService(Service): class Config: - namespace = "enclosure" - cli_namespace = "storage.enclosure" - - @api_method(EnclosureLabelUpdateArgs, EnclosureLabelUpdateResult) - async def update(self, id_, data): - if "label" in data: - await self.middleware.call( - "datastore.delete", "enclosure.label", [["encid", "=", id_]] - ) - await self.middleware.call( - "datastore.insert", - "enclosure.label", - {"encid": id_, "label": data["label"]}, - ) + namespace = "enclosure.label" + cli_namespace = "storage.enclosure.label" @private - async def get_labels(self): + async def get_all(self): return { label["encid"]: label["label"] for label in await self.middleware.call("datastore.query", "enclosure.label") } + + @api_method(EnclosureLabelSetArgs, EnclosureLabelUpdateResult) + async def set(self, id_, label): + await self.middleware.call( + "datastore.delete", "enclosure.label", [["encid", "=", id_]] + ) + await self.middleware.call( + "datastore.insert", + "enclosure.label", + {"encid": id_, "label": label}, + ) diff --git a/src/middlewared/middlewared/pytest/unit/plugins/enclosure/test_enclosure2_query.py b/src/middlewared/middlewared/pytest/unit/plugins/enclosure/test_enclosure2_query.py index 127dc3e0efe83..ba7878f058e7e 100644 --- a/src/middlewared/middlewared/pytest/unit/plugins/enclosure/test_enclosure2_query.py +++ b/src/middlewared/middlewared/pytest/unit/plugins/enclosure/test_enclosure2_query.py @@ -73,7 +73,7 @@ def test_enclosure2_query(enc2_data): e.middleware._resolve_methods([Enclosure2Service], []) e.middleware['truenas.get_chassis_hardware'] = Mock(return_value=enc2_mocked.chassis) e.middleware['truenas.is_ix_hardware'] = Mock(return_value=True) - e.middleware['enclosure.get_labels'] = Mock(return_value=enc2_mocked.labels) + e.middleware['enclosure.label.get_all'] = Mock(return_value=enc2_mocked.labels) e.middleware['system.dmidecode_info'] = Mock(return_value=enc2_mocked.dmi) e.middleware['jbof.query'] = Mock(return_value=[]) e.middleware['enclosure2.map_jbof'] = Mock(return_value=[])