]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Host Maintenance Follow ups 41056/head
authorNizamudeen A <nia@redhat.com>
Fri, 26 Mar 2021 07:57:40 +0000 (13:27 +0530)
committerNizamudeen A <nia@redhat.com>
Wed, 28 Apr 2021 07:32:07 +0000 (13:02 +0530)
Added the ability to create a host in maintenance mode

Fixes: https://tracker.ceph.com/issues/49998
Signed-off-by: Nizamudeen A <nia@redhat.com>
(cherry picked from commit 23bdf201c4bfac4628c27cc9a9dc749ad277a563)

14 files changed:
qa/workunits/cephadm/test_dashboard_e2e.sh
src/pybind/mgr/dashboard/controllers/host.py
src/pybind/mgr/dashboard/frontend/cypress/fixtures/orchestrator/services.json [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/hosts.po.ts
src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/01-hosts-force-maintenance.e2e-spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/01-hosts.e2e-spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-form/host-form.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-form/host-form.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-form/host-form.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/api/host.service.ts
src/pybind/mgr/dashboard/openapi.yaml
src/pybind/mgr/dashboard/services/orchestrator.py

index 5764ecb5d43c25b248babb9bfd25af60a288f597..bd37154d9b879e298669a4ae907085cfea63ad46 100755 (executable)
@@ -74,10 +74,12 @@ ceph device monitoring off
 ceph tell mon.\* injectargs '--mon-allow-pool-delete=true'
 ceph osd pool rm device_health_metrics device_health_metrics --yes-i-really-really-mean-it
 
-# Take `orch device ls` as ground truth.
+# Take `orch device ls` and `orch ps` as ground truth.
 ceph orch device ls --refresh
+ceph orch ps --refresh
 sleep 10  # the previous call is asynchronous
 ceph orch device ls --format=json | tee cypress/fixtures/orchestrator/inventory.json
+ceph orch ps --format=json | tee cypress/fixtures/orchestrator/services.json
 
 DASHBOARD_ADMIN_SECRET_FILE="/tmp/dashboard-admin-secret.txt"
 printf 'admin' > "${DASHBOARD_ADMIN_SECRET_FILE}"
@@ -91,10 +93,23 @@ find cypress # List all specs
 
 cypress_run "orchestrator/01-hosts.e2e-spec.ts"
 
+ceph orch apply rgw foo --placement=3
+sleep 15
+ceph orch device ls --refresh
+ceph orch ps --refresh
+sleep 10  # the previous call is asynchronous
+ceph orch device ls --format=json | tee cypress/fixtures/orchestrator/inventory.json
+ceph orch ps --format=json | tee cypress/fixtures/orchestrator/services.json
+
+cypress_run "orchestrator/01-hosts-force-maintenance.e2e-spec.ts"
+
 # Hosts are removed and added in the previous step. Do a refresh again.
+ceph orch rm rgw.foo
 ceph orch device ls --refresh
+ceph orch ps --refresh
 sleep 10
 ceph orch device ls --format=json | tee cypress/fixtures/orchestrator/inventory.json
+ceph orch ps --format=json | tee cypress/fixtures/orchestrator/services.json
 
 cypress_run "orchestrator/02-hosts-inventory.e2e-spec.ts"
 cypress_run "orchestrator/03-inventory.e2e-spec.ts"
index aeb4b437428f1b639d0bba68d6a01b7ef3294d10..c822cb503136d5a22f63e2ea52ca142b06ada1d5 100644 (file)
@@ -274,10 +274,11 @@ class Host(RESTController):
     @raise_if_no_orchestrator([OrchFeature.HOST_LIST, OrchFeature.HOST_CREATE])
     @handle_orchestrator_error('host')
     @host_task('create', {'hostname': '{hostname}'})
-    def create(self, hostname):  # pragma: no cover - requires realtime env
+    def create(self, hostname: str,
+               status: Optional[str] = None):  # pragma: no cover - requires realtime env
         orch_client = OrchClient.instance()
         self._check_orchestrator_host_op(orch_client, hostname, True)
-        orch_client.hosts.add(hostname)
+        orch_client.hosts.add(hostname, status)
     create._cp_config = {'tools.json_in.force': False}  # pylint: disable=W0212
 
     @raise_if_no_orchestrator([OrchFeature.HOST_LIST, OrchFeature.HOST_DELETE])
diff --git a/src/pybind/mgr/dashboard/frontend/cypress/fixtures/orchestrator/services.json b/src/pybind/mgr/dashboard/frontend/cypress/fixtures/orchestrator/services.json
new file mode 100644 (file)
index 0000000..433da1f
--- /dev/null
@@ -0,0 +1,523 @@
+[
+    {
+        "container_id": "9fa324d32bc8",
+        "container_image_digests": [
+            "docker.io/prom/alertmanager@sha256:7e4e9f7a0954b45736d149c40e9620a6664036bb05f0dce447bef5042b139f5d",
+            "docker.io/prom/alertmanager@sha256:b9323917a2eda265bec69e59a457f001c529facbbc8166df277f4850cdac61a0"
+        ],
+        "container_image_id": "0881eb8f169f5556a292b4e2c01d683172b12830a62a9225a98a8e206bb734f0",
+        "container_image_name": "docker.io/prom/alertmanager:v0.20.0",
+        "created": "2021-04-04T14:20:55.872521Z",
+        "daemon_id": "ceph-node-00",
+        "daemon_type": "alertmanager",
+        "events": [
+            "2021-04-04T14:20:55.970128Z daemon:alertmanager.ceph-node-00 [INFO] \"Deployed alertmanager.ceph-node-00 on host 'ceph-node-00.cephlab.com'\"",
+            "2021-04-04T14:25:37.637716Z daemon:alertmanager.ceph-node-00 [INFO] \"Reconfigured alertmanager.ceph-node-00 on host 'ceph-node-00.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-00.cephlab.com",
+        "is_active": true,
+        "last_refresh": "2021-04-04T14:27:38.610198Z",
+        "memory_usage": 10471079,
+        "ports": [
+            9093,
+            9094
+        ],
+        "started": "2021-04-04T14:25:36.837872Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "0.20.0"
+    },
+    {
+        "container_id": "44add59a53bc",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4",
+        "created": "2021-04-04T14:21:00.330646Z",
+        "daemon_id": "ceph-node-00",
+        "daemon_type": "crash",
+        "events": [
+            "2021-04-04T14:21:00.456022Z daemon:crash.ceph-node-00 [INFO] \"Deployed crash.ceph-node-00 on host 'ceph-node-00.cephlab.com'\"",
+            "2021-04-04T14:25:41.234986Z daemon:crash.ceph-node-00 [INFO] \"Reconfigured crash.ceph-node-00 on host 'ceph-node-00.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-00.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:38.610356Z",
+        "memory_usage": 7190085,
+        "ports": [],
+        "started": "2021-04-04T14:20:59.550334Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "4a2180e2e4ae",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4",
+        "created": "2021-04-04T14:24:23.552501Z",
+        "daemon_id": "ceph-node-01",
+        "daemon_type": "crash",
+        "events": [
+            "2021-04-04T14:24:23.591035Z daemon:crash.ceph-node-01 [INFO] \"Deployed crash.ceph-node-01 on host 'ceph-node-01.cephlab.com'\"",
+            "2021-04-04T14:25:42.677262Z daemon:crash.ceph-node-01 [INFO] \"Reconfigured crash.ceph-node-01 on host 'ceph-node-01.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-01.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:26:25.839645Z",
+        "memory_usage": 7147094,
+        "ports": [],
+        "started": "2021-04-04T14:24:23.188059Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "2eb2f0a13f46",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4",
+        "created": "2021-04-04T14:24:21.012014Z",
+        "daemon_id": "ceph-node-02",
+        "daemon_type": "crash",
+        "events": [
+            "2021-04-04T14:24:21.047797Z daemon:crash.ceph-node-02 [INFO] \"Deployed crash.ceph-node-02 on host 'ceph-node-02.cephlab.com'\"",
+            "2021-04-04T14:25:43.974052Z daemon:crash.ceph-node-02 [INFO] \"Reconfigured crash.ceph-node-02 on host 'ceph-node-02.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-02.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:37.470841Z",
+        "memory_usage": 8018460,
+        "ports": [],
+        "started": "2021-04-04T14:24:20.664558Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "10359b995638",
+        "container_image_digests": [
+            "docker.io/ceph/ceph-grafana@sha256:44f6f2bfa52724d4db9a2ce343b299ff70a18dc21f1420548d5643df4ee18a6b"
+        ],
+        "container_image_id": "80728b29ad3f603cb306daeb6b0fb6c4c388e29e7eaac82cd3d3582ffd96b931",
+        "container_image_name": "docker.io/ceph/ceph-grafana:6.7.4",
+        "created": "2021-04-04T14:21:41.602878Z",
+        "daemon_id": "ceph-node-00",
+        "daemon_type": "grafana",
+        "events": [
+            "2021-04-04T14:21:41.651390Z daemon:grafana.ceph-node-00 [INFO] \"Deployed grafana.ceph-node-00 on host 'ceph-node-00.cephlab.com'\"",
+            "2021-04-04T14:25:26.705257Z daemon:grafana.ceph-node-00 [INFO] \"Reconfigured grafana.ceph-node-00 on host 'ceph-node-00.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-00.cephlab.com",
+        "is_active": true,
+        "last_refresh": "2021-04-04T14:27:38.609816Z",
+        "memory_usage": 27797749,
+        "ports": [
+            3000
+        ],
+        "started": "2021-04-04T14:25:26.020123Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "6.7.4"
+    },
+    {
+        "container_id": "04e86dfde3ae",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph:master",
+        "created": "2021-04-04T14:17:17.458301Z",
+        "daemon_id": "ceph-node-00.cephlab.com.qqwcpr",
+        "daemon_type": "mgr",
+        "events": [
+            "2021-04-04T14:25:24.076974Z daemon:mgr.ceph-node-00.cephlab.com.qqwcpr [ERROR] \"\"",
+            "2021-04-04T14:25:39.425312Z daemon:mgr.ceph-node-00.cephlab.com.qqwcpr [INFO] \"Reconfigured mgr.ceph-node-00.cephlab.com.qqwcpr on host 'ceph-node-00.cephlab.com'\""
+        ],
+        "hostname": "",
+        "is_active": true,
+        "last_refresh": "2021-04-04T14:20:21.353502Z",
+        "memory_usage": 411670937,
+        "ports": [
+            9283
+        ],
+        "started": "2021-04-04T14:17:16.779682Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "04e86dfde3ae",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph:master",
+        "created": "2021-04-04T14:17:17.458301Z",
+        "daemon_id": "ceph-node-00.cephlab.com.qqwcpr",
+        "daemon_type": "mgr",
+        "events": [
+            "2021-04-04T14:25:24.076974Z daemon:mgr.ceph-node-00.cephlab.com.qqwcpr [ERROR] \"\"",
+            "2021-04-04T14:25:39.425312Z daemon:mgr.ceph-node-00.cephlab.com.qqwcpr [INFO] \"Reconfigured mgr.ceph-node-00.cephlab.com.qqwcpr on host 'ceph-node-00.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-00.cephlab.com",
+        "is_active": true,
+        "last_refresh": "2021-04-04T14:27:38.610265Z",
+        "memory_usage": 468608614,
+        "ports": [
+            9283
+        ],
+        "started": "2021-04-04T14:17:16.779682Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "7bfba45507ab",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4",
+        "created": "2021-04-04T14:24:25.445135Z",
+        "daemon_id": "ceph-node-02.mywsmi",
+        "daemon_type": "mgr",
+        "events": [
+            "2021-04-04T14:24:25.484361Z daemon:mgr.ceph-node-02.mywsmi [INFO] \"Deployed mgr.ceph-node-02.mywsmi on host 'ceph-node-02.cephlab.com'\"",
+            "2021-04-04T14:25:46.457476Z daemon:mgr.ceph-node-02.mywsmi [INFO] \"Reconfigured mgr.ceph-node-02.mywsmi on host 'ceph-node-02.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-02.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:37.471837Z",
+        "memory_usage": 384617676,
+        "ports": [
+            8443,
+            9283
+        ],
+        "started": "2021-04-04T14:24:25.142998Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "6045be766e88",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph:master",
+        "created": "2021-04-04T14:17:07.904023Z",
+        "daemon_id": "ceph-node-00.cephlab.com",
+        "daemon_type": "mon",
+        "events": [
+            "2021-04-04T14:25:24.076865Z daemon:mon.ceph-node-00.cephlab.com [ERROR] \"\"",
+            "2021-04-04T14:25:28.250425Z daemon:mon.ceph-node-00.cephlab.com [INFO] \"Reconfigured mon.ceph-node-00.cephlab.com on host 'ceph-node-00.cephlab.com'\""
+        ],
+        "hostname": "",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:20:21.353077Z",
+        "memory_usage": 35871784,
+        "ports": [],
+        "started": "2021-04-04T14:17:13.608122Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "6045be766e88",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph:master",
+        "created": "2021-04-04T14:17:07.904023Z",
+        "daemon_id": "ceph-node-00.cephlab.com",
+        "daemon_type": "mon",
+        "events": [
+            "2021-04-04T14:25:24.076865Z daemon:mon.ceph-node-00.cephlab.com [ERROR] \"\"",
+            "2021-04-04T14:25:28.250425Z daemon:mon.ceph-node-00.cephlab.com [INFO] \"Reconfigured mon.ceph-node-00.cephlab.com on host 'ceph-node-00.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-00.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:38.609967Z",
+        "memory_usage": 74826383,
+        "ports": [],
+        "started": "2021-04-04T14:17:13.608122Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "d2d261f4eb17",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4",
+        "created": "2021-04-04T14:24:28.269212Z",
+        "daemon_id": "ceph-node-02",
+        "daemon_type": "mon",
+        "events": [
+            "2021-04-04T14:24:28.314782Z daemon:mon.ceph-node-02 [INFO] \"Deployed mon.ceph-node-02 on host 'ceph-node-02.cephlab.com'\"",
+            "2021-04-04T14:25:45.448194Z daemon:mon.ceph-node-02 [INFO] \"Reconfigured mon.ceph-node-02 on host 'ceph-node-02.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-02.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:37.471665Z",
+        "memory_usage": 65515028,
+        "ports": [],
+        "started": "2021-04-04T14:24:28.147109Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "51c04231de4c",
+        "container_image_digests": [
+            "docker.io/prom/node-exporter@sha256:a2f29256e53cc3e0b64d7a472512600b2e9410347d53cdc85b49f659c17e02ee",
+            "docker.io/prom/node-exporter@sha256:b630fb29d99b3483c73a2a7db5fc01a967392a3d7ad754c8eccf9f4a67e7ee31"
+        ],
+        "container_image_id": "e5a616e4b9cf68dfcad7782b78e118be4310022e874d52da85c55923fb615f87",
+        "container_image_name": "docker.io/prom/node-exporter:v0.18.1",
+        "created": "2021-04-04T14:21:52.336199Z",
+        "daemon_id": "ceph-node-00",
+        "daemon_type": "node-exporter",
+        "events": [
+            "2021-04-04T14:21:52.372374Z daemon:node-exporter.ceph-node-00 [INFO] \"Deployed node-exporter.ceph-node-00 on host 'ceph-node-00.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-00.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:38.610044Z",
+        "memory_usage": 8001683,
+        "ports": [
+            9100
+        ],
+        "started": "2021-04-04T14:21:52.044759Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "0.18.1"
+    },
+    {
+        "container_id": "ac9e1d055972",
+        "container_image_digests": [
+            "docker.io/prom/node-exporter@sha256:a2f29256e53cc3e0b64d7a472512600b2e9410347d53cdc85b49f659c17e02ee",
+            "docker.io/prom/node-exporter@sha256:b630fb29d99b3483c73a2a7db5fc01a967392a3d7ad754c8eccf9f4a67e7ee31"
+        ],
+        "container_image_id": "e5a616e4b9cf68dfcad7782b78e118be4310022e874d52da85c55923fb615f87",
+        "container_image_name": "docker.io/prom/node-exporter:v0.18.1",
+        "created": "2021-04-04T14:24:39.469923Z",
+        "daemon_id": "ceph-node-01",
+        "daemon_type": "node-exporter",
+        "events": [
+            "2021-04-04T14:24:39.508244Z daemon:node-exporter.ceph-node-01 [INFO] \"Deployed node-exporter.ceph-node-01 on host 'ceph-node-01.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-01.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:26:25.839072Z",
+        "memory_usage": 7052722,
+        "ports": [
+            9100
+        ],
+        "started": "2021-04-04T14:24:39.156587Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "0.18.1"
+    },
+    {
+        "container_id": "b133dbf9cff8",
+        "container_image_digests": [
+            "docker.io/prom/node-exporter@sha256:a2f29256e53cc3e0b64d7a472512600b2e9410347d53cdc85b49f659c17e02ee",
+            "docker.io/prom/node-exporter@sha256:b630fb29d99b3483c73a2a7db5fc01a967392a3d7ad754c8eccf9f4a67e7ee31"
+        ],
+        "container_image_id": "e5a616e4b9cf68dfcad7782b78e118be4310022e874d52da85c55923fb615f87",
+        "container_image_name": "docker.io/prom/node-exporter:v0.18.1",
+        "created": "2021-04-04T14:24:49.840797Z",
+        "daemon_id": "ceph-node-02",
+        "daemon_type": "node-exporter",
+        "events": [
+            "2021-04-04T14:24:49.901437Z daemon:node-exporter.ceph-node-02 [INFO] \"Deployed node-exporter.ceph-node-02 on host 'ceph-node-02.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-02.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:37.471349Z",
+        "memory_usage": 7696547,
+        "ports": [
+            9100
+        ],
+        "started": "2021-04-04T14:24:49.524299Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "0.18.1"
+    },
+    {
+        "container_id": "51d864a583df",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4",
+        "created": "2021-04-04T14:25:03.086634Z",
+        "daemon_id": "0",
+        "daemon_type": "osd",
+        "events": [
+            "2021-04-04T14:25:03.152770Z daemon:osd.0 [INFO] \"Deployed osd.0 on host 'ceph-node-00.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-00.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:38.610426Z",
+        "memory_usage": 63826821,
+        "osdspec_affinity": "all-available-devices",
+        "ports": [],
+        "started": "2021-04-04T14:25:02.948826Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "7a141557611e",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4",
+        "created": "2021-04-04T14:25:02.803534Z",
+        "daemon_id": "1",
+        "daemon_type": "osd",
+        "events": [
+            "2021-04-04T14:25:02.905863Z daemon:osd.1 [INFO] \"Deployed osd.1 on host 'ceph-node-01.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-01.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:26:25.839343Z",
+        "memory_usage": 44155535,
+        "osdspec_affinity": "all-available-devices",
+        "ports": [],
+        "started": "2021-04-04T14:25:02.650699Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "bbf4cc5b870a",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4",
+        "created": "2021-04-04T14:25:03.771174Z",
+        "daemon_id": "2",
+        "daemon_type": "osd",
+        "events": [
+            "2021-04-04T14:25:03.827365Z daemon:osd.2 [INFO] \"Deployed osd.2 on host 'ceph-node-02.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-02.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:37.471996Z",
+        "memory_usage": 62495129,
+        "osdspec_affinity": "all-available-devices",
+        "ports": [],
+        "started": "2021-04-04T14:25:08.134780Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "e36d84e5608b",
+        "container_image_digests": [
+            "docker.io/prom/prometheus@sha256:5880ec936055fad18ccee798d2a63f64ed85bd28e8e0af17c6923a090b686c3d",
+            "docker.io/prom/prometheus@sha256:b4e6cd0275a26750505e539f8528e891053434ebd3972be02645bed5f02f0795"
+        ],
+        "container_image_id": "de242295e2257c37c8cadfd962369228f8f10b2d48a44259b65fef44ad4f6490",
+        "container_image_name": "docker.io/prom/prometheus:v2.18.1",
+        "created": "2021-04-04T14:22:11.310763Z",
+        "daemon_id": "ceph-node-00",
+        "daemon_type": "prometheus",
+        "events": [
+            "2021-04-04T14:22:11.356043Z daemon:prometheus.ceph-node-00 [INFO] \"Deployed prometheus.ceph-node-00 on host 'ceph-node-00.cephlab.com'\"",
+            "2021-04-04T14:25:33.086106Z daemon:prometheus.ceph-node-00 [INFO] \"Reconfigured prometheus.ceph-node-00 on host 'ceph-node-00.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-00.cephlab.com",
+        "is_active": true,
+        "last_refresh": "2021-04-04T14:27:38.610128Z",
+        "memory_usage": 27724349,
+        "ports": [
+            9095
+        ],
+        "started": "2021-04-04T14:25:32.344156Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "2.18.1"
+    },
+    {
+        "container_id": "5cdeb705c7f6",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4",
+        "created": "2021-04-04T14:27:26.775628Z",
+        "daemon_id": "foo.ceph-node-00.qknfoh",
+        "daemon_type": "rgw",
+        "events": [
+            "2021-04-04T14:27:26.824821Z daemon:rgw.foo.ceph-node-00.qknfoh [INFO] \"Deployed rgw.foo.ceph-node-00.qknfoh on host 'ceph-node-00.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-00.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:38.610617Z",
+        "memory_usage": 53309603,
+        "ports": [
+            80
+        ],
+        "started": "2021-04-04T14:27:26.350981Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_id": "18a2179a35c0",
+        "container_image_digests": [
+            "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4"
+        ],
+        "container_image_id": "f72dfde44435bedf5e4c8be05c8194cc57f5f654b9bb146b73e81f1c5358b4c5",
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4",
+        "created": "2021-04-04T14:27:24.200977Z",
+        "daemon_id": "foo.ceph-node-02.fgzmmm",
+        "daemon_type": "rgw",
+        "events": [
+            "2021-04-04T14:27:24.300473Z daemon:rgw.foo.ceph-node-02.fgzmmm [INFO] \"Deployed rgw.foo.ceph-node-02.fgzmmm on host 'ceph-node-02.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-02.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:37.471149Z",
+        "memory_usage": 53487861,
+        "ports": [
+            80
+        ],
+        "started": "2021-04-04T14:27:23.793957Z",
+        "status": 1,
+        "status_desc": "running",
+        "version": "17.0.0-2786-g7fb0569e"
+    },
+    {
+        "container_image_name": "quay.ceph.io/ceph-ci/ceph@sha256:cfd9dc4a437e11894a9a0d930ed1221ccc4e939b943981f6dfbdc611816904d4",
+        "created": "2021-04-04T14:27:30.048136Z",
+        "daemon_id": "foo.ceph-node-02.hqjyla",
+        "daemon_type": "rgw",
+        "events": [
+            "2021-04-04T14:27:30.115692Z daemon:rgw.foo.ceph-node-02.hqjyla [INFO] \"Deployed rgw.foo.ceph-node-02.hqjyla on host 'ceph-node-02.cephlab.com'\""
+        ],
+        "hostname": "ceph-node-02.cephlab.com",
+        "is_active": false,
+        "last_refresh": "2021-04-04T14:27:37.471564Z",
+        "ports": [
+            80
+        ],
+        "status": -1,
+        "status_desc": "unknown"
+    }
+]
\ No newline at end of file
index 0785f5107274fe1140c5a54fcf21d85106a2560f..160242d82b04ea6fd70fd90b5a82770ffa1daf74 100644 (file)
@@ -120,41 +120,51 @@ export class HostsPageHelper extends PageHelper {
   }
 
   @PageHelper.restrictTo(pages.index.url)
-  maintenance(hostname: string, exit = false) {
-    let services: string[];
-    let runTest = false;
-    this.getTableCell(this.columnIndex.hostname, hostname)
-      .parent()
-      .find(`datatable-body-cell:nth-child(${this.columnIndex.services}) a`)
-      .should(($el) => {
-        services = $el.text().split(', ');
-        if (services.length < 2 && services[0].includes('osd')) {
-          runTest = true;
-        }
-      });
-    if (runTest) {
+  maintenance(hostname: string, exit = false, force = false) {
+    if (force) {
       this.getTableCell(this.columnIndex.hostname, hostname).click();
-      if (exit) {
-        this.clickActionButton('exit-maintenance');
-
-        this.getTableCell(this.columnIndex.hostname, hostname)
-          .parent()
-          .find(`datatable-body-cell:nth-child(${this.columnIndex.status}) .badge`)
-          .should(($ele) => {
-            const status = $ele.toArray().map((v) => v.innerText);
-            expect(status).to.not.include('maintenance');
-          });
-      } else {
-        this.clickActionButton('enter-maintenance');
-
-        this.getTableCell(this.columnIndex.hostname, hostname)
-          .parent()
-          .find(`datatable-body-cell:nth-child(${this.columnIndex.status}) .badge`)
-          .should(($ele) => {
-            const status = $ele.toArray().map((v) => v.innerText);
-            expect(status).to.include('maintenance');
-          });
-      }
+      this.clickActionButton('enter-maintenance');
+
+      cy.contains('cd-modal button', 'Continue').click();
+
+      this.getTableCell(this.columnIndex.hostname, hostname)
+        .parent()
+        .find(`datatable-body-cell:nth-child(${this.columnIndex.status}) .badge`)
+        .should(($ele) => {
+          const status = $ele.toArray().map((v) => v.innerText);
+          expect(status).to.include('maintenance');
+        });
+    }
+    if (exit) {
+      this.getTableCell(this.columnIndex.hostname, hostname)
+        .click()
+        .parent()
+        .find(`datatable-body-cell:nth-child(${this.columnIndex.status})`)
+        .then(($ele) => {
+          const status = $ele.toArray().map((v) => v.innerText);
+          if (status[0].includes('maintenance')) {
+            this.clickActionButton('exit-maintenance');
+          }
+        });
+
+      this.getTableCell(this.columnIndex.hostname, hostname)
+        .parent()
+        .find(`datatable-body-cell:nth-child(${this.columnIndex.status})`)
+        .should(($ele) => {
+          const status = $ele.toArray().map((v) => v.innerText);
+          expect(status).to.not.include('maintenance');
+        });
+    } else {
+      this.getTableCell(this.columnIndex.hostname, hostname).click();
+      this.clickActionButton('enter-maintenance');
+
+      this.getTableCell(this.columnIndex.hostname, hostname)
+        .parent()
+        .find(`datatable-body-cell:nth-child(${this.columnIndex.status}) .badge`)
+        .should(($ele) => {
+          const status = $ele.toArray().map((v) => v.innerText);
+          expect(status).to.include('maintenance');
+        });
     }
   }
 }
diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/01-hosts-force-maintenance.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/01-hosts-force-maintenance.e2e-spec.ts
new file mode 100644 (file)
index 0000000..ac00e2f
--- /dev/null
@@ -0,0 +1,39 @@
+import { HostsPageHelper } from '../cluster/hosts.po';
+
+describe('Hosts page', () => {
+  const hosts = new HostsPageHelper();
+
+  beforeEach(() => {
+    cy.login();
+    Cypress.Cookies.preserveOnce('token');
+    hosts.navigateTo();
+  });
+
+  describe('when Orchestrator is available', () => {
+    beforeEach(function () {
+      cy.fixture('orchestrator/inventory.json').as('hosts');
+      cy.fixture('orchestrator/services.json').as('services');
+    });
+
+    it('should force enter host into maintenance', function () {
+      const hostname = Cypress._.sample(this.hosts).name;
+      const serviceList = new Array();
+      this.services.forEach((service: any) => {
+        if (hostname === service.hostname) {
+          serviceList.push(service.daemon_type);
+        }
+      });
+
+      let enterMaintenance = true;
+      serviceList.forEach((service: string) => {
+        if (service === 'mgr' || service === 'alertmanager') {
+          enterMaintenance = false;
+        }
+      });
+
+      if (enterMaintenance) {
+        hosts.maintenance(hostname, true, true);
+      }
+    });
+  });
+});
index 473ca2c55f3339fd0a9d88bebecbd7f74448f8b0..46bb1fea89e11817b771ab328be236e8c0fe23ae 100644 (file)
@@ -12,6 +12,7 @@ describe('Hosts page', () => {
   describe('when Orchestrator is available', () => {
     beforeEach(function () {
       cy.fixture('orchestrator/inventory.json').as('hosts');
+      cy.fixture('orchestrator/services.json').as('services');
     });
 
     it('should not add an exsiting host', function () {
@@ -57,7 +58,21 @@ describe('Hosts page', () => {
 
     it('should enter host into maintenance', function () {
       const hostname = Cypress._.sample(this.hosts).name;
-      hosts.maintenance(hostname);
+      const serviceList = new Array();
+      this.services.forEach((service: any) => {
+        if (hostname === service.hostname) {
+          serviceList.push(service.daemon_type);
+        }
+      });
+      let enterMaintenance = true;
+      serviceList.forEach((service: string) => {
+        if (service === 'mgr' || service === 'alertmanager') {
+          enterMaintenance = false;
+        }
+      });
+      if (enterMaintenance) {
+        hosts.maintenance(hostname);
+      }
     });
 
     it('should exit host from maintenance', function () {
index 0bb3fb8dbfda9bf5b7588dfa11e9a73d0ff8a099..ef7c293ea3f43e7954425963e7be898e2e9fddc0 100644 (file)
                   i18n>The chosen hostname is already in use.</span>
           </div>
         </div>
+
+        <!-- Maintenance Mode -->
+        <div class="form-group row">
+          <div class="cd-col-form-offset">
+            <div class="custom-control custom-checkbox">
+              <input class="custom-control-input"
+                     id="maintenance"
+                     type="checkbox"
+                     formControlName="maintenance">
+              <label class="custom-control-label"
+                     for="maintenance"
+                     i18n>Maintenance Mode</label>
+            </div>
+          </div>
+        </div>
       </div>
 
       <div class="card-footer">
index f47f72d1c209bf8a099f96c50597939b2c7399be..d9135197e85aa61191b832d5bedf6815f92b2459 100644 (file)
@@ -37,4 +37,11 @@ describe('HostFormComponent', () => {
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+
+  it('should select maintenance mode', () => {
+    component.hostForm.get('maintenance').setValue('maintenance');
+    fixture.detectChanges();
+    component.submit();
+    expect(component.status).toBe('maintenance');
+  });
 });
index 04b6d82ca0c89631ad33d1e8398f689cc9ca964c..e9e51c3e1ebbc10631c530c56776106a6189a608 100644 (file)
@@ -20,6 +20,7 @@ export class HostFormComponent extends CdForm implements OnInit {
   action: string;
   resource: string;
   hostnames: string[];
+  status: string;
 
   constructor(
     private router: Router,
@@ -51,18 +52,20 @@ export class HostFormComponent extends CdForm implements OnInit {
             return this.hostnames && this.hostnames.indexOf(hostname) !== -1;
           })
         ]
-      })
+      }),
+      maintenance: new FormControl(false)
     });
   }
 
   submit() {
     const hostname = this.hostForm.get('hostname').value;
+    this.status = this.hostForm.get('maintenance').value ? 'maintenance' : '';
     this.taskWrapper
       .wrapTaskAroundCall({
         task: new FinishedTask('host/' + URLVerbs.CREATE, {
           hostname: hostname
         }),
-        call: this.hostService.create(hostname)
+        call: this.hostService.create(hostname, this.status)
       })
       .subscribe({
         error: () => {
index 82e85965b39a8a34ad109719ee46db9457d42c85..c92188ed054114173bd6733ec855d6cdea4fce55 100644 (file)
@@ -24,11 +24,26 @@ import {
 } from '~/testing/unit-test-helper';
 import { HostsComponent } from './hosts.component';
 
+class MockShowForceMaintenanceModal {
+  showModal = false;
+  showModalDialog(msg: string) {
+    if (
+      msg.includes('WARNING') &&
+      !msg.includes('It is NOT safe to stop') &&
+      !msg.includes('ALERT') &&
+      !msg.includes('unable to stop')
+    ) {
+      this.showModal = true;
+    }
+  }
+}
+
 describe('HostsComponent', () => {
   let component: HostsComponent;
   let fixture: ComponentFixture<HostsComponent>;
   let hostListSpy: jasmine.Spy;
   let orchService: OrchestratorService;
+  let showForceMaintenanceModal: MockShowForceMaintenanceModal;
 
   const fakeAuthStorageService = {
     getPermissions: () => {
@@ -54,6 +69,7 @@ describe('HostsComponent', () => {
   });
 
   beforeEach(() => {
+    showForceMaintenanceModal = new MockShowForceMaintenanceModal();
     fixture = TestBed.createComponent(HostsComponent);
     component = fixture.componentInstance;
     hostListSpy = spyOn(TestBed.inject(HostService), 'list');
@@ -102,6 +118,37 @@ describe('HostsComponent', () => {
     });
   });
 
+  it('should show force maintenance modal when it is safe to stop host', () => {
+    const errorMsg = `WARNING: Stopping 1 out of 1 daemons in Grafana service.
+                    Service will not be operational with no daemons left. At
+                    least 1 daemon must be running to guarantee service.`;
+    showForceMaintenanceModal.showModalDialog(errorMsg);
+    expect(showForceMaintenanceModal.showModal).toBeTruthy();
+  });
+
+  it('should not show force maintenance modal when error is an ALERT', () => {
+    const errorMsg = `ALERT: Cannot stop active Mgr daemon, Please switch active Mgrs
+                    with 'ceph mgr fail ceph-node-00'`;
+    showForceMaintenanceModal.showModalDialog(errorMsg);
+    expect(showForceMaintenanceModal.showModal).toBeFalsy();
+  });
+
+  it('should not show force maintenance modal when it is not safe to stop host', () => {
+    const errorMsg = `WARNING: Stopping 1 out of 1 daemons in Grafana service.
+                    Service will not be operational with no daemons left. At
+                    least 1 daemon must be running to guarantee service.
+                    It is NOT safe to stop ['mon.ceph-node-00']: not enough
+                    monitors would be available (ceph-node-02) after stopping mons`;
+    showForceMaintenanceModal.showModalDialog(errorMsg);
+    expect(showForceMaintenanceModal.showModal).toBeFalsy();
+  });
+
+  it('should not show force maintenance modal when it is unable to stop host', () => {
+    const errorMsg = 'unable to stop osd.0 because of some unknown reason';
+    showForceMaintenanceModal.showModalDialog(errorMsg);
+    expect(showForceMaintenanceModal.showModal).toBeFalsy();
+  });
+
   describe('table actions', () => {
     const fakeHosts = require('./fixtures/host_list_response.json');
 
index 640d39d1fdd532fdb82e3ec8170dce95e57d053f..e4f042699eb39d396b45d6dbbbc3c8e2766b09f3 100644 (file)
@@ -246,7 +246,8 @@ export class HostsComponent extends ListWithDetails implements OnInit {
           if (
             error.error['detail'].includes('WARNING') &&
             !error.error['detail'].includes('It is NOT safe to stop') &&
-            !error.error['detail'].includes('ALERT')
+            !error.error['detail'].includes('ALERT') &&
+            !error.error['detail'].includes('unable to stop')
           ) {
             const modalVarialbes = {
               titleText: $localize`Warning`,
index 74c0c30d449678c69fcfa01180350abefe5edfc2..ba2b4aded7efa282ceae545374a493ebdbc524f3 100644 (file)
@@ -25,8 +25,12 @@ export class HostService {
     return this.http.get<object[]>(this.baseURL);
   }
 
-  create(hostname: string) {
-    return this.http.post(this.baseURL, { hostname: hostname }, { observe: 'response' });
+  create(hostname: string, status: string) {
+    return this.http.post(
+      this.baseURL,
+      { hostname: hostname, status: status },
+      { observe: 'response' }
+    );
   }
 
   delete(hostname: string) {
index d0f489c197b8f45cbc2920402a4cb1d88952c71f..ba2b26bf0dbe8284759280498a8aae113df43c84 100644 (file)
@@ -3241,6 +3241,8 @@ paths:
               properties:
                 hostname:
                   type: string
+                status:
+                  type: string
               required:
               - hostname
               type: object
index 1b472932c933cfac7721cff9f7091bcf7bb9d01e..7dfdfc2920f83d77f48cab6093530c10a82b0a40 100644 (file)
@@ -64,8 +64,8 @@ class HostManger(ResourceManager):
         return hosts[0] if hosts else None
 
     @wait_api_result
-    def add(self, hostname: str):
-        return self.api.add_host(HostSpec(hostname))
+    def add(self, hostname: str, status: str):
+        return self.api.add_host(HostSpec(hostname, status=status))
 
     @wait_api_result
     def remove(self, hostname: str):